各种排序的比较
2015-06-15 00:35
302 查看
各种排序之间的比较
排序从数据结构上讲分为插入排序,交换排序,选择排序,归并排序,如下图
排序分为内部排序和外部排序,内部排序是排序过程中所有数据是放入内存进行处理的,外部排序是排序期间全部对象个数太多,不能同时放入你内存进行处理,需要不断在内外存进行移动的序列,下面讨论的是内部排序。
插入排序
插入排序的丝线格式将对象插入到前面已经排好序的子序列中。直到全部对象插入完成为止。
直接插入排序是初始化两个数组,一个数组的元素为原始序列,一个数组的元素为null ,引用arr[0]作为监视哨。直接插入排序是一种稳定的排序算法,时间复杂度为O(n^2)
public class InsertSort { public static void main(String []args){ int []arr={1,45,767,879,45,788,443 ,545,4,6,7,85}; int i,j; for(i=2;i<arr.length;i++){ arr[0]=arr[i]; j=i-1; while (arr[0]<arr[j]) { arr[j+1]=arr[j]; j--; } arr[j+1]=arr[0]; } for (int j2 = 1; j2 < arr.length; j2++) { System.out.print(arr[j2]+" "); } } }
希尔排序
希尔排序又称为缩小增量排序,它是一种对直接插入排序的改进,将整个子序列分成若干子序列分别进行直接插入排序。待整个序列基本有序后再对全部序列进行一次直接插入排序。
public class ShellSort {
public static void main(String []args) { int []arr={1,23,435,657,87,5,5,768,4453,778,32}; int i,j,d ,n=arr.length; for ( d = n/2; d >0; d=d/2) { for ( i = d+1; i <=n; i++) { arr[0] = arr[i]; j=i-d; while (j>=0&&arr[0]<arr[j]) arr[j+d]=arr[j]; j=j-d; arr[j+d]=arr[0]; } } for (int k = 1; k < arr.length-1; k++) { System.out.print(arr[k]+" "); }
}
}
交换排序
冒泡排序冒泡排序是一种最直观的排序方法,排序过程中,将相邻的元素进行比较,若前面的元素大于后面的元素,则将他们进行交换。冒泡排序是一种稳定的排序算法。时间复杂度为O(n^2).
public void sort(char arr[]){ int exchange=0; char temp='a'; for(int c=0;c<length;c++) { for(int ch=0; ch<arr.length()-1;ch++){ if(arr[ch]>arr[ch+1]){ temp=arr[ch]; arr[ch]=arr[ch+1]; arr[ch+1]=temp; exchange=1; } } if(exchange==0) break; } for (int d = 0; d < arr.length(); d++) { System.out.print(arr[d]); } }
快速排序
快速排序是对冒泡排序的一种改进,,在冒泡排序中,数据的移动是在相邻的两个元素之间,所以造成了移动次数较多。快速排序是从两端向中间进行的。其基本做法是选择排序中的一个元素为基准,一般选取第一个元素。通过一趟排序将带排序的记录分为左右两个子序列。左边的所有元素均小于或等于关键字,右边的所有元素均大于或等于关键字。
public class QuickSort { static int []arr={1,223,65,44,2,5,3,64,2,5}; static int high = arr.length; public static int Partition(int arr[],int low,int high){ arr[0] = arr[low]; while (low<high) { while (low<high&&arr[high]>=arr[0]) --high; arr[low]=arr[high]; while (low<high&&arr[low]<=arr[0]) arr[high]=arr[low]; } arr[low]=arr[0]; return low; } public static void Quicksort(int arr[],int low,int high){ int loc; if(low<high){ loc = Partition(arr,low,high); Quicksort(arr, low, loc-1); Quicksort(arr, loc+1, high); } } public static void main(String []args) { Quicksort(arr, 0, high); for (int i = 0; i < args.length; i++) { System.out.print(arr[i]); } } }
选择排序
简单选择排序简单选择排序也称直接选择排序,它先选出关键字最小的元素放在第一个位置,然后选出关键字第二小的元素放在第二个位置,依次….简单选择排序是一种不稳定的算法,时间复杂度为O(n^2)
public class SelectSort { public static void main(String []args) { int []arr = {1,3234,6788,7,66,89,57,5,6,95,3,6}; int n = arr.length-1; int i,j,min; for ( i = 1; i < n; i++) { min = i; for ( j = i+1; j <=n; ++j) if (arr[min]>arr[j]) min= j; if(min!=i) { arr[0]=arr[min]; arr[min]=arr[i]; arr[i]=arr[0]; } } for (int k = 1; k < arr.length; k++) { System.out.print(arr[k]+" "); } } }
堆排序
public class HeapSort { private static int[] sort = new int[]{1,0,10,20,3,5,6,4,9,8,12,17,34,11}; public static void main(String[] args) { buildMaxHeapify(sort); heapSort(sort); print(sort); } private static void buildMaxHeapify(int[] data){ //没有子节点的才需要创建最大堆,从最后一个的父节点开始 int startIndex = getParentIndex(data.length - 1); //从尾端开始创建最大堆,每次都是正确的堆 for (int i = startIndex; i >= 0; i--) { maxHeapify(data, data.length, i); } } /** * 创建最大堆 * @param data * @param heapSize需要创建最大堆的大小,一般在sort的时候用到,因为最多值放在末尾,末尾就不再归入最大堆了 * @param index当前需要创建最大堆的位置 */ private static void maxHeapify(int[] data, int heapSize, int index){ // 当前点与左右子节点比较 int left = getChildLeftIndex(index); int right = getChildRightIndex(index); int largest = index; if (left < heapSize && data[index] < data[left]) { largest = left; } if (right < heapSize && data[largest] < data[right]) { largest = right; } //得到最大值后可能需要交换,如果交换了,其子节点可能就不是最大堆了,需要重新调整 if (largest != index) { int temp = data[index]; data[index] = data[largest]; data[largest] = temp; maxHeapify(data, heapSize, largest); } } /** * 排序,最大值放在末尾,data虽然是最大堆,在排序后就成了递增的 * @param data */ private static void heapSort(int[] data) { //末尾与头交换,交换后调整最大堆 for (int i = data.length - 1; i > 0; i--) { int temp = data[0]; data[0] = data[i]; data[i] = temp; maxHeapify(data, i, 0); } } /** * 父节点位置 * @param current * @return */ private static int getParentIndex(int current){ return (current - 1) >> 1; } /** * 左子节点position注意括号,加法优先级更高 * @param current * @return */ private static int getChildLeftIndex(int current){ return (current << 1) + 1; } /** * 右子节点position * @param current * @return */ private static int getChildRightIndex(int current){ return (current << 1) + 2; } private static void print(int[] data){ int pre = -2; for (int i = 0; i < data.length; i++) { if (pre < (int)getLog(i+1)) { pre = (int)getLog(i+1); System.out.println(); } System.out.print(data[i] + " |"); } } /** * 以2为底的对数 * @param param * @return */ private static double getLog(double param){ return Math.log(param)/Math.log(2); }
}
归并排序
下面图片和代码来自维基百科public int[] Two_Way_Merge_Sort(int[] A, int[] B) { int[] C = new int[A.length + B.length]; int k = 0; int i = 0; int j = 0; while(i < A.length && j < B.length) { if (A[i] < B[j]) C[k++] = A[i++]; else C[k++] = B[j++]; } while (i < A.length) C[k++] = A[i++]; while (j < B.length) C[k++] = B[j++]; return C; } /** * one good implements. <br /> * * */ public class Sort { public static final int CUTOFF = 11; /** * merge sort algorithm. * * @param arr an array of Comparable item. * 1.here only use one temp array (think about it). <br /> * 2.copy the element back after the sub merge operation. @see merge(T, T, int, int); * the above two points make it more efficient. <br /> */ @SuppressWarnings("unchecked") public static <T extends Comparable<? super T>> void mergeSort( T[] arr ) { //you may use insertionSort instead when the arr.length is not that large. /*if ( arr.length < CUTOFF ) { insertionSort( arr ); return; }*/ T[] tmpArr = (T[]) new Comparable[arr.length]; mergeSort(arr, tmpArr, 0, arr.length - 1); } /** * internal method to make a recursive call to merge. <br /> * * @param arr an array of Comparable items. <br /> * @param tmpArr temp array to placed the merged result. <br /> * @param left left-most index of the subarray. <br /> * @param right right-most index of the subarray. <br /> */ private static <T extends Comparable<? super T>> void mergeSort( T[] arr, T[] tmpArr, int left, int right ) { //recursive way if ( left < right ) { int center = ( left + right ) / 2; mergeSort(arr, tmpArr, left, center); mergeSort(arr, tmpArr, center + 1, right); merge(arr, tmpArr, left, center + 1, right); } //loop instead,not working, do it youself. /* int n = 0, j; while ( true ) { int step = ( int ) Math.pow(2, ++n); int len = step / 2; int count = arr.length / step; int rpos; //previous pow(2, k) elements for ( j = 0; j < count; j++ ) { rpos = j + len; System.out.println(j+", "+rpos); merge( arr, tmpArr, j, rpos, rpos + len - 1); } //the rest elements //for () ; if ( step * 2 >= arr.length ) break; } */ } /** * internal method to merge the sorted halves of a subarray. <br /> * * @param arr an array of Comparable items. <br /> * @param tmpArr temp array to placed the merged result. <br /> * @param leftPos left-most index of the subarray. <br /> * @param rightPos right start index of the subarray. <br /> * @param endPos right-most index of the subarray. <br /> */ private static <T extends Comparable<? super T>> void merge( T[] arr, T[] tmpArr, int lPos, int rPos, int rEnd ) { int lEnd = rPos - 1; int tPos = lPos; int leftTmp = lPos; while ( lPos <= lEnd && rPos <= rEnd ) { if ( arr[lPos].compareTo( arr[rPos] ) <= 0 ) tmpArr[ tPos++ ] = arr[ lPos++ ]; else tmpArr[ tPos++ ] = arr[ rPos++ ]; } //copy the rest element of the left half subarray. while ( lPos <= lEnd ) tmpArr[ tPos++ ] = arr[ lPos++ ]; //copy the rest elements of the right half subarray. (only one loop will be execute) while ( rPos <= rEnd ) tmpArr[ tPos++ ] = arr[ rPos++ ]; //copy the tmpArr back cause we need to change the arr array items. for ( ; rEnd >= leftTmp; rEnd-- ) arr[rEnd] = tmpArr[rEnd]; } }
总结:各种排序算法的比较
排序方法 | 最好时间 | 时间复杂度 | 最坏时间 | 辅助空间 | 稳定性 | ||||||
---|---|---|---|---|---|---|---|---|---|---|---|
直接插入排序 | O(n) | O(n^2) | O(n^2) | O(1) | yes | ||||||
冒泡排序 | O(n) | O(n^2) | O(n^2) | O(1) | yes | ||||||
快速排序 | O(nlog(n,2)) | O(n^2) | O(nlog(n,2)) | O(nlog(n,2)) | no | ||||||
简单选择排序 | O(n^2) | O(n^2) | O(n^2) | O(1) | no | ||||||
堆排序 | O(nlog(n,2)) | O(nlog(n,2)) | O(nlog(n,2)) | O(1) | no | ||||||
两路归并排序 | O(nlog(n,2)) | O(nlog(n,2)) | O(nlog(n,2)) | O(n) | yes |
相关文章推荐
- Intellij IDEA 下有些中文变成了小方块
- Path相关方法讲解(一)
- 继承中的类型兼容性原则
- 继承中的类型兼容性原则
- import cx_Oracle 错误: ImportError: DLL load failed: %1 不是有效的 Win32 应用程序。(暂未解决)
- Javascript:是你的高阶函数
- 一些数字音频的基础定义
- 需找字符串中重复的最长子串
- 有效地进行网站优化推广所需要的最少时间
- vs2010程序运行出错 link : fatal error lnk1123: 转换到 coff 期间失败: 文件无效或损坏
- ActionContext、ValueStack、Stack Context之间的关系
- 隔行变色
- Java for each
- 《出彩中国人》的平衡术表演
- How to undo (almost) anything with Git
- JPA和Hibernate的关系
- 用hibernate分页查询的底层方法
- CentOS网络问题汇总
- iOS项目立项
- xml解析