几种常见的排序算法
2015-08-24 22:38
429 查看
一、几种常见的排序算法性能比较
排序算法 | 最好时间 | 平均时间 | 最坏时间 | 辅助内存 | 稳定性 | 备注 |
---|---|---|---|---|---|---|
简单选择排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | 不稳定 | n小时较好 |
直接插入排序 | O(n) | O(n^2) | O(n^2) | O(1) | 稳定 | 大部分已有序的较好 |
冒泡排序 | O(n) | O(n^2) | O(n^2) | O(1) | 稳定 | n小时较好 |
希尔排序 | O(n) | O(nlogn) | O(n^s), s∈(1,2) | O(1) | 不稳定 | s是所选分组 |
快速排序 | O(nlogn) | O(nlogn) | O(n^2) | O(logn) | 不稳定 | n大时较好 |
堆排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(1) | 不稳定 | n大时较好 |
归并排序 | O(nlogn) | O(nlogn) | O(nlogn) | O(n) | 稳定 | n大时较好 |
二、常见算法的实现(java)
1、选择排序(Selection Sort)
选择排序的基本思想是对待排序的记录序列进行n-1遍的处理,第i遍处理是将L[i..n]中最小者与L[i]交换位置。这样,经过i遍处理之后,前i个记录的位置已经是正确的了。public class selectSort { public static void selectSort(int[] a){ int i,j; for (i=0;i<a.length;i++){ for (j=i+1;j<a.length;j++){ if (a[j]<a[i]){ int temp=a[i]; a[i]=a[j]; a[j]=temp; } } } } public static void main(String args[]){ int[] a={5,4,9,8,7,6,0,1,3,-5}; selectSort(a); for(int i=0;i<a.length;i++){ System.out.print(a[i]+" "); } System.out.println(); } }
2、插入排序(Insertion Sort)
插入排序的基本思想是,经过i-1遍处理后,L[1..i-1]己排好序。第i遍处理仅将L[i]插入L[1..i-1]的适当位置,使得L[1..i]又是排好序的序列。要达到这个目的,我们可以用顺序比较的方法。首先比较L[i]和L[i-1],如果L[i-1]≤ L[i],则L[1..i]已排好序,第i遍处理就结束了;否则交换L[i]与L[i-1]的位置,继续比较L[i-1]和L[i-2],直到找到某一个位置j(1≤j≤i-1),使得L[j] ≤L[j+1]时为止。图1演示了对4个元素进行插入排序的过程,共需要(a),(b),(c)三次插入。public class insertSort { public static void insertSort(int[] a){ if (a!=null){ for (int i=1;i<a.length;i++){ int temp=a[i],j=i; if (a[j-1]>temp){ while(j>=1&&a[j-1]>temp){ a[j]=a[j-1]; j--; } } a[j]=temp; } } } public static void main(String args[]){ int[] a={5,4,9,8,7,6,0,1,3,2}; insertSort(a); for(int i=0;i<a.length;i++){ System.out.print(a[i]+" "); } System.out.println(); } }
3、冒泡排序(Bubble Sort)
冒泡排序方法是最简单的排序方法。这种方法的基本思想是,将待排序的元素看作是竖着排列的“气泡”,较小的元素比较轻,从而要往上浮。在冒泡排序算法中我们要对这个“气泡”序列处理若干遍。所谓一遍处理,就是自底向上检查一遍这个序列,并时刻注意两个相邻的元素的顺序是否正确。如果发现两个相邻元素的顺序不对,即“轻”的元素在下面,就交换它们的位置。显然,处理一遍之后,“最轻”的元素就浮到了最高位置;处理二遍之后,“次轻”的元素就浮到了次高位置。在作第二遍处理时,由于最高位置上的元素已是“最轻”元素,所以不必检查。一般地,第i遍处理时,不必检查第i高位置以上的元素,因为经过前面i-1遍的处理,它们已正确地排好序。public class bubbleSort { public static void bubbleSort(int[] a){ for (int i=0;i<a.length;i++){ for (int j=0;j<a.length-1;j++){ if (a[j]>a[j+1]){ int temp=a[j]; a[j]=a[j+1]; a[j+1]=temp; } } } } public static void main(String args[]) { int[] a = {5, 4, 9, 8, 7, 6, 0, 1, 3, 2}; bubbleSort(a); for (int i = 0; i < a.length; i++) { System.out.print(a[i] + " "); } System.out.println(); } }
4、希尔排序(Shell Sort)
在直接插入排序算法中,每次插入一个数,使有序序列只增加1个节点,并且对插入下一个数没有提供任何帮助。如果比较相隔较远距离(称为增量)的数,使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。D.L.shell于1959年在以他名字命名的排序算法中实现了这一思想。算法先将要排序的一组数按某个增量d分成若干组,每组中记录的下标相差d.对每组中全部元素进行排序,然后再用一个较小的增量对它进行,在每组中再进行排序。当增量减到1时,整个要排序的数被分成一组,排序完成。public class shellSort { public static void shellSort(int[] array){ int len=array.length; for(int h=len/2;h>0;h=h/2){//步长为h for (int i=h;i<len;i++){ int temp=array[i]; int j; for (j=i-h;j>=0;j-=h){//相隔h个常量,跳跃式移动,使得排序效率提高 if (temp==array[j]){ array[j+h]=array[h]; }else break; } array[j+h]=temp; } } } public static void main(String args[]){ int[] a={5,4,9,8,7,6,0,1,3,2}; shellSort(a); for(int i=0;i<a.length;i++){ System.out.print(a[i]+" "); } System.out.println(); } }
5、快速排序(Quick Sort)
快速排序是对冒泡排序的一种本质改进。它的基本思想是通过一趟扫描后,使得排序序列的长度能大幅度地减少。在冒泡排序中,一次扫描只能确保最大数值的数移到正确位置,而待排序序列的长度可能只减少1。快速排序通过一趟扫描,就能确保某个数(以它为基准点吧)的左边各数都比它小,右边各数都比它大。然后又用同样的方法处理它左右两边的数,直到基准点的左右只有一个元素为止。public class quickSort { public static void quickSort(int[] array,int low,int high) { if(low < high){ int privotLoc = partition(array, low, high); //将表一分为二 quickSort(array,low,privotLoc -1); //递归对低子表递归排序 quickSort(array,privotLoc + 1,high); //递归对高子表递归排序 } } public static int partition(int a[], int low, int high) { int privotKey = a[low]; //基准元素 while(low < high){ //从表的两端交替地向中间扫描 while(low < high && a[high] >= privotKey) --high; //从high 所指位置向前搜索,至多到low+1 位置。将比基准元素小的交换到低端 swap(a,low,high); while(low < high && a[low] <= privotKey ) ++low; swap(a,low,high); } return low; } public static void swap(int[] a, int i,int j) { int tmp = a[i]; a[i] = a[j]; a[j] = tmp; } public static void main(String args[]){ int[] a={5,4,9,8,7,6,0,1,3,2}; quickSort(a,0,a.length-1); for(int i=0;i<a.length;i++){ System.out.print(a[i]+" "); } System.out.println(); } }
6、堆排序(Heap Sort)
堆排序是一种树形选择排序,在排序过程中,将A看成是完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。
/** * 堆排序 * * 首先使用建立最大堆的算法建立好最大堆, * 然后将堆顶元素(最大值)与最后一个值交换, * 同时使得堆的长度减小1 ,调用保持最大堆性质的算法调整, * 使得堆顶元素成为最大值,此时最后一个元素已被排除在外 */ public class heapSort { private static int heapSize;//元素个数 private static void maxHeapify( int[] array , int index ){ int left = 2*index;//左孩子 int right = 2*index+1;//右孩子 int largest; if( left < heapSize && array[ index ] < array[ left ]){ largest = left; }else{ largest = index; } if( right < heapSize && array[ right ] > array[ largest ]){ largest = right; } if( largest == index ){ return ; } else { int temp = array[ index ]; array[ index ] = array[ largest ]; array[ largest ] = temp; maxHeapify( array, largest ); } } /** * 建立最大堆。在数据中,array.length/2+1一直到最后的元素都是叶子元素, * 因此从其前一个元素开始,一直到第一个元素,重复调用maxHeapify函数,使其保持最大堆的性质 * @param array */ private static void buildMaxHeap(int[] array){ // 找出最小元素,并将其置于array[0] int min = array[0]; for(int i = 1 ; i < array.length ; i++ ){ if( min > array[i] ){ min = array[i]; array[i] = array[0]; array[0] = min; } } for( int i = array.length / 2 ; i >= 1; i-- ){ maxHeapify( array , i ); } } /** * 堆排序: */ public static void heapSort( int[] array ){ buildMaxHeap( array ); for(int i = array.length - 1 ; i >= 2 ; i--){ int temp = array[1]; array[1] = array[i]; array[i] = temp; heapSize--; maxHeapify( array , 1 ); } } public static void main(String args[]){ int[] a={5,4,9,8,7,6,0,1,3,2}; heapSize = a.length; heapSort(a); for(int i=0;i<a.length;i++){ System.out.print(a[i] + " "); } System.out.println(); } }
7、归并排序(Merge Sort)
设有两个有序(升序)序列存储在同一数组中相邻的位置上,不妨设为A[l..m],A[m+1..h],将它们归并为一个有序数列,并存储在A[l..h]。public class mergeSort { public static void MergeSort(int[] array,int p,int r){ if (p<r){ int q=(p+r)/2; MergeSort(array,p,q); MergeSort(array,q+1,r); Merge(array,p,q,r); } } public static void Merge(int[] array,int p,int q,int r){ int n1=q-p+1; int n2=r-q; int[] L=new int[n1]; int[] R=new int[n2]; for (int i=0;i<n1;i++){ L[i]=array[p+i]; } for (int i=0;i<n2;i++){ R[i]=array[q+1+i]; } int i,j,k=p; for (i=0,j=0;i<n1&&j<n2;k++){ if (L[i]<R[j]){ array[k]=L[i]; i++; }else{ array[k]=R[j]; j++; } } if (i<n1){ for (j=i;j<n1;j++,k++) array[k]=L[j]; } if (j<n2){ for (i=j;i<n2;i++,k++) array[k]=R[i]; } } public static void main(String args[]) { int[] a = {5, 4, 9, 8, 7, 6, 0, 1, 3, 2}; MergeSort(a,0,a.length-1); for (int i = 0; i < a.length; i++) { System.out.print(a[i] + " "); } System.out.println(); } }
相关文章推荐
- Selenium学习---(四)
- C语言的int最值问题,以及原码反码及补码
- Intellij IDEA Java web 项目搭建
- 表单Form传参数
- 面试题21包含min函数的栈
- UI简单页面设计 之 动画效果 (1)
- Mac无法调节声音
- 开关和灯泡的对应关系-二进制编码
- [原]无损有源钳位吸收
- leetcode 188: Best Time to Buy and Sell Stock IV
- JAVA问题总结之5-易错点之连接符和加号分析
- C#创建windows服务的步骤
- OK6410裸机开发2——更改软件源
- 移动web点5像素的秘密(转)
- Default debug keystore和Custom debug keystore的使用
- Java心得20
- linux的环境变量文件enviroment 、profile、bashrc和bash_profile的区别
- 集合
- 20150823 命令练习总结
- UI18_UICollectionView