簡體   English   中英

將多維std :: vector排序為單個向量

[英]sort multidimensional std::vector as single 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

std::vector保證連續存儲元素。 但是,向量不僅僅包含其元素。 因此,如果您在一個內部向量的邊界上進行迭代,則不會最終到達下一個內部向量的第一個元素。 取而代之的是,您將遇到任何一個向量的(私有)成員之一。

為了解決您的問題,例如,您可以編寫一個自定義迭代器,並將其傳遞給std::sort std::sort需要一個隨機訪問迭代器 假設您的內部向量始終具有相同的長度( 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 一個迭代外部向量,另一個迭代第一迭代器指向的內部向量。

我認為您可以使用以下方式:

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;

如果我對您的內部向量排序后正確理解了您的知識,則可以按第一個值對它們進行排序。

解決方案的問題是,您假設不僅虛空子是連續的,而且還假設它們的所有元素,但是您所知道的錯誤是所有矢量的元素都是連續的,並且矢量對象的矢量(例如,在內存vec:| v1 |中)是錯誤的。 v2 | ... | vn |)是連續的,但不是所有子向量的所有元素。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM