快速排序

来源:互联网 发布:cm和魔趣哪个优化好点 编辑:程序博客网 时间:2024/06/05 00:42

快速排序也是交换排序的一种。

快速排序的基本思想是,通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。


假设待排序的记录序列为{r[low],r[low +1 ],r[low +2],.....r[high]},首先在该序列中任意选择一个记录(该记录成为支点,通常选r[low]作为支点),然后将所有关键字比支点小的记录都放在支点的左边,将所有关键字比支点大的记录放到支点的右边,由此可以将该支点最后所落的位置i作为分界线,将记录{r[low],r[low +1 ],r[low +2],.....r[high]}分割为两个部分{r[low],r[low +1 ],r[low +2],.....r[i-1]}和{r[i+1],r[i+2]........r[high]},这个过程称为一次划分(一趟快速排序)。通过一趟快速排序,支点记录就落在了最终排序结果的位置上了。


一趟快速排序的步骤如下:

(1)设置两个变量i和j,初值分别为low和high,分别表示待排序序列的起始下标和终止下标。

(2)将第i个记录设置成为支点,将关键字值暂存在变量pivot中,即pivot = r[i]。

(3)从下标为j的位置开始从后向前依次搜索,当找到第一个比pivot小的记录时,将该记录复制到下标为i的位置上,然后i=i+1。

(4)从下标为i的位置起向后依次搜索,当找到比pivot大的记录时,将该记录复制到下表为j的位置上,再令j=j-1。

(5)重复(3)、(4)步骤,直到i==j为止。

(6)将pivot置于最终位置,r[i] = pivot。




一趟快排划分的代码如下:

public int partition(int[] array, int start, int end) {int i = start;int j = end;int temp = 0;if (i < j) {temp = array[i];while (i != j) {while (array[j] > temp && i < j) {j--;}if (i < j) {array[i] = array[j];i++;}while (array[i] < temp && i < j) {i++;}if (i < j) {array[j] = array[i];j--;}}array[i] = temp;}return i;}


public static void qSort(int[] arr, int start, int end) {if (start < end) {int pivot = partition(arr, start, end);qSort(arr, start, pivot - 1);qSort(arr, pivot + 1, end);}}


算法性能分析:

(1)空间复杂度:快速排序在系统内部需要一个栈来实现递归,每层递归调用的指针和参数均需要用栈来存放。快速排序的递归过程可以用一棵二叉树来表示。若每次划分较为均匀,则其递归树的高度为O(logn),故所需栈空间为O(logn),最坏情况下,即递归树为一个单枝树,书的高度为O(n),其空间复杂度为O(n)。

(2)时间复杂度:在含有n个记录的排序序列中,每进行一次划分需要进行n此比较,时间复杂度为O(n)。最好情况下,每次划分正好是两个等长的子序列,T(n) <=cn +2T(n/2),即T(n)<= cnlogn + nT(1)=O(nlogn)。最坏情况下,当关键字序列有序或者基本有序,在快速排序过程中每次划分只能得到一个子序列,这样快速排序反而退化为冒泡排序,时间复杂度为O(n^2)。

快速排序是不稳定的排序算法