c++实现快速排序

来源:互联网 发布:mac高光修容液 编辑:程序博客网 时间:2024/06/03 17:28

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

2、快排步骤:

①分解: 
    
 在R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无须参加后续的排序。
 注意:划分的关键是要求出基准记录所在的位置pivotpos。划分的结果可以简单地表示为(注意pivot=R[pivotpos]): R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys     其中low≤pivotpos≤high。

②求解: 
     
通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。

③组合: 
    
 因为当"求解"步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言,"组合"步骤无须做什么,可看作是空操作。

通俗理解核心步骤:

1.i =L; j = R; 将基准数备份形成第一个可以看成空值的a[i]。

2.j--由后向前找比它小的数,找到后把此数填前一个a[i]中。

3.i++由前向后找比它大的数,找到后也把此数填到前一个坑a[j]中。

4.再重复执行2,3二步,直到i==j,将基准数填入a[i]中

3、算法性能

时间复杂度:O(n*lgn)
最坏:O(n^2)
空间复杂度:O(n*lgn)
不稳定。

实现代码:

//先上递归版#include <stdio.h>#include <stdlib.h>#include <iostream>#include <time.h>#include <stack>
using namespace std;#define  MAX 101int Partition(int num[], int low, int high){                                 //int pivotkey;这个枢轴的选取很关键,改进版的可以用三数取中,就九数取中等int pivotkey = num[low];         //在这里就取第一个元素num[0] = pivotkey;               //备份到num【0】,while (low < high){while (low < high&&num[high] >= pivotkey)high--;num[low] = num[high];            //不满足循环条件就执行这个语句,因为备份出【low】,所以可以覆盖他,这也是这个while在                                                 //前面的原因。否则【high】会丢失的。while (low < high&&num[low] <= pivotkey)low++;num[high] = num[low];                             //交换low,是因为low=pivotkey,比较了。}num[low] = num[0];return low;                         //最后high和low在某一个位置相遇,就是切分部的值。}void Qsort1(int num[], int low, int high)   //对随机产生的无序数组进行快速排序,这也是二分法的缺陷之一。{                                           //快排对很多数据更有优势,可以设置一个数据个数的阈值,才进行快排,这里也是一个优化的地方int pivot;//if (low < high){pivot = Partition(num, low, high);   //轴值所在的位置Qsort1(num, low, pivot - 1);         //递归的深度决定了时间的复杂度。Qsort1(num, pivot + 1, high);}}//非递归版,模拟栈的inline void push2(stack<int> &s, int l, int r){s.push(r);s.push(l);}void Qsort(int num[], int l, int r){stack<int> s;push2(s, l, r);int lwalker, rwalker, mid;while (!s.empty()){int left = s.top(); s.pop();int right = s.top(); s.pop();lwalker = left;rwalker = right;mid = num[(lwalker + rwalker) / 2];while (lwalker < rwalker){while (num[lwalker] < mid) lwalker++;while (num[rwalker]>mid) rwalker--;if (lwalker <= rwalker){int tmp = num[lwalker];num[lwalker] = num[rwalker]; num[rwalker] = tmp;lwalker++;rwalker++;}}if (lwalker < right)  push2(s, lwalker,right);if (rwalker>left)  push2(s, left, rwalker);}}void input(int num[])//实参传入的数组的首地址,而不是整个数组{int i;srand((unsigned)time(NULL));//产生随机函数的随机数种子for (i = 1; i < MAX; i++){num[i] = rand() % 100;}}void  output(int num[]){int i;for (i = 1; i <= MAX; i++){printf("%5d", num[i]);if (i % 100 == 0)printf("\n");}}void main(){ int num[MAX],num2[MAX];time_t start, end;time(&start);input(num);cout << "递归排序前:" << endl;output(num);Qsort1(num, 0,MAX - 1);cout << "递归排序后:" << endl;output(num);input(num2);cout << "开始非递归排序,排序前:"<<endl;    output(num2);cout << "非递归排序后:" << endl;Qsort(num2, 0, MAX - 1);output(num2);time(&end);cout << "用时为" << end-start << endl;system("pause");}



0 0