快速排序算法总结

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/paulkg12/article/details/78408296

Quick Sort

翻译部分

综述

快速排序是基于Partition(分区处理)的高效排序算法,或许也可以说是分而治之的思想。

他会把数组分割成两个小的数组,一个数组保有小于pivot(枢纽)的元素,一个数组保有大于pivot的元素。

快排会对分区调用自身再次处理,这就是递归。

这个算法是很有效率的,平均和最坏的复杂度都是O(nlogn),n就是有多少个元素。快排对于处理海量数据很好。

Partition

你可以观看DATA_Struct app 上的动画,来理解partition的原理。

Pivot 算法

步骤大致如下:

  1. 选择最高位(最后一位,其实第一位也行,必然行)的元素作为pivot(枢纽)
  2. 召唤两个变量来指向左和右
  3. 左边的指针指向低位的索引
  4. 右边的指针指向高位的索引
  5. 当左边指针指向的元素小于pivot元素,左边指针不断右移
  6. 当右边指针指向的元素大于pivot元素,右边指针不断左移
  7. 当左右指针遇到他们理想的元素(左遇大,右遇小)便交换他们
  8. 如果发现左边的指针位置>=右边指针的位置,他们就是相遇了,这个相遇的地方就是新的pivot
  9. pivot会作为partition函数的返回值返回,继续partition

快排中的找pivot的伪代码


function partitionFunc(left, right, pivot)
  lefPointer = left - 1
  rightPointer = right

  while TRUE do
    while A[++leftPointer] < pivot do
    //actually do nothing
    end while

    while rightPointer > 0 && A[--rightPointer] > pivot do
    //actually do nothing
    end while

    if leftPointer >= rightPointer
      break
    else
      swap leftPointer, rightPointer
    end if
  end while

  swap leftPointer, right

  return leftPointer
end function      

快排的伪代码

基于我们给出上述的pivot求解代码,使用之,我们会得到更小的分区,每个分区再使用quickSort,以递归的方式,最终就这样解决问题了。

我们可以如下来写quickSort的算法

  1. 让最右侧的索引作为pivot
  2. 对整个数组partition(会得到左右两个partition后的小数组)
  3. 对左侧数组快排
  4. 对右侧数组快排

    • 快排的具体伪代码

procedure quickSort(left, right)
  if right - left <= 0
    return
  else
      pivot = A [right]
      partition = partitionFunc(left, right, pivot)
      quickSort(left, partition - 1)
      quickSort(partition + 1, right)
  end if
end procedure  

Java实现


public class QuickSort {  

    public static void quickSort(int[] array){  
        if(array != null){  
            quickSort(array, 0, array.length-1);  
        }  
    }  

    private static void quickSort(int[] array,int beg,int end){  
        if(beg >= end || array == null)  
            return;  
        int p = partition(array, beg, end);  
        quickSort(array, beg, p-1);  
        quickSort(array, p+1, end);  
    }  
}  

上面就是快排主要的框架,最重要就是partition方法,它是划分并找到下次分割排序的位置p

常用的partition方法


//方法一:形象地来说是:
// 以first作为pivot,i去往后寻找一个大于first的元素
//j从end往前寻找一个小于first的元素
//i,j都发现了自己希望的元素,便停下来,交换。
private static int partition(int[] array, int beg, int end) {  
        int first = array[beg];  
        int i = beg, j = end;  
        while (i < j) {  
            while (array[i] <= first && i < end) {  
                i++;  
            }  
            while (array[j] > first && j >= beg) {  
                j--;  
            }  
            if (i < j) {  
                array[i] = array[i] ^ array[j];  
                array[j] = array[i] ^ array[j];  
                array[i] = array[i] ^ array[j];  
            }  
        }  
        if (j != beg) {  
            array[j] = array[beg] ^ array[j];  
            array[beg] = array[beg] ^ array[j];  
            array[j] = array[beg] ^ array[j];  
        }  
        return j;  
}  

第二种partition方法实现


//这个形象来说是:i作为一个拖后腿的小兵,而j是一个也是从beg开始的大将,j它会
//在前方寻找array[j] <= array[end]的元素(小的,老弱病残的元素),再让i接手
private static int partition(int[] array,int beg,int end){  
        int last = array[end];  
        int i = beg -1;  
        for (int j = beg; j <= end-1; j++) {  
            if(array[j] <= last){  
                i++;  
                if(i != j){  
                    array[i] = array[i]^array[j];  
                    array[j] = array[i]^array[j];  
                    array[i] = array[i]^array[j];  
                }  
            }  
        }  
        if((i+1) != end){  
            array[i+1] = array[i+1]^array[end];  
            array[end] = array[i+1]^array[end];  
            array[i+1] = array[i+1]^array[end];  
        }  
        return i+1;  
}  

猜你喜欢

转载自blog.csdn.net/paulkg12/article/details/78408296