版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dugudaibo/article/details/79509413
1. 基本原理
首先回顾一下之前所讲的几个排序算法,如下图所示
在这里继续介绍一种新的排序算法,即快速排序。这种方法的想法实际上很简单,首先选定某一个确定的值,将小于这个值的元素放在他的左边,将大于这个值的元素放在他的右边,之后将左侧元素递归第使用该方法,直至排好整个序列。
2. 代码实现
#include <stdio.h>
// 在数组中将下标为 low 和 high 的元素进行互换
void swap(int k[], int low, int high)
{
int temp;
temp = k[low];
k[low] = k[high];
k[high] = temp;
}
int Partition(int k[], int low, int high)
{
int point;
point = k[low]; // 令基准点为数组的第一个元素,且 point 是变量而非指针
while( low < high )
{
// 从右边开始过滤掉所有比基准点大的数值,因为它们就在右边就好了,不用动
while( low < high && k[high] >= point )
{
high--;
}
// 找到比基准点小的值就互换位置
swap(k, low, high);
// 与上面的同理
while( low < high && k[low] <= point )
{
low++;
}
swap(k, low, high);
}
return low;
}
// 其中的 low 是数组的起始位置, high 是数组的终止位置
void QSort(int k[], int low, int high)
{
int point; // 基准点
// 通过不断地对基准点进行比较,在比较的过程中个左边的基准点和右边的基准点都会移动
// 当指针重合的时候说明已经进行了一轮比较了
if( low < high )
{
point = Partition(k, low, high); //定位基准点,将小于基准点的数字放在左边,大于的放在右边
QSort(k, low, point-1); // 对基准点左边进行递归调用
QSort(k, point+1, high); // 对基准点右边进行递归调用
}
}
void QuickSort(int k[], int n)
{
QSort(k, 0, n-1);
}
int main()
{
int i, a[10] = {4, 2, 5, 0, 3, 9, 1, 7, 6, 8};
QuickSort(a, 10);
printf("排序后的结果是:");
for( i=0; i < 10; i++ )
{
printf("%d", a[i]);
}
printf("\n\n");
return 0;
}
3. 快速排序的优化
3.1 优化选取基准点
之前的方法直接将第一个元素作为 point ,但是这样的取法很容易使得作为比较元素的 ponit 本身就是最大值,使得算法的效率降低,为了避免这种情况的产生,选取数组的第一个元素,最后一个元素和中间元素中位于中间的那个元素作为 pnoint 。
3.2 优化不必要的交换
再优化的过程可以看到 point 元素来回移动了数次,但是再一次循环中实际上最后是确定一个位置,所以之前经过的位置都是无用功,可以不这样来回移动位置,而是直接采用赋值操作,这样就不用调用子函数了。
3.3 优化小数组时的排序方案
数组规模较小(比如说小于 7 的时候),可以直接采用插入排序的方法,当数组的规模比较大的时候使用递归(即快速排序的方法)。
3.4 优化递归操作
使用尾递归的方式优化递归操作。所谓的尾递归就是,如果一个函数中递归形式的调用出现函数的末尾,我们称这个递归函数是为尾递归的。