快速排序的实现

        这是C++算法基础-基础算法专栏的第一篇文章,专栏详情请见此处


引入

        在C++中,有一个STL的排序函数——sort(),它的实现就采用了快速排序(准确地说,其实sort()是运用了内省排序实现的,但内省排序的本质就是快速排序),这足以体现快速排序的实用性。

Q:C++STL中已经有了排序函数sort(),为什么还要学习快速排序呢?

A:首先,长远来看,学习快速排序是为了学习一种思想。学习思想看似没有实际作用,但是随着逐渐积累,你会发现,做题与学习其他更多的算法会变得越来越得心应手;其次,快速排序的思想还会在快速选择算法中用到,它会在接下来的学习中发挥作用。

        下面我们就来讲快速排序的实现。

定义

        快速排序(quicksort),又称分区交换排序(partition-exchange sort),简称「快排」,是一种被广泛运用的排序算法。

过程

        快速排序的工作原理是通过分治的原理来将一个数组排序。共分为三个过程:

  1. 将数列划分为两部分;
  2. 递归到两个子序列中分别进行排序;
  3. 当递归到边界时,不用合并,因为此时数列已经完全有序,并终止操作;如果递归未到边界,则重复1、2两步,直到递归到边界。

        第一步并不是普通地直接分成前后两个序列,而是在分的过程中要保证相对大小关系。具体来说,选择一个分界点m,把数列分成两个部分,然后让前一个子数列中的数都小于后一个子数列中的数

Q:分界点可以取哪些位置?

A:常见的分界点有:取左边界,取中间值,取右边界与随机选择一个位置(代码中是取数组中点数来当做两个子数列的分界)。

        注意,我们说的是用数组中点上的数值来作为标准来分,并不是将数组从中点处划分为两个部分,所以,两个部分中不一定含有相同数量的数!

       第二步,维护一前一后pq两个指针,依次考虑当前的数是否放在了应该放的位置。如果当前的数没放对,比如说如果后面的指针q遇到了一个比m小的数,那么就交换pq位置上的数,再把p后移一位。当前的数的位置放对后,再移动指针继续处理,直到两个指针相遇

        第三步,如递归到边界,序列已经分别有序,这时第一个序列中的数都小于第二个序列中的数,所以直接拼接起来就好了,然后终止操作;否则继续进行递归(进行1、2两步),直到递归到边界。

        下面给出快速排序思想图(此处的分界点为取左边界):

性质

        稳定性

        快速排序是一种不稳定的排序算法。

        时间复杂度

        快速排序的平均与最好时间复杂度均为O(nlog_{2}n),而最坏时间复杂度为O(n^{2})

        空间复杂度

        快速排序的空间复杂度为O(nlog_{2}n)

代码

        下面给出快速排序的实现代码:

void quick_sort(int q[],int l,int r){
	if(l>=r) 
	 	 return;
	int i=l-1,j=r+1,x=q[l+r>>1];
	while(i<j){
		while(q[i]<x)
			i++;
		while(q[j]>x)
			j--;
		if(i<j)
			swap(q[i],q[j]);
	}
	quick_sort(q,l,j);
	quick_sort(q,j+1,r);
}

C++算法基础专栏文章    下一篇-快速选择算法的实现


每周六更新一篇文章,内容一般是自己总结的经验或是在其他网站上整理的优质内容

点个赞,关注一下呗~

  • 39
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值