排序算法
来源:互联网 发布:淘宝女装分类宝贝图片 编辑:程序博客网 时间:2024/05/29 02:22
归并排序(顶->下)
private static void sort(Comparable[] a, int lo, int hi){ if(lo >= hi) return; int mid = lo + (hi-lo)/2; sort(a, lo, mid); sort(a, mid+1, hi);//mid+1保证了不会进入迭代死循环 merge(a, lo, mid, hi); }
归并排序(顶->下)的优化:
- 对小数组采用插排
- 判断
sort()
后的数组是否有序,即a[mid] < a [mid+1]
,若成立则跳过merge() - 不将元素复制进辅助数组
对于第三点优化,练习2.2.11的部分代码段如下:
private static void merge(Comparable[] src, Comparable[] dst, int lo, int mid, int hi) {//得到后者dst有序 // precondition: src[lo .. mid] and src[mid+1 .. hi] are sorted subarrays assert isSorted(src, lo, mid); assert isSorted(src, mid+1, hi); int i = lo, j = mid+1; for (int k = lo; k <= hi; k++) { if (i > mid) dst[k] = src[j++]; else if (j > hi) dst[k] = src[i++]; else if (less(src[j], src[i])) dst[k] = src[j++]; // to ensure stability else dst[k] = src[i++]; } // postcondition: dst[lo .. hi] is sorted subarray assert isSorted(dst, lo, hi); } private static void sort(Comparable[] src, Comparable[] dst, int lo, int hi) { // if (hi <= lo) return; if (hi <= lo + CUTOFF) { insertionSort(dst, lo, hi); return; } int mid = lo + (hi - lo) / 2; sort(dst, src, lo, mid);//在这里可以看出与sort输入的相反了 sort(dst, src, mid+1, hi); // if (!less(src[mid+1], src[mid])) { // for (int i = lo; i <= hi; i++) dst[i] = src[i]; // return; // } // using System.arraycopy() is a bit faster than the above loop if (!less(src[mid+1], src[mid])) { System.arraycopy(src, lo, dst, lo, hi - lo + 1); return; } merge(src, dst, lo, mid, hi);//依据该函数的具体构成可以看出结果是保证了dst有序。所以得出当前sort的输出是保证dst有序的 } /** * Rearranges the array in ascending order, using the natural order. * @param a the array to be sorted */ public static void sort(Comparable[] a) { Comparable[] aux = a.clone(); sort(aux, a, 0, a.length-1); //所以将原数组a放在后面 assert isSorted(a); }
归并排序(底->上)
取消了sort(a, lo, hi)
并修改了sort(Comparable[] a)
public static void sort(Comparable[] a){ int N = a.length; aux = new Comparable[N]; for(int size = 1; size < N; size = 2*size){ for(int lo = 0; lo < N-size; lo += 2*size){//lo<N-sz因为merge仅仅需要保证一个数组的长度,另一个长度不作要求 merge(a, lo, lo+size-1, Math.min(lo+2*size-1, N-1)); } } }
注:自底向上的归并适合用于链表结构的数据集。
快速排序
继承于归并,重点在于切分,即通过切分保证切分点左边的数组总小于切分点右边的数组。
public static void sort(Comparable[] a){ StdRandom.shuffle(a); //记得随机化 sort(a, 0, a.length-1); } private static void sort(Comparable[] a, int lo, int hi){ if(lo >= hi) return; int j; j = partition(a, lo, hi); sort(a, lo, j-1); //记得-1,防止无限迭代 sort(a, j+1, hi); //记得+1,防止无限迭代 } private static int partition(Comparable[] a, int lo, int hi){ Comparable v = a[lo]; int i = lo; int j = hi+1; //记得+1 while(true){ while(less(a[++i], v)) if(i == hi) break; //先++在i while(less(v, a[--j])) if(j == lo) break; if(i >= j) break; //防止过度交换 exch(a, i, j); } exch(a, lo, j); return j; }
快速排序优化
- 小数组采用插排
- 改善切分点
- 考虑重复元素数组的快排改进——三向切分(基于信息量排序)
补充
采用comparator接口代替comparable来使得排序规则具有选择性。
优先队列/堆排序
JAVA实现的类:
Class PriorityQueue<E>
一个基于优先级堆的无界优先级队列。优先级队列的元素按照其自然顺序进行排序,或者根据构造队列时提供的 Comparator 进行排序,具体取决于所使用的构造方法。优先级队列不允许使用 null 元素。依靠自然顺序的优先级队列还不允许插入不可比较的对象(这样做可能导致 ClassCastException)。
基于堆排序的优先队列可以在以较小的代价下,实现局部有序。
来看一下堆排序方法,其核心原理是利用树结构,父节点总是大于子节点,每次插入新元素,只需要比较父节点和其中一个子节点就能保证根节点是最大的,并且实现在取出根节点后不需要在重新比较所有元素,而仅仅用部分比较就可以继续保持局部有序。因此堆排序可以将比较次数减少为树高。由此也可以看出,对于二叉堆,多叉堆的效率会更高,但是,效率的提升是有限的,其最终改变的就是从log2变为log3,都是线性对数级别。
阅读全文
0 0
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- 排序算法
- Ubuntu全盘备份与恢复,亲自总结,实测可靠
- java:使用RXTXcomm向安卓系统板子的串口进行命令写入
- Codevs 1961 躲避大龙
- Redis Desktop Manager
- 总结一下之前socket opencv传灰度图片
- 排序算法
- 【LeetCode】C# 56、Merge Intervals
- [Web Service]Web Service学习与工作原理研究|用IDEA开发Web Service
- LayoutInFlater原理
- 【项目经理之修炼(6)】《基础篇》项目经理应该坐在哪儿?
- shell脚本归纳总结(二)
- python3 读取写入Excel
- eclipse导包和maven导包、lombok包
- A联合之bundle传值在xlistview中获取