【数据结构】 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;        }    }}
原创粉丝点击