c++计数排序

c++ counting sort

本文关键字:排序 c++      更新时间:2023-10-16

我试着写一个计数排序,但是有一些问题。

代码如下:

int *countSort(int* start, int* end, int maxvalue)
{
    int *B = new int[(int)(end-start)];
    int *C = new int[maxvalue];
    for (int i = 0; i < maxvalue; i++) 
    { 
        *(C+i) = 0; 
    }
    for (int *i = start; i < end; i++) 
    { 
        *(C+*i) += 1; 
    }
    for (int i = 1; i < maxvalue-1 ; i++) 
    { 
        *(C+i) += *(C+i-1); 
    } 
    for (int *i = end-1; i > start-1; i--) 
    { 
        *(B+*(C+(*i))) = *i; 
        *(C+(*i)) -= 1; 
    }
    return B;   
}

在最后一个循环中,它抛出一个异常"在location: -some ram地址-写access violation "

我哪里做错了?

for (int i = 1; i < maxvalue-1 ; i++) 

这是错误的上界。你想从1maxvalue

for (int *i = end-1; i > start-1; i--) 
{ 
    *(B+*(C+(*i))) = *i; 
    *(C+(*i)) -= 1; 
}

这个循环也是完全不正确的。我不知道它是做什么的,但一个简单的心理测试表明,第一次迭代将数组中最后一个元素的值的索引处的B元素设置为它显示的次数。我保证那是不对的。最后一个循环应该是这样的:

int* out = B;
int j=0; 
for (int i = 0; i < maxvalue; i++) {  //for each value
    for(j<C[i]; j++) {                //for the number of times its in the source
        *out = i;                     //add it to the output
        ++out;                        //in the next open slot
    }
}

最后要说明的是,你为什么要这样摆弄指针?

*(B + i)  //is the same as
B[i]      //and people will hate you less
*(B+*(C+(*i))) //is the same as
B[C[*i]]  

既然您正在使用c++,为什么不通过使用std::vector而不是动态分配数组(并在过程中泄漏一个)来简化代码(戏剧性地)?

std::vector<int>countSort(int* start, int* end, int maxvalue)
{
    std::vector<int> B(end-start);
    std::vector<int> C(maxvalue);
    for (int *i = start; i < end; i++) 
        ++C[*i];
// etc.

除此之外,你使用的逻辑对我来说没有意义。我认为要得到一个有效的结果,你最好坐下来,拿着一张纸,找出你需要使用的步骤。我保留了上面的计数部分,因为我相信大部分都是正确的。我不认为其他的是真的。我甚至会给出一个相当简单的提示:一旦您完成了计数,您就可以仅基于C中所拥有的内容生成B(您的结果)—您确实不需要引用原始数组。最简单的方法通常是使用嵌套循环。还请注意,在Breserve空格并使用push_back将数据放入其中可能比设置其初始大小更容易。

在我看来,使用简单的指针算术是缺乏的。这是我的代码,它的工作(我测试了样本代码)。

int* sort1(int *start, int *end, int max) {
int min = INT_MAX;
int n = abs(end - start) + 1;
int* arr = new int[n];
for(int i = 0; i < n; ++i) {
  arr[i] = *(start + i);
  //cout << arr[i] << endl;
}
for(int i =0 ; i < n; ++i) {
  min = ((arr[i] < min)? arr[i] : min);
}
int r = abs(max - min);
int t[r + 1] = {0};
for(int i = 0; i < n; ++i) {
  t[arr[i] - min]++;
}
for(int i =0, j =0; i < (r+1); ++i) {
  if(t[i] > 0) {
    arr[j] = i + min;
    ++j;
  }
}
return arr;
}
int main()
{
  int arr1[] = {3,1,5,9};
  int arr2[] = {6,4,100,0,-1,50,-11,-101};
  int n1 = (sizeof(arr1)/sizeof(arr1[0]));
  int n2 = (sizeof(arr2)/sizeof(arr2[0]));
  int n3 = (n1 + n2);
  int arr3[n3];
  for(int i = 0; i < n1; ++i) {
    arr3[i] = arr1[i];
  }
  for(int i = 0; i < n2; ++i) {
    arr3[n1 + i] = arr2[i];
  }
  int *arr5 = sort1(&arr3[0], &arr3[n3 - 1], 100);
  for(int i = 0; i < (n1 + n2); ++i) {
    cout << *(arr5 + i) << endl;
  }
  return 0;
}
The output:
-101
-11
-1
0
1
3
4
5
6
9
50
100