19、归并排序、计数排序、基数排序
来源:互联网 发布:婚纱网络客服 编辑:程序博客网 时间:2024/06/11 01:41
1、归并排序是另一种运用分治排序的算法,它的不同在于归并过程-将两个有序的数据集合合并成一个有序的数据集。
所有情况下都能达到快速排序的平均性能,但是需要额外的存储空间来运行,因为合并过程不能在无序数据本身运行。
会按照分的方式合,不用担心是否为2的幂。
//把排序好的两堆合并成一堆 //i为头,k为尾;i 到 j;j+1 到 k static int merge(void *data, int size, int esize, int i, int k, int j, int (*compare)(const void *key1, const void *key2)){ char *a = data, *m;//m暂存排序好的有序数组 int ipos, jpos, mpos; ipos = i; jpos = j + 1; mpos = 0; if((m = (char *)malloc(esize *((k - i) + 1))) == NULL)//0到n是n+1个数 return -1; //从两组数的头开始比,两组都是排序好的数组,小的在前,依次把小的放入数组m //当 (ipos <= j) || ((jpos <= k)说明没比完 while((ipos <= j) || ((jpos <= k)) { if(compare(&a[ipos * esize], &a[jpos * esize]) < 0) { memcpy(&m[mpos * esize], &a[ipos * esize], esize); ipos++; mpos++; } else { memcpy(&m[mpos * esize], &a[jpos * esize], esize); jpos++; mpos++; } //左边都小,前面已经放完,现在放入右边 if(ipos > j) { while(jpos <= k) { memcpy(&m[mpos * esize], &a[jpos * esize], esize); jpos++; mpos++; } } else if(jpos > k) { while(ipos <= j) { memcpy(&m[mpos * esize], &a[ipos * esize], esize); ipos++; mpos++; } } } //把排好的数据放回原来数组对应区域 memcpy(&a[i * esize], m , esize*((k - i) + 1)); free(m); return 0;}
int mgsort(void *data, int size, int esize, int i, int k, int (*compare)(const void *key1, const void *key2)){ int j; if(i < k) { //当只剩下两个元素进入时(i=j,j+1=k),下面两个mgsort()不执行,直接执行merge() j = (int)( ((i + k - 1)) / 2 ); if(mgsort(data, size, esize, i, j, compare) < 0) return -1; if(mgsort(data, size, esize, j+1, k, compare) < 0) return -1; if(merge(data, esize, i, j, k, compare) < 0) return -1; } return 0;}
2、计数排序
线性排序,不同于前面的比较算法,计数排序通过计算集合中整数出现的次数来决定集合应该如何排序。效率比O(nlgn)高,但是只能用于整形或者那些可以用整形来表示的数据集合。
//k是data中最大整数加1 ,0到k即k+1个数 int ctsort(int *data, int size, int k){ int *counts, *temp; int i, j; //0到k每个数对应一个数组位置记录其出现的次数,和上面图中不同。 //这样data中数的大小直接对应计数数组中的位置,计数数组该位置对应的数字即data中数该放在排序数组中的位置 if((counts = (int *)malloc(k * sizeof(int))) == NULL) return -1; if((temp = (int *)malloc(size * sizeof(int))) == NULL) return -1; //计数值清零 for(i = 0; i < k; i++) counts[i] = 0; //对应数字 data[j]存入count数组count位置data[j],并在 其内容存放出现次数 for(j = 0; j < size; j++) counts[data[j]] = counts[data[j]] + 1; //把计数次数装换为,对应数字该从哪个位置放,倒放 for(i = 1; i < k; i++) counts[i] = counts[i-1] + counts[i]; for(j = size - 1; j >= 0; j--) { //counts[data[j]] - 1就是 data[j]该放的位置 temp[counts[data[j]] - 1] = data[j]; counts[data[j]] = counts[data[j]] - 1; } memcpy(data, temp, size * sizeof(int)); free(counts); free(temp); return 0; }
3、基数排序
线性排序,先比较数据的最低位进行排序(每一位排序应用计数排序),然后次低位依次排序。
基数排序并不局限于对整型数据进行排序,只要能把元素分割成整形数就可以使用基数排序。
//p是位数,k是进制 int rxsort(int *data, int size, int p, int k){ int *counts, *temp; int index, pval; int i, j, n; if((counts = (int *)malloc(k * sizeof(int))) == NULL) return -1; if((temp = (int *)malloc(size * sizeof(int))) == NULL) return -1; //对每一位进行排序 for(n = 0; n < p; n++) { for(i = 0 ;i < k;i++) counts[i] = 0; //对于整数则pval=k*n,当做取某位上数字时的除数 pval = (int)pow((double)k, (double)n); for(j = 0;j < size; j++) { index = (int)(data[j] / pval) % k; counts[index] = counts[index] + 1; } for(i = 1;i < k;i++) { counts[i] = counts[i] + counts[i - 1]; } for(j = size - 1; j >= 0; j--) { index = (int)(data[j] / pval) % k; temp[counts[index] - 1] = data[j]; counts[index] = counts[index] - 1; } memcpy(data, temp, size * sizeof(int)); free(counts); free(temp); return 0; }}
阅读全文
0 0
- 19、归并排序、计数排序、基数排序
- 快速排序,插入排序,归并排序,计数排序,基数排序,堆排序
- 算法导论之排序:快速排序、归并排序、计数排序、基数排序、桶排序
- java实现:快速排序,基数排序,计数排序,归并排序,堆排序,希尔排序
- 计数排序,基数排序
- 计数排序和基数排序
- 计数排序-基数排序
- 计数排序和基数排序
- 基数排序和计数排序
- 计数排序和基数排序
- 计数排序+基数排序
- 计数排序和基数排序
- 基数排序/计数排序
- 计数排序和基数排序
- 基数排序,计数排序
- 计数排序和基数排序
- 计数排序实现基数排序
- 基数排序与计数排序
- unity3d 命令行参数 Command line arguments
- Effective Modern C++翻译系列之Item16
- hdu6140-多校8&思维&坑- Hybrid Crystals
- Struts2 将EXTJS Json解析为List数据
- HDU 6128 Inverse of sum (数论, 2017 Multi-Univ Training Contest 7)
- 19、归并排序、计数排序、基数排序
- 用于快速排查Java的CPU性能问题
- Intra Mode Coding With 67 Intra Prediction Modes
- POJ-1279 Art Gallery(求多边形内核面积,半平面交)
- Java向上转型和向下转型
- vue中transition之slide效果
- transient 暂态
- 开垦一篇荒地
- BZOJ 4031 小Z的房间(生成树计数+行列式)