十大排序之快速排序

快速排序

快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用,再加上快速排序思想----分治法也确实实用,因此很多软件公司的笔试面试,包括像腾讯,微软等知名IT公司都喜欢考这个,还有大大小的程序方面的考试如软考,考研中也常常出现快速排序的身影。

快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-Conquer Method)。

1.算法步骤

该方法的基本思想是:

  • 先从数列中取出一个数作为基准数(头部尾部都可以,实际上任何一个都可以)。
  • 分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。
  • 再对左右区间重复第二步,直到各区间只有一个数。

2.动图演示

img

3.代码实现

void swap(int* x, int* y) {
    int t = *x;
    *x = *y;
    *y = t;
}

3.1.首元素作为基准数

void quick_sort_recursive_front(int arr[], int start, int end) {
    if (start >= end)//这个地方大于等于都可以,只不过当start==end的时候,多了一层递归。当然这一层递归并没有任何实质性作用
        return;
    int mid = arr[start];
    int left = start+1, right = end;
    while (left < right) {
        while (arr[right] > mid && left < right)
            right--;
        while (arr[left] < mid && left < right)
            left++;
        //left不可能大于right,最多是等于
        swap(&arr[left], &arr[right]);//最后一次肯定有自己交换一次
    }//while语句运行完后,left==right
    if (arr[left] >= arr[start])
        left--;//这是一种特殊情况,mid的值恰好是最大值,left--将指向基准值
    else
        swap(&arr[left], &arr[start]);
    if (left)//这里的left可要可不要,只不过多了一次函数递归而已
        quick_sort_recursive_front(arr, start, left - 1);//左递归
    quick_sort_recursive_front(arr, left + 1, end);//右递归
}

3.2.尾元素作为基准数

void quick_sort_recursive_tail(int arr[], int start, int end) {
    if (start >= end)//这个地方大于等于都可以,只不过当start==end的时候,多了一层递归。当然这一层递归并没有任何实质性作用
        return;
    int mid = arr[end];
    int left = start, right = end - 1;
    while (left < right) {
        while (arr[left] < mid && left < right)
            left++;
        while (arr[right] > mid && left < right)
            right--;
        //left不可能大于right,最多是等于
          swap(&arr[left], &arr[right]);//最后一次肯定有自己交换一次
    }//while语句运行完后,left==right
        if (arr[left] >= arr[end])
            swap(&arr[left], &arr[end]);
        else
            left++;//这是一种特殊情况,mid的值恰好是最大值,left++将指向基准值
        if (left)//这里的left可要可不要,只不过多了一次函数递归而已
            quick_sort_recursive_tail(arr, start, left - 1);//左递归
        quick_sort_recursive_tail(arr, left + 1, end);//右递归
}
void quickSort(int arr[], int len)
{
    quick_sort_recursive_front(arr, 0, len - 1);
    //quick_sort_recursive_tail(arr, 0, len - 1);
}

3.3.测试程序

void main()
{
	int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 9, 70, 35,32};//定义一个待排序的数组
	int len = sizeof(arr) / sizeof(*arr);//获取数组长度
	printf("\nsort before\n");
	for (int i = 0; i < len; i++)//排序前数组元素的顺序
	{
		printf("%d\t", arr[i]);
	}
	quickSort(arr,len);//快速排序
	printf("\quickSort after\n");//排序后数组元素的顺序
	for (int i = 0; i < len; i++)
	{
		printf("%d\t", arr[i]);
	}
	system("pause");
}

4.归纳总结

  • 从while循环出来之后left == right
  • 存在一种极为特殊的情况:选择的基准值就是最大值
  • 递归的终止条件start>=end可以改为start>end,只不过多了一层递归而已,对整个数组元素的顺序没有任何变化
  • 如果不是处于特殊情况,从while循环出来之后,left和right同时指向比基准值更大的值然后再与基准值进行交换,此时left与right同时指向基准值,但如果是处于特殊情况,那么此时left和right指向基准值旁边的值,至于++还是–则取决于是首元素作为基准数还是尾元素作为基准数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值