对数组进行排序并维护元素的旧索引

时间:2015-07-07 04:58:26

标签: c++ arrays sorting c++11 structure

我有一个数组A:

A     =   [10 11 3 15 8 7]
index =    0   1 2  3 4 5

我想对这个数组进行排序。排序后我想要旧索引的信息。为此,我可以创建一个这样的结构。

struct VnI{
  int value;
  int index;
};

根据值对结构数组进行排序可以解决我的问题。但我想知道可以使用排序或C ++ 11中的任何其他函数来解决这个问题。

我试过这种方式:

struct VnI{
int V;
int I;
};

bool comparator(VnI x,VnI y){
    if(x.V < y.V)
        return true;
    return false;
}
int maximumGap(const vector<int> &A) {
   vector<VnI> B;
   for(int i = 0;i < A.size();i++){
      B[i].I = i;
      B[i].V = A[i];
}
sort(B.begin(),B.end(),comparator);
for(int i = 0;i < B.size();i++){
    cout<<B[i].I<<" "<<B[i].V<<endl;
  }
}

但是我遇到了运行时错误。 请帮忙。

4 个答案:

答案 0 :(得分:2)

此代码错误:

vector<VnI> B;  

for(int i = 0;i < A.size();i++){
   B[i].I = i;
   B[i].V = A[i];
}

当您撰写B[i]时,它会假定B 至少大小为i+1。由于i(您使用B的索引)的最大值为A.size()-1。您的代码中的假设是B的大小至少为A.size()此假设错误 - 事实是B的大小为0

不幸的是,operator[] std::vector未检查超出范围的索引。如果您使用at(),代码将抛出std::out_of_range例外:

vector<VnI> B;  

for(int i = 0;i < A.size();i++){
   B.at(i).I = i;
   B.at(i).V = A[i];
}

现在这会抛出std::out_of_range例外。

无论如何,一个简单的解决办法就是:

 vector<VnI> B (A.size());  //initialize B with the size of A.

 for(int i = 0;i < A.size();i++){
    B[i].I = i;
    B[i].V = A[i];
 }

但是,我建议这个解决方案:

 vector<VnI> B;      
 B.reserve(A.size()); 

 for(int i = 0;i < A.size(); i++){
    B.emplace_back(i, A[i]);
 }

我还建议您阅读有关std::vector的更多信息,尤其是以下功能:

  • size()
  • capacity()
  • resize()
  • reserve()
  • push_back()
  • operator[]
  • at()
  • emplace_back()
  • 和所有构造函数。

另外,请学会正确命名变量并与之保持一致。

希望有所帮助。

答案 1 :(得分:2)

你是否愿意使用矢量和配对?

每一对都有&#34;第一&#34; && 34; second&#34;,put&#34; first&#34; = value to sort,&#34; second&#34; =原始索引,为每个元素创建一对并将它们放入向量中进行排序:

int N[]={10,11,3,15,8,7};
std::vector<std::pair<int,int> > v;
//create pair for each element
for(int i=0;i<sizeof(N)/sizeof(int);i++){
    //first is value of array,second is original index
    v.push_back(std::make_pair(N[i],i));
}

//sort the vector of pair
sort(v.begin(),v.end());

//get original index from second of pair
for(std::pair<int,int>& p : v){
    std::cout << p.first << ":" << p.second << std::endl;
}

输出

3:2
7:5
8:4
10:0
11:1
15:3

答案 2 :(得分:1)

通常做的是相反的......即,给定数组x的元素计算整数数组ix,以便x[ix[i]]看起来按照某个标准排序。

这允许用不同的顺序表示容器,而不必实际移动/复制元素。

使用C ++ 11,可以使用lambdas轻松完成:

// Build the index vector ix
std::vector<int> ix(x.size());
for (int i=0,n=x.size(); i<n; i++) ix[i] = i;

// Sort ix according to the corresponding values in x
// (without touching x)
std::sort(ix.begin(), ix.end(),
          [&x](int a, int b) { return x[a] < x[b]; });

ix索引数组是您要求的(即元素的“旧”位置:ix[i]是排序列表的i - 元素所在的位置原始数组)并且无需修改输入数组。

答案 3 :(得分:-1)

您正在尝试对自定义对象列表进行排序,请在此处回答:

SO Link

列出listVnI个对象后,您可以通过我认为是索引的I成员访问旧索引。