int a[] = {0, 0, 0, 0, 0, 0, 1, 1, 2, 0, 0, 2, 1, 1, 0, 0, 0, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0};
对此类系列进行排序的最佳方法是什么?请记住,我想要最小的复杂性。
如果数字的上限较小,则可以使用计数排序:计算每个项目在数组中出现的次数,然后遍历数组,并为每个值放入与计数一样多的项目。
例如,在您的情况下,您将计算 17 个零、7 个 1 和 4 个 2。设置前 17 项为 0,后面 7 项为 1,其余 4 项为 2,得到排序后的数组。
这种方法具有线性复杂性。
您可以使用Counting Sort
对此类系列进行排序。
如果数字系列确实限于值 0-2,那么最好的办法是使用计数样式排序。
void CountedSortMaxThree(int* array, size_t length) {
int count0 = 0;
int count1 = 0;
int count2 = 0;
for (int i = 0; i < length; i++) {
switch(array[i]) {
case 0: count0++; break;
case 1: count1++; break;
case 2: count2++; break;
}
}
int index = 0;
while (count0-- > 0) array[index++] = 0;
while (count1-- > 0) array[index++] = 1;
while (count2-- > 0) array[index++] = 2;
}
为了可重用,您需要定义一个等于最大值与硬编码数字的桶数组
void CountedSort(int* array, int length, int max) {
int* buckets = malloc(sizeof(int) * max);
for (int i = 0; i < length; i++) {
bucket[array[i]]++;
}
int index = 0;
for (int i = 0; i < max; i++) {
while (buckets[i]-- > 0) {
array[index++] = i;
}
}
free(buckets);
}
请注意,仅当值的范围较小时才应使用计数排序。在您的示例中,范围是 3(包括 0 到 2),因此可以进行计数排序。如果范围要高得多(想想Int32.Max
),那么你最终会分配一个巨大的桶数组,这最终会变得相当低效
void sort012Dutch(int A[],int n)
{
int pos0=0,pos2=n-1,i=0;
while(i<n)
{
if(A[i]==0)
{
A[i]=A[pos0];
A[pos0]=0;
pos0++;
}
if(A[i]==2&&i<pos2)
{
A[i]=A[pos2];
A[pos2]=2;
pos2--;
i--;//0 could be swapped
}
i++;
}
}
pos0 indicates the next index in the array where 0 is to be inserted
pos2 indicates the next index in the array where 2 is to be inserted
您可以使用该qsort
功能。