二路归并排序

来源:互联网 发布:libevent源码怎么读 编辑:程序博客网 时间:2024/06/06 03:48

交换排序:冒泡排序、快速排序(改进的)

1、基本思想:确定一个基准值,将所有元素划分为两个序列,前一序列元素比基准值小,后一序列元素比基准值大,再对两个子序列进行相同操作,每次划分都将确定一个基准值的最终位置。

2、标准快排(挖坑法)实现步骤:

  • 假设数组为array,将每个序列的 第一个值作为基准值pivot;
  • 初始化i,j:i为第一个元素所在位置,j为最后一个元素所在位置,当前坑为array[i];
  • 如果array[j]>=pivot,那么j--, 否则array[i] = array[j],i++,当前坑为array[j];
  • 如果array[i]<=pivot,那么i++,否则array[j] = array[i],j--,当前坑为array[i];
  • 对于其余子序列也做相同操作,先j变化再i变化,直到i==j为止。

3、代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public void quickSort(int[] array){
    sort(0,array.length-1,array);
}
private void sort(int left,int right,int[] array){
    if(left<right){
        int pivotPos = partion(left,right,array);
        sort(left,pivotPos-1,array);
        sort(pivotPos+1,right,array);
    }
}
private int partion((int left,int right,int[] array){
    int pivotPos = left;  //
    int pivot = array[left]; //
    int i = left,i = right;
    while(i<j){
        while(i<j && array[j]>=pivot)
         j--;
        if(i<j){
            array[i= array[j];  ////ji
            i++;
        }
        while(i<j && array[i]<=pivot////
            i++;
        if(i<j){
            array[j= array[i]; ////ij
            j--;
        }
    }
    pivotPos = i//i,j
    array[pivotPos= pivot;
    return pivotPos
}

 

4、时间复杂度

(1)最好情况:每次划分都从中间分成相等的两个子序列。每次定位基准值的位置需要的时间为O(n),那么

   T(n) <= cn + 2T(n/2) = cn + 2(cn/2 + 2T(n/4)) = 2cn+4T(n/4)=2cn+4(cn/4+2T(n/8))=3cn+8T(n/8)=cnlogn+nT(1)=O(nlogn)

   从另一个角度来看,快速排序的过程实际就是一棵递归树,树的深度logn就是递归的次数,每次对O(n)个元素排序,所以时间复杂度为O(nlogn);

(2)最坏情况:元素按照正序排列,每次划分后都只排序好基准值左边的序列,需要对右边的序列继续划分,则划分次数总共为n-1次,每次划分需要比较n-k次(1<k<n-1),那么

   T(n) = n-1+n-2+n-3+...+1 = n(n-1)/2 = O(n^2)

(3)平均情况:T(n) = O(nlogn)

5、空间复杂度

每次递归都要是用一个栈,所以空间复杂度为O(logn)

6、稳定性:不稳定

7、改进快排

  改进快排的着手点主要在基准值的选取上,基准值要选取的尽量能将序列划分均匀。

(1)对于每个序列,比较第一个元素、中间元素和最后一个元素的值,取值居中的一个数作为基准值,将第一个数与值居中的这个数交换位置。

代码实现:

private int partion (int leftint rightint[] array){
    //
    int mid = (left+right)/2;
    int a = array[left];
    int b = array[right];
    int c = array[mid];
    int pivot = a>b?(a>c?((b>c)?b:c):a):(a>c?a:(b>c:c:b));
    int pivotPos = left;
    if(pivot==b)
    pivotPos = right;
    else if(pivot==c)
    pivotPos = mid;
    //
    if(pivotPos!=left){
        int temp = array[pivotPos];
        array[pivotPos= array[left];
        array[left= temp;
        pivotPos = left;
    }
    int i=left,j=right;
    while(i<j){
        while(i<j && array[j]>=pivot)
        j--;
        if(i<j &){
            array[i= array[j];
            i++;
        }
        while(i<j && array[i]<=pivot)
        i++;
        if(i<j){
            array[j= array[i];
            j--;
        }
    }
    pivotPos = i;
    array[pivotPos= pivot;
    return pivotPos;
}

(2)对于每个序列,随机选取从头到尾的一个随机数作为基准值,这种排序叫做随机快速排序。

 

 

 

 

 

原创粉丝点击