【数据结构】 MergeSort与QuickSort的详细分析
来源:互联网 发布:美发预约软件 编辑:程序博客网 时间:2024/05/21 04:42
转自:http://blog.csdn.net/qt_pixie/article/details/1361777
MergeSort和QuickSort是两种比较类似的sort方式,他们都是通过Divide and Conquer来实现的。都需要使用recursion的方式进行排序。
他们的相同之处在于原理上一致。首先要做的是split,将N个element分成两部分进行排序,每一部分也会再继续分成两部分排序,直到只有2个element的时候就可以很容易的比较排序。这个就是recursion的使用方法。属于Divide and Conquer中的Divide部分。当N个element被分解为很多个小部分进行排序后,要做的就是把他们再合并起来组成排好顺序的list. 这个就是merge,或者说是Conquer。这两种Sort都需要merge这一步骤,但是细节不同。下面就来分析一下两种sort的区别之处。
MergeSort的split比较简单,将所有element以binary的方式分开,就是说分开后左边与右边element的个数是相等的,或者相差为1(比如总共有5个element的时候,分成左边3个右边2个)。divide过程的复杂度只需计算为1就可以了。而MergeSort的Conquer(Merge)部分则相对复杂。当所有element被分为很多个小部分进行排序后,每个小部分里面的element都是排好顺序的,然后需要和另一个小部分里的element排序。因为在split的时候是以binary方式分开的,左边和右边的element没有任何大小关系,所以在合并的过程中需要将左边部分的element与右边部分的element逐一比较然后存储在一个新的list里面。这样,合并过程的复杂度为N。MergeSort的复杂度为N+2T(N/2). (这里的第一个N是指merge的复杂度)。经过进一步计算得到的复杂度为NlgN.
QuickSort的split比较复杂,而且有多种方法,方法一:使用第一个element做为pivot,然后把小于这个pivot的所有element放在左边,大与他的放在右边,这样得到的两个部分左边任意element都比右边任意element小。方法二:使用中间值的方法作为pivot,(IndexOfBegin+IndexOfEnd)/2。我们选择pivot的标准是尽量选择不大不小接近中间的element,这样根据这个pivot所分开的两部分的数量不会相差太大。如果使用方法一,而list中的element刚好又是sorted的,那divide分开的两部分数量悬殊,算法复杂度非常高,为N*N。一般情况,QuickSort的split的复杂度为N. 假设QuickSort的split方法分开后的所有小部分为a,b,c… 那么a中的所有element都比b中的小,b中的所有element比c中的小。这样在合并的时候非常简单,只要把a,b,c…里的element排好顺序,然后把b直接放在a后面就好了。这里的复杂度只有1。所以整个QuickSort的复杂度为N+2T(N/2)这里的第一个N指split的复杂度。经过计算得到的复杂度为NlgN.
总体来说,MergeSort的split方便merge复杂,QuickSort的split复杂merge简单。了解原理后就可以根据不同情况选择不同的排序方法。
代码转自:http://blog.csdn.net/dream_mushuang/article/details/71104076
Merge Sort:
package mergeSort;import java.util.Random;/** * Array are rearranged with smallest item first * @author * */public class MergeSort { private static final int NUM_ITEMS = 30; private static final Random rnd = new Random(); public static void main(String[] args) { Integer[] a = new Integer[NUM_ITEMS]; for(int i=0; i<a.length; i++){ a[i] = i; } permute(a); print(a); System.out.println("Merge Sort"); mergeSort(a); print(a); } private static void print(Integer[] a){ for(int i=0; i<a.length; i++){ System.out.print(a[i]+" "); } System.out.println("\ndone....\n"); } public static <T extends Comparable<? super T>> void insertionSort(T[] array, int left, int right){ for(int p= left+1; p<= right; p++){ T tmp = array[p]; int j; for(j=p; j>left && tmp.compareTo(array[j-1])<0; j--){ array[j] = array[j-1]; array[j] = tmp; } } } public static <T extends Comparable<? super T>> void mergeSort(T[] a){ @SuppressWarnings("unchecked") T[] tmpArray = (T[]) new Comparable[a.length]; mergeSort(a, tmpArray, 0, a.length-1); } /** * Internal method that makes recursive calls * @param a an array of Comparable items * @param tmpArray an array to place the merged result * @param left the left-most index of the subarray * @param right the right-most index of the subarray */ private static <T extends Comparable<? super T>> void mergeSort(T[] a, T[] tmpArray, int left, int right){ if(left < right){ int center = (left + right)/2; mergeSort(a, tmpArray, left, center); mergeSort(a, tmpArray, center+1, right); merge(a, tmpArray, left, center+1, right); } } /** * Internal method that merges two sorted halves of a subarray * @param a * @param tmpArray an array to place the merged result * @param leftPos * @param rightPos the index of the start of the second half * @param rightEnd */ private static <T extends Comparable<? super T>> void merge(T[] a, T[] tmpArray, int leftPos, int rightPos, int rightEnd){ int leftEnd = rightPos - 1; int tmpPos = leftPos; int numEles = rightEnd - leftPos + 1; //Merge while(leftPos <= leftEnd && rightPos <= rightEnd){ if(a[leftPos].compareTo(a[rightPos])<=0){ tmpArray[tmpPos++] = a[leftPos++]; }else{ tmpArray[tmpPos++] = a[rightPos++]; } } //copy rest of first half while(leftPos <= leftEnd){ tmpArray[tmpPos++] = a[leftPos++]; } //copy rest of right half while(rightPos <= rightEnd){ tmpArray[tmpPos++] = a[rightPos++]; } //copy tmpArray back for(int i=0; i<numEles; i++, rightEnd--){ a[rightEnd] = tmpArray[rightEnd]; } } public static void permute(Integer[] array){ int size = array.length; for(int index = size-1; index>=0; index--){ //swap(rnd.nextInt(index+1), index); int rndPos = rnd.nextInt(index+1); int tmp = array[rndPos]; array[rndPos]= array[index]; array[index] = tmp; } }}
The most important thing is to choose proper pivot!!!
QuickSort:
import util.SortUtil;public class QuickSort { public static void main(String[] args) { int[] a = new int[30]; for(int i=0; i<a.length; i++){ a[i] = i; } SortUtil.permute(a); SortUtil.print(a); quickSort(a); SortUtil.print(a); } public static void quickSort(int[] array){ subQuickSort(array, 0, array.length-1); } public static void subQuickSort(int[] array, int start, int end){ if(array==null || (end-start+1)<2){ return; } int part = partition(array, start, end); if(part==start){ subQuickSort(array, part+1, end); }else if(part==end){ subQuickSort(array, start, part-1); }else{ subQuickSort(array, start, part-1); subQuickSort(array, part+1, end); } } private static int partition(int[] array, int start, int end){ int value = array[end]; int index = start-1; for(int i=start; i<end; i++){ if(array[i]<value){ index++; if(index != i){ SortUtil.swap(array,index, i); } } } if((index+1)!=end){ SortUtil.swap(array, index+1, end); } return index+1; }}package util;import java.util.Random;public class SortUtil { private static final Random rnd = new Random(); public static void swap(int[] array, int aPos, int bPos){ int temp = array[aPos]; array[aPos] = array[bPos]; array[bPos] = temp; } public static void print(int[] a){ for(int i=0; i<a.length; i++){ System.out.print(a[i]+" "); } System.out.println("\ndone....\n"); } public static void permute(int[] array){ int size = array.length; for(int index = size-1; index>=0; index--){ //swap(rnd.nextInt(index+1), index); int rndPos = rnd.nextInt(index+1); int tmp = array[rndPos]; array[rndPos]= array[index]; array[index] = tmp; } }}
- 【数据结构】 MergeSort与QuickSort的详细分析
- MergeSort与QuickSort的详细分析
- MergeSort与QuickSort的详细分析
- MergeSort与QuickSort
- MergeSort和QuickSort的比较
- QuickSort & MergeSort & InsertionSort
- insertSort,quickSort,mergeSort
- QuickSort 和 MergeSort
- QuickSort 快速排序的分析与实现
- 单链表的排序 快速排序 归并排序 quicksort mergesort
- 基本代码 QuickSort MergeSort Binary
- (算法设计技巧与分析)MergeSort
- 数据结构--归并排序(MergeSort)思想与实现
- (算法设计技巧与分析)QuickSort
- 数据结构与算法的分析
- 温习数据结构(1):MergeSort
- java数据结构和算法(MergeSort)
- 快速排序 (QuickSort) Java数据结构与算法
- Android API24以上Error inflating class android.support.design.widget.TabLayout
- 关于C里面宏替换的问题
- socket
- 【学习笔记】第一章:Java服务端编程15、Servlet概念详解
- fgets实现行号的统计
- 【数据结构】 MergeSort与QuickSort的详细分析
- IntelliJ IDEA使用(1)——IDEA配置JDK
- 单例模式
- sudo apt-get update 出错 E: Could not get lock /var/lib/apt/lists/lock
- 2017.9.17 function 思考记录
- windows 无法结束进程怎么办?怎样强制结束进程
- TensorFlow入门--安装常用的算法模块
- Git学习笔记五:Git分支管理策略
- Android的错误集合