快速排序 递归与非递归
Posted 文竹balala
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速排序 递归与非递归相关的知识,希望对你有一定的参考价值。
绪论: 由于平常用c++STL里面的sort习惯了,所以很少用过快速排序,同时也对快速排序有一种恐惧感,一直以为自己不会写,但是仔细想想快排的思想,还是很容易理解的,
只要思维达到一个高度,就都不是问题了。
交换排序:说到快排,就要先说到交换排序,因为快排是交换排序的一种,而说的交换排序,就不得不先说最简单的冒泡排序。因为任何高明的算法都不是一下子就能想出来的,都是在已有的基础上进行不断的优化得来的。
冒泡排序:冒泡排序的过程就是首先将第一个关键字与第二个关键字进行比较,如果是逆序的(a[1] > a[2]),从1开始n结束,则进行交换,第一趟排序(交换)是从1到n,结果最大的在第n个位置上,然后接下来第i趟排序都要把最大的交换到n-i+1的位置上,最终经过n-1趟排序,时间复杂度为O(n2)。
优化:现在再来想想改进算法了,如果我们可以想到分割的思想(很多算法都用到),每次交换和比较只要比较一部分,比如分为两半,这样的话比较和交换的代价就会小很多,所以我们就想到每一趟排序都把待排记录分为独立的两部分,其中一部分的关键字比另一部分的关键字小,这样只要分别对这两部分精心进行排序就可以使整体有序。
于是就有了快速排序,但是其代码实现不尽相同,效率也有不同。比如说递归和非递归,递归里关于枢轴的设置。有人可能以为递归就够了,但是有一些公司面试或机试时专门让写一个非递归的快排,这时如果不理解其中的思想就跪了。下面只是对快排几种写法的简单的探索。
递归写法:
递归主体函数:
void quicksort(int *a, int low, int high)
if (low < high)
int p = Partition1(a, low, high);//p就是分为两半后中间的那个关键字
quicksort1(a, low, p-1);
quicksort1(a, p+1, high);
再有就是关于Partition函数的实现了,可以说是快排算法里核心内容,实现方法不同,效率也不同
int Partition1(int *a, int low, int high)
int x = a[low];
int pivotkey = a[low];
while(low < high)
while (low < high && a[high] >= pivotkey) high--;
a[low] = a[high];
while (low < high && a[low] <= pivotkey) low++;
a[high] = a[low];
a[low] = x;
return low;
int Partition2(int *a, int low, int high)
int x = a[high];
int i = low-1;
for (int j = low; j < high; j++)
if (a[j] < x)
i++;
int t;
t = a[j];
a[j] = a[i];
a[i] = t;
int t = a[i+1];
a[i+1] = a[high];
a[high] = t;
return i+1;
我学习到的目前有这两种:
第一种是数据严蔚敏数据结构课本里的,大致思路是设一个数为枢轴,并通过从两头向中间遍历,使枢轴放到一个确定的位置,使左边的都小于枢轴上的关键字,右边的都大于枢轴上的关键字。
第二种是从算法导论里边的,思路是从最做到右遍历一遍,找到小于枢轴的就交换到左边。
对于这两种方法的效率比较我用了一组数据进行了测试,数据为大小为 0xffffff的随机数并把其保存的文件里,首先声明,关于时间都只是一个相对的概念,毕竟我的电脑配置不高。
经过比较第一种算法比第二种效率高,可能第一种是从两边进行比较的缘故,而且交换不像第二种每次交换都是t = a, a = b, b = t 的过程,而只是一步。
所以之后的算法我只测试Partition1,然后又把Partition1这个函数放到了quicksort函数里面进行了测试。
非递归写法:
非递归写法其实就是手动建立一个栈的过程,所以算法关键是这个栈的优劣,下面是两种写法:用STL里的栈和用数组表示栈。
void no_recursion_quicksort_stl(int *a, int low, int high)
stack<int> Stack;
Stack.push(low);
Stack.push(high);
while (!Stack.empty())
int r = Stack.top();
Stack.pop();
int l = Stack.top();
Stack.pop();
int p = Partition1(a, l, r);
if (p-1 > l)
Stack.push(l);
Stack.push(p-1);
if (p+1 < r)
Stack.push(p+1);
Stack.push(r);
int Stack[100000];
void no_recursion_quicksort_array(int *a, int low, int high)
int top = 0;
Stack[top++] = low;
Stack[top++] = high;
while (top != 0)
int r = Stack[--top];
int l = Stack[--top];
int p = Partition1(a, l, r);
if (p-1 > l)
Stack[top++] = l;
Stack[top++] = p-1;
if (p+1 < r)
Stack[top++] = p+1;
Stack[top++] = r;
结果是非递归写法中用STL的栈比递归写法效率更低,而用数组表示栈效率并没有提高。可能是我的算法有问题,先留下问题等待以后研究。
以上是关于快速排序 递归与非递归的主要内容,如果未能解决你的问题,请参考以下文章