漫谈经典排序算法:三、冒泡排序 && 快速排序

程序员通勤双肩包,下单送全年 CSDN 会员 防泼水面料电脑包,保护笔记本电脑,背负轻便,下单再赠 Coding Plan,看技术干货、查文档、下载源码,一站式搞定学习需求 阅读详情

1、序言

这是《漫谈经典排序算法系列》第三篇,先解析了冒泡排序,然后引出快速排序,给出了快速排序的两种实现版本

各种排序算法的解析请参考如下:

《漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析》

《漫谈经典排序算法:二、各种插入排序解析及性能比较》

《漫谈经典排序算法:三、冒泡排序 && 快速排序》

《漫谈经典排序算法:四、归并排序》

《漫谈经典排序算法:五、线性时间排序(计数、基数、桶排序)》

《漫谈经典排序算法:六、各种排序算法总结》

 

注:为了叙述方便,本文以及源代码中均不考虑A[0],默认下标从1开始。

2、冒泡排序

          2.1 引出

           前面的两篇博客里讲的插入排序是基于“逐个记录插入”,选择排序是基于“选择”,那么冒泡排序其实是基于“交换”。每次从第一个记录开始,一、二两个记录比较,大的往后放,二三两个记录比较...依次类推,这就是一趟冒泡排序。每一趟冒泡排序后,无序序列中值最大的记录冒到序列末尾,所以称之为冒泡排序。

          2.2 代码

//冒泡排序
void bubbleSort(int *a,int n)
{
	int i,j;
	for(i=1;i<n;i++)
		for(j=1;j<n-i+1;j++){
			if(a[j+1]<a[j]){
				a[j]=a[j]+a[j+1];
				a[j+1]=a[j]-a[j+1];
				a[j]=a[j]-a[j+1];
			}
		}
}

          2.3 效率分析

相对于简单选择排序,冒泡排序交换次数明显更多。它是通过不断地交换把最大的数冒出来。冒泡排序平均时间和最坏情况下(逆序)时间为o(n^2)。最佳情况下虽然不用交换,但比较的次数没有减少,时间复杂度仍为o(n^2)。此外冒泡排序是稳定的。

3、快速排序

          3.1 引出

           快速排序是冒泡排序的一种改进,冒泡排序排完一趟是最大值冒出来了,那么可不可以先选定一个值,然后扫描待排序序列,把小于该值的记录和大于该值的记录分成两个单独的序列,然后分别对这两个序列进行上述操作。这就是快速排序,我们把选定的那个值称为枢纽值,如果枢纽值为序列中的最大值,那么一趟快速排序就变成了一趟冒泡排序。

          3.2 代码

           两种版本,第一种是参考《数据结构》,在网上这种写法很流行。第二种是参考《算法导论》,实现起来较复杂。

//快速排序(两端交替着向中间扫描)
void quickSort1(int *a,int low,int high)
{
	int pivotkey=a[low];//以a[low]为枢纽值
	int i=low,j=high;
	if(low>=high)
		return;
	//一趟快速排序
	while(i<j){//双向扫描
		while(i < j && a[j] >= pivotkey)
			j--;
		a[i]=a[j];
		while(i < j && a[i] <= pivotkey)
			i++;
		a[j]=a[i];
	}
	a[i]=pivotkey;//放置枢纽值
	//分别对左边、右边排序
    quickSort1(a,low,i-1); 
	quickSort1(a,i+1,high); 
}

//快速排序(以最后一个记录的值为枢纽值,单向扫描数组)
void quickSort2(int *a,int low,int high)
{
	int pivotkey=a[high];//以a[high]为枢纽值
    int i=low-1,temp,j;
	if(low>=high)
		return;
	//一趟快速排序
	for(j=low;j<high;j++){
		if(a[j]<=pivotkey){
			i++;
            temp=a[i];
			a[i]=a[j];
			a[j]=temp;
		}
	}
	i++;
	//放置枢纽值
	temp=a[i];
	a[i]=pivotkey;
	a[high]=temp;
	//分别对左边、右边排序
    quickSort2(a,low,i-1); 
	quickSort2(a,i+1,high); 
}

          3.3 效率分析

        快速排序时间与划分是否对称有关。快速排序的平均时间复杂度为o(n*logn),至于为什么是o(n*logn),请参考《算法导论》第7章,书中用递归树的方法阐述了快速排序平均时间。且常数因子很小,所以就平均时间而言,快速排序是很好的内部排序方法。最佳情况下(每次划分都对称)时间复杂度o(n*logn)。最坏情况下(每次划分都不对称,如输入的序列有序或者逆序时)时间复杂度为o(n^2),所以在待排序序列有序或逆序时不宜选用快速排序。此外,快速排序是不稳定的。

        最佳情况下,每次划分都是对称的,由于枢纽值不再考虑,所以得到的两个子问题的大小不可能大于n/2,同时一趟快速排序时间为o(n),所以运行时间递归表达式:

T(n)<=2T(n/2)+o(n)。这个递归式的解法请参考下一篇博客中归并排序效率分析。其解为T(n)=o(n*logn)。

        最坏情况下,每次划分都很不对称,T(n)=T(n-1)+o(n),可以用递归树来解,第i层的代价为n-i+1.总共有n层。把每一层代价加起来有n-1个n相加。所以这个递归式的解为T(n)=o(n^2),此时就是冒泡排序。

4、附录

         4.1 参考书籍

          《数据结构》严蔚敏版                    《算法导论》

           4.2 所有源代码
#include<stdio.h>

//冒泡排序
void bubbleSort(int *a,int n)
{
	int i,j;
	for(i=1;i<n;i++)
		for(j=1;j<n-i+1;j++){
			if(a[j+1]<a[j]){
				a[j]=a[j]+a[j+1];
				a[j+1]=a[j]-a[j+1];
				a[j]=a[j]-a[j+1];
			}
		}
}

void main()
{
	int i;
	int a[7]={0,3,5,8,9,1,2};//不考虑a[0]
	bubbleSort(a,6);
	for(i=1;i<=6;i++)
		printf("%-4d",a[i]);
	printf("\n");
}
#include<stdio.h>

//快速排序(两端交替着向中间扫描)
void quickSort1(int *a,int low,int high)
{
	int pivotkey=a[low];//以a[low]为枢纽值
	int i=low,j=high;
	if(low>=high)
		return;
	//一趟快速排序
	while(i<j){//双向扫描
		while(i < j && a[j] >= pivotkey)
			j--;
		a[i]=a[j];
		while(i < j && a[i] <= pivotkey)
			i++;
		a[j]=a[i];
	}
	a[i]=pivotkey;//放置枢纽值
	//分别对左边、右边排序
    quickSort1(a,low,i-1); 
	quickSort1(a,i+1,high); 
}

//快速排序(以最后一个记录的值为枢纽值,单向扫描数组)
void quickSort2(int *a,int low,int high)
{
	int pivotkey=a[high];//以a[high]为枢纽值
    int i=low-1,temp,j;
	if(low>=high)
		return;
	//一趟快速排序
	for(j=low;j<high;j++){
		if(a[j]<=pivotkey){
			i++;
            temp=a[i];
			a[i]=a[j];
			a[j]=temp;
		}
	}
	i++;
	//放置枢纽值
	temp=a[i];
	a[i]=pivotkey;
	a[high]=temp;
	//分别对左边、右边排序
    quickSort2(a,low,i-1); 
	quickSort2(a,i+1,high); 
}

void main()
{
	int i;
	int a[7]={0,3,5,8,9,1,2};//不考虑a[0]
	quickSort2(a,1,6);
	quickSort1(a,1,6);
	for(i=1;i<=6;i++)
		printf("%-4d",a[i]);
	printf("\n");
}


 

 

漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析 1、序言 这是《漫谈经典排序算法系列》第一篇,该篇从最简单的选择排序算法谈起,由浅入深的详细解析两种选择排序算法的过程及性能比较。逐步揭露选择排序的本质及其基本思想。 各种排序算法的解析请参考如下: 《漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析》 《漫谈经典排序算法:二、各种插入排序解析及性能比较》 《漫谈经典排序算法:冒泡排序 && 快速排序》 《漫谈经典排序算 阅读详情

相关推荐

漫谈经典排序算法:二、各种插入排序解析及性能比较

1、序言 这是《漫谈经典排序算法系列》第二篇,解析了各种插入排序算法。主要包括:直接插入排序、折半插入排序、表插入排序、希尔插入排序。每一种算法的开头都叙述了引出该算法的原因,然后给出代码,最后分析算法效率及其他插入排序相比,优劣在哪里。 各种排序算法的解析请参考如下:

Touch_2011的专栏 1万+

必学算法快速排序及其改进方案

必学算法快速排序及其改进方案

qq_41583040的博客 1694

冒泡排序(超详细)

1、什么是冒泡排序冒泡排序的英文Bubble Sort,是一种最基础的交换排序。之所以叫做冒泡排序,因为每一个元素都可以像小气泡一样,根据自身大小一点一点向数组的一侧移动。 冒泡排序的原理: 每一趟只能确定将一个数归位。即第一趟只能确定将末位上的数归位,第二趟只能将倒数第 2 位上的数归位,依次类推下去。如果有 n 个数进行排序,只需将 n-1 个数归位,也就是要进行 n-1 趟操作。 而 “每一趟 ” 都需要从第一位开始进行相邻的两个数的比较,将较大的数放后面,比较完毕之后向后挪一位继续比较下面

hcz666的博客 39万+

排序算法-快速排序的优化

跳转:排序算法 在看这个学习,有些没讲全,以下为补充。 快速排序优化 基准的选择 固定基准 基本算法本身每次切分是用的第一个,就叫固定基准,但如果序列本身有序或基本有序,则会使时间复杂度提升到O(N²),因为每次切分都用的第一个,要切分N次,每第 i 次比较 N - i 次。 随机基准 随机取基准,基准选的最差的概率就是N分之一,当然,选择最优基准的概率也是N分之一。避免了最坏情况的多次发生,算法的平均性能较好。 数取中 选取数组开头,中间结尾的元素,通过比较,选择中间的值作为快排的基准。比较稳定,但是

Tj的博客 782

快速排序的优化

今天,我们组这周小会讲了讲算法导论上的快速排序优化问题;大家分享,有什么问题,希望大家指正,谢谢!!! 1. 快速排序定义: 通过一趟排序将待排序数组分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。              它是采用分治思想,进行排序;每次选取一个枢轴,确定枢轴的位置,将原数组分成两部分,进行递

zhaojinjia的专栏 1598

漫画:什么是冒泡排序

————— 当天上午 —————什么是冒泡排序冒泡排序的英文Bubble Sort,是一种最基础的交换排序。大家一定都喝过汽水,汽水中常常有许多小小的气泡,哗啦哗啦...

CSDN资讯 6524

漫谈经典排序算法:六、各种排序算法总结

1、这是《漫谈经典排序算法》最后一篇,总结了各种排序算法的时间复杂度、稳定性、辅助空间、约束条件。 各种排序算法的解析请参考如下: 《漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析》 《漫谈经典排序算法:二、各种插入排序解析及性能比较》 《漫谈经典排序算法:

Touch_2011的专栏 8940

漫谈经典排序算法

漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析》 《漫谈经典排序算法:二、各种插入排序解析及性能比较》 《漫谈经典排序算法:冒泡排序 && 快速排序》 《漫谈经典排序算法:四、归并排序》 《漫谈经典排序算法:五、线性时间排序(计数、基数、桶排序)》 《漫谈经典排序算法:六、各种排序算法总结》 原文:http://blog.csdn.

Make progress step by step everyday..... 612

冒泡排序&快速排序

1、序言 这是《漫谈经典排序算法系列》第篇,先解析了冒泡排序,然后引出快速排序,给出了快速排序的两种实现版本。 各种排序算法的解析请参考如下: 《漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析》 《漫谈经典排序算法:二、各种插入排序解析及性能比较》 《漫谈经典排序算法:冒泡排序 && 快速排序》 《漫谈经典排序算法:四、归并排序》 《漫谈经典排序算法:...

m0_55548657的博客 435

漫谈排序算法及其优化方案——C++程序员必须掌握的技能

在计算机科学中,排序算法(Sorting Algorithm)是一种将一组数据按照指定顺序进行排列的算法。通常情况下,这种指定的顺序是由一个排序关键字所决定的,例如,按照学生的考试成绩排序,或者按照工资大小排序等。在计算机科学中,排序算法是非常重要的基础算法。不同的排序算法在不同的场景下起到不同的作用。本篇文章将总结c++排序算法的优缺点及未来发展趋势。

BXA 1374

漫谈经典排序算法:六、各种排序算法总结 .

1、这是《漫谈经典排序算法》最后一篇,总结了各种排序算法的时间复杂度、稳定性、辅助空间、约束条件。 各种排序算法的解析请参考如下: 《漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析》 《漫谈经典排序算法:二、各种插入排序解析及性能比较》 《漫谈经典排序算法:冒泡排序 && 快速排序》 《漫谈经典排序算法:四、归并排序》 《漫谈经典排序算法:五、线性时间排序(计数、基数、桶

u010129251的专栏 368

漫谈经典排序算法:四、归并排序(合并排序)

1、序言 这是《漫谈经典排序算法系列》第四篇,解析了归并排序。  各种排序算法的解析请参考如下: 《漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析》 《漫谈经典排序算法:二、各种插入排序解析及性能比较》 《漫谈经典排序算法:冒泡排序 && 快速排序

Touch_2011的专栏 1万+

漫谈经典排序算法:五、线性时间排序(计数、基数、桶排序)

1、序言 这是《漫谈经典排序算法系列》第五篇,给出了种线性时间排序,分别是计数排序、基数排序、桶排序。 各种排序算法的解析请参考如下:   《漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析》 《漫谈经典排序算法:二、各种插入排序解析及性能比较》 《漫谈

Touch_2011的专栏 1万+

排序算法3

1、序言 这是《漫谈经典排序算法系列》第篇,先解析了冒泡排序,然后引出快速排序,给出了快速排序的两种实现版本。 各种排序算法的解析请参考如下: 《漫谈经典排序算法:一、从简单选择排序到堆排序的深度解析》 《漫谈经典排序算法:二、各种插入排序解析及性能比较》 《漫谈经典排序算法:冒泡排序 && 快速排序》 《漫谈经典排序算法:四、归并排序》 《漫谈

jx347638458的博客 305
上一篇: 漫谈经典排序算法:二、各种插入排序解析及性能比较
下一篇: 漫谈经典排序算法:四、归并排序(合并排序)
一个程序写手
博客等级 码龄15年 437粉丝 46原创
评论 11
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值