有没有办法对多维std :: vector进行排序:
std::vector<std::vector<int> > vec = { {3,1,2}, {5,4,6} };
结果:{{1,2,3},{4,5,6}}
没有创建另一个临时向量?
我认为,我需要将多维std :: vector视为简单的向量,类似于:
int* begin = &vec[0][0];
int* end = ....
std::sort(begin, end);
如果所有元素都连续地位于内存中,并且如果我正确理解std :: vector,我只需要指向第一个元素和最后一个元素。为了检查这个想法,我创建了简单的测试 - 从多维向量打印所有元素而没有嵌套循环。但测试返回了错误的结果。
std::vector<std::vector<int> > vec(10);
for(int i = 0; i < vec.size(); ++i)
{
std::vector<int> tmp(1);
tmp[0] = i;
vec[i] = tmp;
}
int* a = &vec[0][0];
for(int i = 0; i < vec.size(); i++) {
std::cout << *a << " ";
++a;
}
std::cout << std::endl;
0 0 0 0 0 0 33 0 1 0
答案 0 :(得分:2)
std::vector
保证不断存储元素。但是,矢量不仅包含其元素。因此,如果迭代其中一个内部向量的边界,则不会最终出现在下一个内向量的第一个元素上。相反,你最终会选择其中一个向量的(私人)成员。
要解决您的问题,您可以编写一个自定义迭代器,您可以将其传递给std::sort
。 std::sort
需要random access iterator。假设你的内部向量总是具有相同的长度(3
),这样的迭代器实现可能看起来像这样:
struct myiter
{
myiter() : m_vec(NULL), m_idx(0) {}
myiter(std::vector<std::vector<int>>& vec, int idx=0) : m_vec(&vec), m_idx(idx) {}
myiter(myiter& other) : m_vec(other.m_vec), m_idx(other.m_idx) {}
myiter& operator++()
{
m_idx++;
return *this;
}
myiter& operator++(int)
{
myiter& self = *this;
m_idx++;
return self;
}
myiter& operator--()
{
m_idx--;
return *this;
}
myiter& operator--(int)
{
myiter& self = *this;
m_idx--;
return self;
}
myiter operator + (int n) const
{
return myiter(*m_vec, m_idx+n);
}
myiter operator - (int n) const
{
return myiter(*m_vec, m_idx-n);
}
int operator - (myiter rhs) const
{
if (m_vec != rhs.m_vec) throw std::exception("incompatible iterators");
return m_idx-rhs.m_idx;
}
int& operator*()
{
return (*m_vec)[m_idx/3][m_idx%3];
}
bool operator == (const myiter& rhs) const
{
return (m_vec == rhs.m_vec && m_idx == rhs.m_idx);
}
bool operator != (const myiter& rhs) const
{
return !operator==(rhs);
}
bool operator < (const myiter& rhs) const
{
if (m_vec != rhs.m_vec) throw std::exception("incompatible iterators");
return m_idx<rhs.m_idx;
}
std::vector<std::vector<int>>* m_vec;
int m_idx;
};
template<>
struct std::iterator_traits<myiter> {
typedef int difference_type;
typedef int value_type;
typedef int& reference;
typedef int* pointer;
typedef std::random_access_iterator_tag iterator_category;
};
使用此迭代器,您可以使用std::sort
,如下所示:
std::sort(myiter(vec), myiter(vec,vec.size()*3));
如上所述,上面的迭代器实现假设你的内部向量总是大小为3.如果它们的大小不同,你可能想要存储两个迭代器而不是m_idx
。一个遍历外部向量,一个迭代第一个迭代器指向的内部向量。
答案 1 :(得分:0)
我认为你可以使用这样的东西:
std::for_each(std::begin(vec), std::end(vec), [](auto &v) { std::sort(std::begin(v), std::end(v));});
std::sort(std::begin(vec), std::end(vec), [](auto &v1, auto &v2) { return v1[0] < v2[0];});
std::cout << vec << std::endl;
如果我对你的内部向量进行排序后你能正确理解,你可以按第一个值排序。
你的解决方案的问题在于你不仅假设vactors是连续的而且还有它们的所有元素,但是你知道的是每个向量的元素是连续的并且是向量对象的向量(例如在内存vec中: | v1 | v2 | ... | vn |)是连续的,但不是所有子向量的所有元素。