C ++基于其他int数组排序

时间:2014-08-25 13:21:10

标签: c++ sorting vector

假设我有两个向量

std::vector<int>vec_int = {4,3,2,1,5};

std::vector<Obj*>vec_obj = {obj1,obj2,obj3,obj4,obj5};

我们如何根据排序的vec_int位置对vec_o​​bj进行排序? 所以目标可能如下:

std::vector<int>vec_int = {1,2,3,4,5};

std::vector<Obj*>vec_obj = {obj4,obj3,obj2,obj1,obj5};

我一直在尝试创建新的vec_array:

for (int i = 0; i < vec_int.size(); i++) {

    new_vec.push_back(vec_obj[vec_int[i]]);
}

但我认为这不是正确的解决方案。我们如何做到这一点?感谢

std库可能是最好的解决方案,但我无法找到正确的解决方案来实现std :: sort

4 个答案:

答案 0 :(得分:3)

您不必致电std::sort,您需要的是线性时间(假设指数从1到N而不是重复)

std::vector<Obj*> new_vec(vec_obj.size());
for (size_t i = 0; i < vec_int.size(); ++i) {
    new_vec[i] = vec_obj[vec_int[i] - 1];
}

但是,对于此解决方案,您需要额外的new_vec向量。

如果索引是任意的和/或您不想分配另一个向量,则必须使用不同的数据结构:

typedef pair<int, Obj*> Item;
vector<Item> vec = {{4, obj1}, {3, obj2}, {2, obj3}, {1, obj4}, {5, obj5}};
std::sort(vec.begin(), vec.end(), [](const Item& l, const Item& r) -> bool {return l.first < r.first;});

答案 1 :(得分:1)

也许有更好的解决方案,但我个人认为std::map中的项目会按键自动排序。这给出了以下可能性(未经测试!)

// The vectors have to be the same size for this to work!
if( vec_int.size() != vec_obj.size() ) { return 0; }

std::vector<int>::const_iterator intIt = vec_int.cbegin();
std::vector<Obj*>::const_iterator objIt = vec_obj.cbegin();

// Create a temporary map
std::map< int, Obj* > sorted_objects;
for(; intIt != vec_int.cend(); ++intIt, ++objIt )
{
    sorted_objects[ *intIt ] = *objIt;
}

// Iterating through map will be in order of key
//  so this adds the items to the vector in the desired order.
std::vector<Obj*> vec_obj_sorted;
for( std::map< int, Obj* >::const_iterator sortedIt = sorted_objects.cbegin();
  sortedIt != sorted_objects.cend(); ++sortedIt )
{
  vec_obj_sorted.push_back( sortedIt->second );
}

答案 2 :(得分:0)

[不确定这适合您的用例,但是将元素放入地图中会默认存储按键排序的元素。]

如果新问题的创建是个问题,你可以使用简单的交换技巧(如选择排序)来避免这种情况。

//Place ith element in its place, while swapping to its position the current element.
for (int i = 0; i < vec_int.size(); i++) {
    if (vec_obj[i] != vec_obj[vec_int[i])
        swap_elements(i,vec_obj[i],vec_obj[vec_int[i]])
}

答案 3 :(得分:0)

这种通用形式称为&#34;根据&#34;重新排序,这是循环排序的变体。与您的示例不同,索引向量需要的值为0到size-1,而不是{4,3,2,1,5},它需要是{3,2,1,0,4}(否则你必须调整下面的示例代码)。重新排序是通过根据&#34;循环&#34;旋转元素组来完成的。在索引向量或数组中。 (在我调整的例子中有3&#34;周期&#34;,第1周期:index [0] = 3,index [3] = 0.第2周期:index [1] = 2,index [2] = 1第3周期指数[4] = 4)。索引向量或数组也在过程中排序。如果要保留原始索引向量或数组,可以保存原始索引向量或数组的副本。根据模板形式的vI重新排序vA的示例代码:

template <class T>
void reorder(vector<T>& vA, vector<size_t>& vI)  
{
size_t i, j, k;
T t;
    for(i = 0; i < vA.size(); i++){
        if(i != vI[i]){
            t = vA[i];
            k = i;
            while(i != (j = vI[k])){
            // every move places a value in it's final location
                vA[k] = vA[j];
                vI[k] = k;
                k = j;
            }
            vA[k] = t;
            vI[k] = k;
        }
    }
}

简单的说法是根据vI将vA复制到另一个向量vB:

    for(i = 0; i < vA.size(); i++){
        vB[i] = vA[vI[i]];