排序算法之快速排序

本文详细介绍了快速排序的基本思想,包括左右指针法、挖坑法和前后指针法的排序过程,并讨论了三数取中法的优化。此外,还提供了C语言的代码实现,并分析了快速排序的时间复杂度为O(N*logN)和空间复杂度为O(logN)。虽然快速排序在某些情况下可能不稳定,但其平均效率高,是常用排序算法之一。
摘要由CSDN通过智能技术生成
快速排序
基本思想

快速排序(Quicksort)是对冒泡排序的一种改进。它由C. A. R. Hoare在1960年提出,是一种二叉树结构的交换排序方法。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,设立一个关键字,其中一部分的所有数据都比关键字小,另外一部分的所有数据都比关键字大,然后再按此方法对这两部分数据分别进行快速排序,直到达到整个数据变成有序序列。

排序过程

快速排序的实现有三种方法:

  1. 左右指针法
    以升序为例,首先定义两个指针left和right,再定义一个指向关键字的指针key。
    第一趟排序时,将left指向第一个元素即最左边,right指向倒数第二个元素即右数第二个元素,key指向最后一个元素,然后left向右走,right向左走,依次移动一个元素的位置,left先走,当left遇见一个比key指向元素大的元素时停下,即指向该元素,然后right向左走,直到遇见一个比key指向元素小的元素时停下,然后交换left和right指向的两个元素,再重复进行这个过程,直到两个指针相遇,然后交换相遇点的元素和key指向的元素。这样就完成了key左边的元素均比它小,而key右边的元素均比它大的目的。
    然后以最后的相遇点作为分界点,将整个待排序序列分为两部分,每部分同样进行上述操作,直到不能再继续分组为止,这时便完成了排序操作。
    在这里插入图片描述

  2. 挖坑法
    挖坑法与左右指针法较为相似,同样以升序为例,首先定义两个指针left和right,再定义一个记录关键字的key。
    第一趟排序时,将left指向第一个元素即最左边,right指向最后一个元素即最右边,取最后一个元素作为key的值,然后left向右走,right向左走,依次移动一个元素的位置,left先走,当left遇见一个比key大的元素时停下,即指向该元素,并将left指向的元素赋值给right指向的位置;然后right向左走,直到遇见一个比key小的元素时停下,并将right指向的元素赋值给left指向的位置;再重复进行这个过程,直到两个指针相遇,然后将相遇点位置赋值为key的值。这样就完成了key左边的元素均比它小,而key右边的元素均比它大的目的。
    然后以最后的相遇点作为分界点,将整个待排序序列分为两部分,每部分同样进行上述操作,直到不能再继续分组为止,这时便完成了排序操作。
    在这里插入图片描述

  3. 前后指针法
    同样以升序为例,这种方法首先定义了两个指针prev和cur,在定义一个只想关键字的key。
    第一趟排序时,令key指向最后一个元素作为关键字,cur指向第一个元素,prev则指向cur前面即左边挨着的一个元素。在cur小于key时,即cur没有和key指向同一个位置,cur向右走,一次走一个元素的距离,如果cur指向的元素小于key,那么prev也跟随cur向右走一个元素的距离,同时如果cur指向的元素小于key且prev指向的的下一个元素不是cur,那么交换prev和cur各自指向的元素。即当cur指向的元素小于key关键字时,prev始终紧挨着cur,指向cur前面即左边挨着的一个元素,但如果cur遇见了大于key关键字的元素,prev会停留在cur左边第一个比key关键字大的元素的左边紧挨着的一个元素的位置。重复上述过程,直到cur遇见key关键字的位置,然后prev再向右走一个位置,再次交换prev和cur各自指向的元素,此时完成第一趟排序,也即完成了key左边的元素均比它小,而key右边的元素均比它大的目的。
    然后以prev的位置作为分界点,将整个待排序序列分为两部分,每部分同样进行上述操作,直到不能再继续分组为止,这时便完成了排序操作。
    在这里插入图片描述
    关于快速排序的优化

    1. 三数取中法优化
      上述算法采用将区间的最后一个元素作为关键字进行进一步的排序,但为了防止出现每次选择到最值元素这种最坏情况,引入三数取中法对算法进行优化。
      三数取中法是取区间的第一个、最后一个和中间元素相比较,选择出大小居中的元素作为关键字。
      引入了三数取中法之后,可以将最坏情况即原始序列有序的情况转换为最好情况,即每一次取到序列的中值元素,即每一次划分完全平均的二分迭代的最好情况。
    2. 小区间优化
      当快速排序采用迭代方式实现时,在区间比较小时改换其他的排序方法进行排序,可以大大减少递归次数,但是很多编译器对于递归本身进行了优化,在实际的测试中这种优化的效果并不明显。
C语言代码实现

交换函数:

void Swap(int* a, int* b)
{
   
	int t = *a;
	*a = *b;
	*b = t;
}

三数取中法优化:

int GetMidIndex(int*a, int left, int right)
{
   
	int mid = left + (right - left) / 2;
	if (a[left] < a[mid])
	{
   
		if (a[mid] < a[right])
			return mid;
		else if (a[left] 
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值