算法基础(3)分治策略之快速排序

来源:互联网 发布:怎样才能恢复手机数据 编辑:程序博客网 时间:2024/05/22 08:03

快速排序是排序中的最佳实用选择,虽然在最坏情况下的时间复杂度为O(n^2), 但在随机输入的情况下,其时间复杂度为O(nlogn).

一、快速排序也是基于分治策略,其三个步骤为:

分解:将待排序数组A[p,r]分解为A[p,q]和A[q+1,r]两个数组,使得A[p,q]中的每个元素都小于A[q+1,r]中的每个元素。q值在分解中计算得到。

解决:通过递归调用对两个子数组A[p,q]和A[q+1,r]进行排序。

合并:无需合并,A[p,r]为已经排好的数组。

二、举个例子(想吃栗子了)

一个有7个待排元素的数组

1.让pivot = a[0]=5, 称为哨兵。通常取第一个元素。z,y为两个指针,分别从前、后扫描数组

2.进入循环,a[y] = a[6]<5,y不动;满足z<y,则a[z] = a[0] =a[y] = 4,z++;

3.a[z] = a[1] = 2<5,z++;a[z] = 6>5;满足z<y,则a[y] = a[6] =a[z] = 6,y--;

                       

4.a[y]<5,y不动;满足z<y;a[z] = a[y] = 3;z++;

5.a[z]<5,z++;a[z]>5;满足z<y;a[y] = a[z] = 7;y--;

                      

6.z=y,退出循环,a[z] = a[y] = pivot = 5;结束;呼得意

之后调用递归,对a[0]-a[3],a[5]-a[6]进行划分。

代码如下

#include<iostream>using namespace std;void quickSort(int *src, int low,int high){if(src == NULL) return ;int i,j,pivot;if(low < high){pivot = src[low];i = low,j = high;while(i < j){while(i<j && src[j] >= pivot) j--;src[i] = src[j];while(i<j && src[i] <= pivot) i++;src[j] = src[i];}src[i] = pivot;quickSort(src,low,i-1);quickSort(src,i+1,high);}}int main(){int src[] = {49,38,65,97,76,13,27,49};int i,low,high,cnt = sizeof(src)/4;quickSort(src,0,cnt-1);//输出for(i = 0; i < cnt; i ++) cout<<src[i]<<" ";cout<<endl;getchar();return 0;}

三、性能分析

1.最坏情况:每一次划分都是极不对称的,假设每次划分两个区域分别保护1个和n-1个元素(例如,原数组是以排好序的)。划分的时间代价为O(n),则

算法运行时间为T(n) = T(n-1)+O(n)

                               

2.最佳情况:对称划分,划分过程中产生的两个区域都包含n/2元素。

算法的运行时间T(n) = 2T(n/2)+O(n), 则T(n) = O(nlogn);

3.平均情况:快排的平均情况与最佳情况很接近,T(n) = O(nlogn);(证明可参看《算法导论》8.4,,其实记住就好了嘛)

原创粉丝点击