您的位置:首页 > 产品设计 > UI/UE

快速(quick)排序算法

2016-07-15 18:22 323 查看
快速排序是不稳定的排序。

1、快速排序的基本思想

快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常撑起为分治法。分治法的基本思想是:将原问题分解为若规模更小但结构与原问题相似的子问题。递归地解决这些子问题,然后将这些子问题的解组合为原问题的解。

快速排序的基本思想:设当前的待排序的无序区为A[low..high],利用分治可描述为:

(1) 分解:

在A[low...high]中任选一个记录作为基准(pivot也叫中轴或者枢纽),依此基准将当前无序区划分为左、右两个较小的自取件A[low...pivot[pos-1]]和A[pivot[pos+1]...high]

并使左边子区间中所有记录的关键字均小于基准记录(pivot),右边的子区间中所有记录的关键字均大于等于pivot,而基准的记录pivot则位于正确的位置上,它无需在参加后续的排序。注意,划分的关键是要求出基准记录所在的位置pivot[pos]。划分的结果可以简单的表示为:A[low...pivot[pos-1]]<=A[pivot[pos]]<=A[pivot[pos+1]...high],其中low<=pivot[pos]<=high。

(2) 求解:

通过递归调用快速排序对左右子区间A[low...pivot[pos-1]]和A[pivot[pos-1]+1...high]排序。

(3) 组合:

当“求解”步骤中的两个递归调用结束时,子左右两个子区间已有序。对排序排序而言,“组合”步骤无需做什么,可以看做空操作。

2、思想

它是由冒泡排序改进而来的。在待排序的n个记录中任取一个记录(通常取第一个记录),把该记录放入适当位置后,数据序列被此记录划分成两部分。所有关键字比该记录关键字小的记录放置在前一部分,所有比它大的记录放置在后一部分,并把该记录排在这两部分的中间(称为该记录归位),这个过程称作一趟快速排序。



说明:最核心的思想是将小的部分放在左边,大的部分放到右边,实现分割。

3、算法复杂度

最好的情况下:因为每次都将序列分为两个部分(一般二分都复杂度都和logN相关),故为 O(N*logN)

最坏的情况下:基本有序时,退化为冒泡排序,几乎要比较N*N次,故为O(N*N)

4、稳定性

由于每次都需要和中轴元素交换,因此原来的顺序就可能被打乱。如序列为 5 3 3 4 3 8 9 10 11会将3的顺序打乱。所以说,快速排序是不稳定的!

5、代码实现

<pre name="code" class="cpp">//编程实现快速排序
//1.快速排序是比较复杂的排序,其中需要知道数组的下标,低位下标要是大于高位下标的话,不进行排序
//2.其中每次取第一个数当做分割点pivot=a[low],循环到低位下标大于高位下标终止循环,这样就确定了pivot的位置。
//3.遍历pivot右边的元素(a[j]>=pivot),若小于pivot将元素放到pivot的左边(a[i++]=a[j]),第一次放的位置为low.
//4.之后遍历low右侧的元素,若大于pivot将元素放到pivot的右边(a[j--]=a[i]),第一次放的位置为high.
//5.3、4步的大前提是低位下标小于高位下标.
//6.终止循环之后,将pivot放到中间位置(a[i]=pivot).
//7.再将low到i-1,也就是pivot的左侧进行同样排序,i+1到high,pivot的右侧进行同样排序。

#include<iostream>
using namespace std;

void quick_sort(int a[], int low, int high) //low和high均为数组的下标
{
//因为在递归的时候需要low和high的位置,所以需要拷贝low和high
int i; //第一个元素下标
int j; //最后一个元素下标
int pivot; //pivot是区间的第一个元素,也是快速排序的枢纽(以他为中间元素,在他的左边元素都是小于他的,右边的元素都是大于他的)
if (low < high) //递归的终止条件是,区间完全重合
{
pivot = a[low];
i = low;
j = high;
while (i < j) //找到中间位置(快速排序的终止条件)
{
while (i < j && a[j] >= pivot) //筛选比pivot小的元素
j--;
if (i < j) //中间位置大前提
a[i++] = a[j]; //将比pivot小的元素赋给区间的第一个元素

while (i < j && a[i] <= pivot) //筛选比pivot大的元素
i++;
if (i < j) //中间位置大前提
a[j--] = a[i]; //将比pivot大的元素赋给比pivot小的元素位置
}
a[i] = pivot; //pivot移到最终位置,枢纽中间位置
quick_sort(a, low, i - 1); //对左侧递归排序
quick_sort(a, i + 1, high); //对右侧递归排序
}
}

static void print_sort(int a[], int len)
{
for (int i = 0; i < len; i++) <span style="white-space:pre"> </span>//打印数组
cout << a[i] << " ";
}
void main9mianshiti4()
{
int a[] = { 83, 38, 96, 23, 15, 72, 60, 45, 54 };
cout << "before quick sort:";
print_sort(a, 9); //打印数组
quick_sort(a, 0, 8); //快速排序
cout << "\nafter quick sort:";
print_sort(a, 9);
system("pause");
}


6、测试结果

before quick sort:83 38 96 23 15 72 60 45 54

after quick sort:15 23 38 45 54 60 72 83 96
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息