将元素附加到向量会导致后续失败的排序

时间:2016-07-15 17:12:09

标签: c++ sorting vector

我有2个向量:元素向量和计数向量。在对Element向量进行排序时,我需要对与Element向量值对应的计数向量进行排序。我需要将Element向量附加到全局向量(Proc)及其相应的Proc_count向量,该向量逐渐增大,并重复上述排序过程。

但是,在将元素附加到Proc和Proc_count向量的末尾后,第二个排序步骤失败。我知道重新调整向量大小会使迭代器失效,但即使使用了std :: reserve,我也注意到了相同的结果。

typedef uint64_t data_t;

struct MyComparator
{
   const std::vector<data_t> & value_vector;
   MyComparator(const std::vector<data_t> & val_vec):
          value_vector(val_vec) {}

   bool operator()(int i1, int i2)
  {
    return value_vector[i1] < value_vector[i2];
  }
};

void SortAndAggregate(std::vector<data_t>& arr, std::vector<int>& count, std::vector<int>& add)
{

 sort(count.begin(), count.end(), MyComparator(arr));
 sort(arr.begin(), arr.end());

    printf("Sorted arr: \n");
    for (std::vector<data_t>::iterator it = arr.begin() ; it != arr.end(); ++it)
         std::cout << ' ' << *it;
    std::cout << '\n';

    printf("Sorted count: \n");
    for (std::vector<int>::iterator it = count.begin() ; it != count.end(); ++it)
         std::cout << ' ' << *it;
    std::cout << '\n';

 int aggr=0;
 for(int i = 0; i < (int)(arr.size()); i++)
    {
      aggr = count[i];
      if (arr[i] == arr[i+1]) {
          do {
                aggr += count[i+1];
                i++;
             } while(i<(int)arr.size() && (arr[i] == arr[i+1]));
       }
       add.push_back(aggr);
    }

 arr.erase( unique( arr.begin(), arr.end() ), arr.end() );
 assert(arr.size() == add.size());

    printf("Sorted add: \n");
    for (std::vector<int>::iterator it = add.begin() ; it != add.end(); ++it)
         std::cout << ' ' << *it;
    std::cout << '\n';
    std::cout << '\n';

}

int main(int argc, char *argv[])
{
    int N=20;
    srand(time(0));

    data_t mydata[] = {14,32,71,12,45,26,80,53,33, 9};
    int mycnt[]     = {1,  2, 3, 4, 5, 6, 7, 8, 9,10};
    std::vector<data_t> dummy_data (mydata, mydata+10);
    std::vector<int> dummy_cnt (mycnt, mycnt+10);

    std::vector<data_t> arr1;
    std::vector<int> cnt;
    std::vector<int> arr3;
    std::vector<data_t> proc_buf;
    std::vector<int> proc_buf_cnt;

    proc_buf.reserve(20);
    proc_buf_cnt.reserve(20);

    proc_buf.insert(proc_buf.end(), dummy_data.begin(), dummy_data.end());
    proc_buf_cnt.insert(proc_buf_cnt.end(), dummy_cnt.begin(), dummy_cnt.end());

    SortAndAggregate (proc_buf, proc_buf_cnt, arr3);
    proc_buf_cnt = arr3;
    arr3.clear();

    printf("Proc buffer before: \n");
    for (std::vector<data_t>::iterator it = proc_buf.begin() ; it != proc_buf.end(); ++it)
         std::cout << ' ' << *it;
    std::cout << '\n';

    printf("Proc Count buffer before: \n");
    for (std::vector<int>::iterator it = proc_buf_cnt.begin() ; it != proc_buf_cnt.end(); ++it)
         std::cout << ' ' << *it;
    std::cout << '\n';
    std::cout << '\n';

    for (int i = 0; i < N; ++i)
    {
         arr1.push_back(rand() % 10);
         cnt.push_back(i);
    }

    printf("Original array: \n");
    for (int it = 0 ; it < (int)arr1.size(); ++it)
         std::cout << ' ' << arr1[it];
    std::cout << '\n';

    printf("Original counts: \n");
    for (int it = 0; it < (int)cnt.size(); ++it)
         std::cout << ' ' << cnt[it];
    std::cout << '\n';
    std::cout << '\n';

    SortAndAggregate (arr1, cnt, arr3);

    proc_buf.insert(proc_buf.end(), arr1.begin(), arr1.end());
    proc_buf_cnt.insert(proc_buf_cnt.end(), arr3.begin(), arr3.end());
    arr3.clear();

    printf("Proc buffer before: size: %d \n", (int)proc_buf.size());
    for (std::vector<data_t>::iterator it = proc_buf.begin() ; it != proc_buf.end(); ++it)
         std::cout << ' ' << *it;
    std::cout << '\n';

    printf("Proc Count buffer before: size: %d \n", (int)proc_buf_cnt.size());
    for (std::vector<int>::iterator it = proc_buf_cnt.begin() ; it != proc_buf_cnt.end(); ++it)
         std::cout << ' ' << *it;
    std::cout << '\n';
    std::cout << '\n';

    SortAndAggregate (proc_buf, proc_buf_cnt, arr3);
    proc_buf_cnt = arr3;

    assert(proc_buf.size() == proc_buf_cnt.size());

    arr1.clear();
    cnt.clear();
    arr3.clear();
    proc_buf.clear();
    proc_buf_cnt.clear();

    return 0;
 }

输出:

   Proc buffer before: 
   9 12 14 26 32 33 45 53 71 80
   Proc Count buffer before: 
   10 9 3 5 1 8 4 7 2 6

   Original Element array: 
   4 6 6 1 7 1 0 7 3 7 8 7 5 0 9 5 6 5 1 3
   original Element counts: 
   0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19

   Sorted arr: 
   0 0 1 1 1 3 3 4 5 5 5 6 6 6 7 7 7 7 8 9
   Sorted count: 
   6 13 3 18 5 19 8 0 17 15 12 1 16 2 11 9 7 4 10 14 // CORRECT sorted order
   Sorted aggregate: 
   19 26 27 0 44 19 31 10 14

   Appended Proc buffer (size: 19) 
   9 12 14 26 32 33 45 53 71 80 0 1 3 4 5 6 7 8 9
   Appended Proc Count buffer (size: 19) 
   10 9 3 5 1 8 4 7 2 6 19 26 27 0 44 19 31 10 14

   Sorted arr: 
   0 1 3 4 5 6 7 8 9 9 12 14 26 32 33 45 53 71 80
   Sorted count:  
   10 10 19 19 14 31 0 1 2 3 4 5 6 7 8 9 26 27 44 // INCORRECT sorted order ...!!!!
   Sorted aggregate: 
   10 10 19 19 14 31 0 1 5 4 5 6 7 8 9 26 27 44

有关第二种排序失败原因的任何线索?我错过了什么吗?

2 个答案:

答案 0 :(得分:2)

正如另一个答案所暗示的那样,您有一个越界访问错误。

此外,你很幸运你的程序甚至已经达到了它,因为你在第一次调用SortAndAggreate时有一个越界访问权限,因此你在你的节目中显示的输出问题基本上是无用的,因为正在调用未定义的行为。

MyComparator仿函数中,您正在执行此操作:

bool operator()(int i1, int i2)
{
    return value_vector[i1] < value_vector[i2];
}

value_vector是一个大小== 10的向量。但是,i1i2的值最终会变为910,因此您将访问超出界限的元素。

问题的起源在main

int mycnt[] = {1,  2, 3, 4, 5, 6, 7, 8, 9,10};

您在填充prof_buf_cnt时使用这些值作为索引,并且您在prof_buf_cnt仿函数std::sort中使用MyComparator作为索引。

至少在这里,解决方案是使用基于0的索引。

int mycnt[] = { 0, 1,  2, 3, 4, 5, 6, 7, 8, 9 };

注意:如果您使用以下内容替换MyComparator仿函数中的该行:

    return value_vector.at(i1) < value_vector.at(i2);

你会立刻看到这个问题,因为会抛出std::out_of_range个例外。这可以保证你的程序会因错误而停止,而不是继续并给人一种正常工作的印象(唯一的问题是输出错误)。

有关不可预测的未定义行为的示例,请参阅以下两个链接:

See this example of your code using at()

See this example of your code using [ ]

请注意,上面的第二个链接显示您的代码“正常工作”,即使它不应该尽可能地完成,而第一个链接通过抛出异常来正确诊断问题。

答案 1 :(得分:1)

i最多只能.size()-1

 int aggr=0;
 for(int i = 0; i < (int)(arr.size()); i++)
    {
      aggr = count[i];
      if (arr[i] == arr[i+1]) {

但是你用i+1索引数组,这超出了arr的最后一个元素。