首页 > 代码库 > 计数排序、基数排序与桶排序
计数排序、基数排序与桶排序
一、计数排序
稳定、 当输入的元素是n 个小区间(0到k)内整数时,它的运行时间是 O(n + k),空间复杂度是O(n)。
const int K = 100; //计数排序:假设输入数据都属于一个小区间内的整数,可用于解决如年龄排序类的问题 //Input:A[0, ..., n-1], 0 <= A[i] < K //Output:B[0, ..., n-1], sorting of A //Aux storage C[0, ..., K) void CountSort(int A[], int B[], int n) { int *C = new int[K]; int i, j; //初始化 //memset(C, 0, sizeof(int)*K); //统计 for (i = 0; i < n; i++) C[A[i]]++; //C[i] = |{key=i}| for (i = 1; i < K; i++) C[i] += C[i - 1]; //C[i] = |{key <= i}| //分配 for(j = n - 1; j >= 0; j--) //for(j = 0; j < n; j++) { //B[C[A[j]] - 1] = A[j]; //C[A[j]]--; B[--C[A[j]]] = A[j]; //对于每一个A[j]来说,C[A[j]]-1就是A[j]在输出数组中的最终位置,因为共有C[A[j]]个元素小于或等于A[j] } delete []C; }
参考算法导论p108~110。
可以利用计数排序的思想,在O(1)的时间复杂度内计算介于0~k之间的n个整数中有多少个落在区间[a,b]内(算法导论p110题8.2-4):
int CountNumberBetweenAB(int L[], int n, int a, int b) { const int K = 100; int *c = new int[K]; int i; memset(c, 0, sizeof(int)*K); for (i = 0; i < n; i++) c[L[i]]++; for (i = 1; i < K; i++) c[i] += c[i - 1]; int count = (a == 0 ? c[b] : c[b] - c[a - 1]); delete c; return count; }
二、基数排序
稳定、按最低有效位到最高有效位进行排序(中间采用的是稳定呢的计数排序), 当输入的元素是n 个d位整数时,它的运行时间是 O(d(n + k)),k一般是10,空间复杂度是O(n)。
void RadixSort(int A[], int n, int d) { const int K = 10; int i, j; int *digitI = new int[n], c[K]; int *tmp = new int[n];//临时数组 int base = 1; for (i = 0; i < d; i++) { memset(c, 0, sizeof(int)*K); for (j = 0; j < n; j++) { digitI[j] = (A[j] / base) % K; //从低位到高位取每一位 c[digitI[j]]++; //printf("%3d ", digitI[j]); } //cout << endl; for (j = 1; j < K; j++) c[j] += c[j - 1]; for (j = n - 1; j >= 0; j--) tmp[--c[digitI[j]]] = A[j]; // = digitI[j]] //for (j = 0; j < n; j++) // printf("%03d ", tmp[j]); //cout << endl; memcpy(A, tmp, sizeof(int)*n); base *= 10; } memcpy(A, tmp, sizeof(int)*n); delete []tmp; delete []digitI; }
参考算法导论p110~112
三、桶排序
桶排序假设输入是由一个随机过程产生,该过程将元素均匀、独立地分布在[0,1)区间上。桶排序是稳定的、期望时间复杂度是O(n),空间复杂度是O(k*n/k) = O(n);
/*initial arr*/ void InitialArr(double *arr,int n) { srand((unsigned)time(NULL)); for (int i = 0; i < n;i++) { arr[i] = rand() / double(RAND_MAX+1); //[0.1) } }
void BucketSort(double arr[], int n) { const int K = 10;//桶的个数 int i, j, k; double *bucket[K]; for (i = 0; i < K; i++) bucket[i] = new double[n]; int count[K] = {0};//每一个桶中的元素个数 for (i = 0; i < n; i++) { double tmp = arr[i]; int digitI = (int)(tmp*10); //digitI表示第i个元素的小数点第一位 //小数点第一位(digitI)相同的元素放在同一个桶(bucket[digitI])中的第count[digitI]个位置上 //通过插入排序将tmp插入到有序的bucket[digitI][0,...,count[digitI] - 1] for (j = count[digitI] - 1; j >= 0 && tmp < bucket[digitI][j]; j--) bucket[digitI][j + 1] = bucket[digitI][j]; bucket[digitI][j + 1] = tmp; count[digitI]++; } //重新连接数据 k = 0; for (i = 0; i < K; i++) for (j = 0; j < count[i]; j++) arr[k++] = bucket[i][j]; for (i = 0; i < K; i++) delete []bucket[i]; }
参考算法导论p112~114
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。