计数排序
1、计数排序思想
计数排序假设n个输入元素中的每一个都是在0到k区间的一个整数,其中k为某个整数。当k=O(n)时,排序的运行时间为O(n)。
计数排序的基本思想是:对每一个输入元素x,确定小于x的元素个数。利用这一信息,就可以直接把x放到它在输出数组中的位置。当有几个元素相同时,要做修改,不能把它们放在同一个输出位置上。
2、伪代码
*COUNTING-SORT(A, A.length,k) 1 let C[0...k] be a new array 2 let B[0... A.length -1] be a new array 3 for i=0 to k 4 C[i]=0//数组C的值全被置成0 5 for j=1 to A.length 6 C[A[j]]=C[A[j]]+1//如果输入的值为i,则数组C中保存的是数组A中元素等于i的元素的个数 7 for i=1 to k 8 C[i]=C[i]+C[i-1]//数组C中保存的是比输入值为i的元素小或者相等的个数 9 for j=A.length down to 1 10 B[C[A[j]]]=A[j] 11 C[A[j]]=C[A[j]]-1 12 return B
3、具体实现
/*计数排序*/ #include <iostream> using namespace std; //打印数组 void PrintCountingSort(int *arr, int len) { for (int i = 1; i < len; i++) { cout << arr[i] << " "; } cout << endl; } //输入数组中的最大值 int MaxElement(int *arr, int len) { int max = arr[1]; for (int i = 2; i < len; i++) { if (max < arr[i]) { max = arr[i]; } } return max; } //计数排序 int *CountingSort(int *a, int len, int key) { //创建数组c 1、用于保存的是数组A中元素等于i(数组a中的元素)的元素的个数 2、用于保存的是比输入值为i的元素小或者相等的个数 int *b, *c; c = (int*)malloc(sizeof(int)*(key+1));//辅助数组 b = (int*)malloc(sizeof(int)*len);//存放排序结果 //将数组c的值置为0 for (int i = 0; i <= key; i++) { c[i] = 0; } //数组c保存数组A中元素等于i(数组a中的元素)的元素的个数 for (int j = 1; j < len; j++) { c[a[j]] ++; } //数组c保存比输入值为i(数组a中的元素)的元素小或者相等的个数 for (int i = 1; i <= key; i++) { c[i] = c[i] + c[i - 1]; } //将数组a中的元素按顺序放入b中 for (int j = len - 1; j >= 0; j--) { b[c[a[j]]] = a[j]; c[a[j]] --; } free(c); return b; } int main() { int len = 0, key=0; int *b = NULL; int a[] = { 0, 2, 5, 3, 0, 2, 3, 0, 3 }; //数组长度 len = sizeof(a) / sizeof(a[0]); //求输入数组中的最大值 key = MaxElement(a, len); //计数排序前的数组 cout << "The original array(1--n):" << endl; PrintCountingSort(a, len); //计数排序 b = CountingSort(a, len, key); //计数排序后的数组 cout << "The original array(1--n):" << endl; PrintCountingSort(b, len); system("pause"); return 0; }
4、算法分析
计数排序总的时间代价是O(k+n)。在实际工作中,当k=O(n)时,一般采用计数排序,运行时间为O(n)。
计数排序的代码中完全没有输入元素之间的比较操作,是使用输入元素的实际值来确定其在数组中的位置。计数排序是稳定的:具有相同值的元素在输出数组中的相对次序与它们在输入数组中的相对次序相同。对于两个相同的数来说,在输入数组中先出现的数,在输出数组中也位于前面。