您的位置:首页 > 其它

快速排序

2017-06-02 17:47 218 查看
快速排序也是交换排序的一种。

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

假设待排序的记录序列为{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)。

快速排序是不稳定的排序算法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  快速排序