快速排序算法总结

来源:互联网 发布:java从入门到精通 编辑:程序博客网 时间:2024/06/05 17:26

  • Quick Sort
    • 翻译部分
      • 综述
      • Partition
      • Pivot 算法
      • 快排中的找pivot的伪代码
      • 快排的伪代码
    • Java实现

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 leftPointerend 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 ifend 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;  }