将多维std :: vector排序为单个向量

时间:2015-04-11 09:00:42

标签: c++ arrays multidimensional-array vector

有没有办法对多维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

2 个答案:

答案 0 :(得分:2)

std::vector保证不断存储元素。但是,矢量不仅包含其元素。因此,如果迭代其中一个内部向量的边界,则不会最终出现在下一个内向量的第一个元素上。相反,你最终会选择其中一个向量的(私人)成员。

要解决您的问题,您可以编写一个自定义迭代器,您可以将其传递给std::sortstd::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 |)是连续的,但不是所有子向量的所有元素。