这似乎是一个非常微不足道的问题,但经过深思熟虑,我仍然无法弄明白。我将这两个代码用于Radix排序。
#include <stdio.h>
#include <malloc.h>
#define BUCKET_SIZE 10
void prin(int* arr,int n)
{
int i;
for(i=0;i<n;i++)
printf("%d ",*(arr+i));
printf("\n");
}
int maxi(int* arr,int n)
{
int i,max=0;
for(i=0;i<n;i++)
{
if(arr[i]>max)
max=arr[i];
}
return max;
}
int* count(int *arr,int n,int k)
{
int* count,i,index;
int* output;
count=(int*)calloc(BUCKET_SIZE-1,sizeof(int));
output=(int*)malloc(n*sizeof(int));
for(i=0;i<n;i++)
{
index=(arr[i]/k)%10;
count[index]++;
}
for(i=0;i<BUCKET_SIZE;i++)
count[i]+=count[i-1];
for(i=n-1;i>=0;i--)
{
index=(arr[i]/k)%10;
output[count[index]-1]=arr[i];
count[index]--;
}
return output;
}
int* radixsort(int* arr,int n)
{
int i,max,k=1;
max=maxi(arr,n);
while(max>0)
{
max/=10;
arr=count(arr,n,k);
k=k*10;
}
return arr;
}
void main()
{
int n,i;
scanf("%d",&n);
int* arr;
arr=(int*)malloc(n*sizeof(int));
for(i=0;i<n;i++)
scanf("%d",(arr+i));
arr=radixsort(arr,n);
prin(arr,n);
}
现在,如果我更改下面的sort子例程,这段代码将不会对给定的数组进行排序,我无法解释为什么会发生这种情况,我仍在遍历整个数组,所以我仍在计算正确的索引所以我的元素应该填写在正确的位置,我应该有一个排序的数组。
仅计数函数最后一个循环已更改。
int* count(int *arr,int n,int k)
{
int* count,i,index;
int* output;
count=(int*)calloc(BUCKET_SIZE-1,sizeof(int));
output=(int*)malloc(n*sizeof(int));
for(i=0;i<n;i++)
{
index=(arr[i]/k)%10;
count[index]++;
}
for(i=0;i<BUCKET_SIZE;i++)
count[i]+=count[i-1];
for(i=0;i<n;i++)
{
index=(arr[i]/k)%10;
output[count[index]-1]=arr[i];
count[index]--;
}
return output;
}
当我正在计算排序时,两个函数都运行良好。有人可以指出我在哪里出错我的基数排序,或者我错过了什么,以及如何计算排序。
感谢。
答案 0 :(得分:2)
在count
函数的最后一个循环中,
当这些行复制每个&#34; bucket&#34;的内容时,
他们写了输出的最后一个元素&#34; bucket&#34;第一,
然后是倒数第二个,以第一个元素结束:
output[count[index]-1]=arr[i];
count[index]--;
在你的程序的第一个版本中,因为你从数组的末尾开始访问输入数组的元素并回到开头, 你首先遇到每个桶的最后一个元素(因此把它放在输出桶的最后一个位置),然后是倒数第二个元素 (你把它放在输出中的倒数第二个位置), 等等。每个存储桶的第一个元素是最后复制的 并被复制到存储桶中的第一个位置。
在程序的第二个版本中,您将继续从后到前填充每个输出存储桶中的空格,但您可以从前到后读取输入。 这样可以将每个桶的第一个元素放在该桶中的最后一个位置,并将桶的最后一个元素放在第一个位置。
也就是说,每次运行count
函数时,它都会反转每个存储桶中元素的顺序。
如果要复制从前到后读取的输入数组,
你需要从前到后填写每个输出桶
使用++count[index]
代替--count[index]
。
您还必须以较低的数字开始count[index]
的每个条目,以便您写入正确的位置。
除此之外:您的程序执行的分配比它需要的多得多,并且不会释放任何内存,因此您可能会发生大量内存泄漏。
您可以考虑将已分配的数组传递到count
,而不是总是分配新数组。
答案 1 :(得分:1)
这是一个从前到后的示例,它还使用已排序的数组替换原始数组,从而释放原始数组。另一种方法是对第二个工作数组进行一次性分配,在原始数组和工作数组之间来回进行基数排序,然后保留排序后的数组,并释放&#34;其他&#34;阵列。
#include <stdio.h>
#include <stdlib.h>
#define BUCKET_SIZE 10
void prin(int* arr, int n)
{
int i;
for(i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
}
int maxi(int* arr, int n)
{
int i,max = 0;
for(i = 0; i < n; i++)
{
if(arr[i] > max)
max = arr[i];
}
return max;
}
/* replaces array with sorted array, frees original array */
void count(int** parr, int n, int k)
{
int* count, i, index;
int* arr = *parr;
int* output;
int sum, cur;
count=calloc(BUCKET_SIZE, sizeof(int));
output=malloc(n*sizeof(int));
for(i = 0; i < n; i++){
index = (arr[i]/k)%10;
count[index]++;
}
sum = 0;
for(i = 0; i < BUCKET_SIZE; i++){
cur = count[i];
count[i] = sum;
sum += cur;
}
for(i = 0; i < n; i++){
index = (arr[i]/k)%10;
output[count[index]++] = arr[i];
}
free(arr);
free(count);
*parr = output;
}
void radixsort(int** parr,int n)
{
int max,k=1;
max=maxi(*parr,n);
while(max>0)
{
max/=10;
count(parr,n,k);
k=k*10;
}
}
int main()
{
int n,i;
int* arr;
scanf("%d",&n);
arr = malloc(n*sizeof(int));
for(i = 0; i < n; i++)
scanf("%d",&arr[i]);
radixsort(&arr,n);
prin(arr,n);
free(arr);
return 0;
}