【问题标题】:sorting an array and maintaining element's old index对数组进行排序并维护元素的旧索引
【发布时间】:2015-07-07 04:58:26
【问题描述】:

我有一个数组 A:

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

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

struct VnI{
  int value;
  int index;
};

根据值对结构数组进行排序解决了我的问题。但我想知道是否可以使用 sort 或 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;
  }
}

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

【问题讨论】:

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


    【解决方案1】:

    这段代码是错误的:

    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

    很遗憾,std::vector 中的 operator[] 不检查 超出范围 索引。如果使用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()
    • 以及所有的构造函数。

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

    希望对您有所帮助。

    【讨论】:

      【解决方案2】:

      你喜欢使用向量和配对吗?

      每对有“第一”和“第二”,把“第一”=值排序,“第二”=原始索引,为每个元素创建一对并放入向量中排序:

      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
      

      【讨论】:

        【解决方案3】:

        通常所做的事情是相反的......即给定一个元素数组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-th 元素在原始数组中的位置)并且那里不需要修改输入数组。

        【讨论】:

          【解决方案4】:

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

          SO Link

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-08-17
            • 1970-01-01
            • 2020-06-22
            • 1970-01-01
            • 2017-11-02
            • 1970-01-01
            • 2019-09-10
            • 2015-08-27
            相关资源
            最近更新 更多