排序--Bubble的三种优化

BubbleSort

冒泡排序是许多人接触的第一种排序方式,由于这种方式比较简单,所以大部分人也没有深入研究,所以写出的代码是这样的:

void BubbleSort(int *arr, int len)
{
	assert(arr);
	int i = 0;
	int j = 0;
	int tmp = 0;
	for (i = 0; i < len - 1; i++)
	{
		for (j = 0; j < len -i- 1; j++)       //每排序一趟,则必然后面有一个已经有序,可以减少循环缩小排序的范围
		{
			if (arr[j]>arr[j + 1])
			{
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

其实我想告诉你的是冒泡排序还有三种优化方式:(以下都是以升序为例)

例如要排序下面这组数据: 1   2   3   4   5   6   7   8  
10  9

按照上面的排序方式,第一趟将10 与
9交换后已经就有序了,所以接下来的8趟都是多余的。这时我们可以加一个标记来判断每一趟排序时是否交换过数据,如果哪一趟排序没有交换数据,则这时就已经有序了。

void BubbleSort(int *arr, int len)
{
	assert(arr);
	int i = 0;
	int j = 0;
	int flag = 0;
	int tmp = 0;
	for (i = 0; i < len - 1; i++)
	{
		flag = 1;                              //flag初始时为1
		for (j = 0; j < len - i - 1; j++)       //每排序一趟,则必然后面有一个已经有序,可以缩小排序的范围
		{
			if (arr[j]>arr[j + 1])             //只要要交换数据,则flag就会被修改
			{
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				flag = 0;                    //只要这组数还未完全有序,则一定会修改flag为0
			}
		}
		if (flag)                             //如果排序一趟,发现已经有序,则不进入if,flag没被修改
		{
			break;
		}
	}
}

这样修改之后虽然提高了冒泡排序的效率,但是还是不是最理想的!!!

例如现在要排序下面这组数据:1  2  5  7  4   3   6   8  9  10

根据上面的算法我们可以写出如下代码:

void BubbleSort(int *arr, int len)
{
	assert(arr);
	int i = 0;
	int j = 0;
	int flag = 0;
	int tmp = 0;
	int m = 0;                  //用来记录最后一次交换的位置
	int k = len-1;
	for (i = 0; i < len - 1; i++)
	{
		m = 0;
		flag = 1;
		for (j = 0; j < k; j++)       //无序区的范围只从第一个元素,到上一趟最后一次交换的位置k
		{
			if (arr[j]>arr[j + 1])
			{
				tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				flag = 0;                    //只要这组数还未完全有序,则一定会修改flag为0
				m = j;
			}
		}
		if (flag)                             //如果排序一趟,发现已经有序,则不进入if,flag没被修改
		{
			break;
		}
		k = m;                             //将k置成最后一次交换的位置
	}
}

写成上面这种方式 ,冒泡排序的效率已经得到了极大的提升,下面我们再来介绍第三种优化的方法!!!

对下面这组这组数进行排序:2  3  4  5  6  7  8  9  10  1

根据上面的算法,我们可以写出如下代码:

void BubbleSort(int *arr, int len)
{
	assert(arr);
	int i = 0;
	int j = 0;
	int flag = 0;
	int m = 0;       //记录最后一次交换的位置
	int n = 0;
	int k = len - 1;
	for (i = 0; i < len - 1; i++)
	{
		m = 0;
		flag = 1;
		//正序扫描找最大值
		for (j = n; j < k; j++)       //无序区的范围只从第一个元素,到上一趟最后一次交换的位置k
		{
			if (arr[j]>arr[j + 1])
			{

				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
				flag = 0;                    //只要这组数还未完全有序,则一定会修改flag为0
				m = j;
			}
		}
		k = m;
		if (flag)                    //如果排序一趟,发现已经有序,则不进入if,flag没被修改
		{
			break;
		}
		//反序扫描找最小值
		for (j = k; j>n; j--)       //无序区的范围只从第一个元素,到上一趟最后一次交换的位置k
		{
			if (arr[j]<arr[j - 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j - 1];
				arr[j - 1] = tmp;
				flag = 0;                    //只要这组数还未完全有序,则一定会修改flag为0
			}
		}
		n++;
		if (flag)                    //如果排序一趟,发现已经有序,则不进入if,flag没被修改
		{
			break;
		}                           //将k置成最后一次交换的位置
	}
}

这种改进之后的冒泡排序是不是很厉害!!!   ^v^

时间: 2025-01-08 00:05:48

排序--Bubble的三种优化的相关文章

冒泡排序的三种优化

传统的冒泡排序完全可以满足我们最基本的需求,但是也仅仅是最简单的需求,这种简单的两个for循环不加任何的判断语句的形式注定它只能是一种效率最低的算法. 我们先贴一个传统的实现方式,之后的三个优化全部建立在函数排序所使用的消耗上,这也是我们优化一切算法的根本路径. void BubbleSort(int* arr,int size) { assert(arr&&size); if(size==1) return; for(int i=0;i<size-1;i++) { for(int

详解Oracle数据货场中三种优化:分区、维度和物化视图

转 xiewmang 新浪博客 本文主要介绍了Oracle数据货场中的三种优化:对分区的优化.维度优化和物化视图的优化,并给出了详细的优化代码,希望对您有所帮助. 我们在做数据库的项目时,对数据货场的优化,大约的原理只有两个:一是数据分块储藏,便于数据的转储和管教:二是其中处理,长进数据供给的速度.本文主要介绍了Oracle数据货场中的三种优化:对分区的优化.维度优化和物化视图的优化,基上面两个大约的原理,借助于数据货场的观念,罗列数据库的优化措施:1.分区在数据货场中,事实表,索引表,维度表分

三种快速排序以及快速排序的优化

一.  快速排序的基本思想 快速排序使用分治的思想,通过一趟排序将待排序列分割成两部分,其中一部分记录的关键字均比另一部分记录的关键字小.之后分别对这两部分记录继续进行排序,以达到整个序列有序的目的. 二.  快速排序的三个步骤 1) 选择基准:在待排序列中,按照某种方式挑出一个元素,作为 "基准"(pivot): 2) 分割操作:以该基准在序列中的实际位置,把序列分成两个子序列.此时,在基准左边的元素都比该基准小,在基准右边的元素都比基准大: 3) 递归地对两个序列进行快速排序,直到

【转】三种快速排序算法以及快速排序的优化

一.  快速排序的基本思想 快速排序使用分治的思想,通过一趟排序将待排序列分割成两部分,其中一部分记录的关键字均比另一部分记录的关键字小.之后分别对这两部分记录继续进行排序,以达到整个序列有序的目的. 二.  快速排序的三个步骤 1) 选择基准:在待排序列中,按照某种方式挑出一个元素,作为 “基准”(pivot): 2) 分割操作:以该基准在序列中的实际位置,把序列分成两个子序列.此时,在基准左边的元素都比该基准小,在基准右边的元素都比基准大: 3) 递归地对两个序列进行快速排序,直到序列为空或

哗啦啦Python之路 - Day 6 - 三种基础排序,递归,反射,模块

1. 三种排序方式 - 冒泡排序:两两比较,大的排右边,每次冒出去一个泡 m = [1,2,6,5,4] for i in range(len(m)): for j in range(i): if m[j] > m[j+1]: m[j],m[j+1] = m[j+1],m[j] print(m) - 选择排序 对于一组关键字{K1,K2,…,Kn}, 首先从K1,K2,…,Kn中选择最小值,假如它是 Kz,则将Kz与 K1对换:然后从K2,K3,… ,Kn中选择最小值 Kz,再将Kz与K2对换.

算法复杂度,及三种主要排序算法的研究

一.时间复杂度 1.时间频度  T(n),n为问题的规模 即--算法中语句的执行次数.又叫语句频度. 2.时间复杂度 记作 O( f(n) ),这里的f(n)是一个T(n)的同数量级函数. 如O(1)表示算法的语句执行次数为一个常数,不随规模n的增长而增长: 又如T(n)=n^2+3n+4与T(n)=4n^2+2n+1它们的频度不同, 但时间复杂度相同,都为O(n^2). 3.算法的性能 主要用算法的 时间复杂度 的数量级来评价一个算法的时间性能. 二.空间复杂度 S(n),包括3方面: 1.算

c# list排序的三种实现方式 (转帖)

用了一段时间的gridview,对gridview实现的排序功能比较好奇,而且利用C#自带的排序方法只能对某一个字段进行排序,今天demo了一下,总结了三种对list排序的方法,并实现动态传递字段名对list进行排序. 首先先介绍一下平时最常用的几种排序方法. 第一种:实体类实现IComparable接口,而且必须实现CompareTo方法 实体类定义如下: 按 Ctrl+C 复制代码 class Info:IComparable { public int Id { get; set; } pu

Java常用三种算法排序比较

Java常用三种算法排序比较 冒泡排序: package demo1; /** * * @author xiaoye 2014-5-13 */ /** * 有N 个数据需要排序,则从第0 个数开始,依次比较第0 和第1 个数据, * 如果第0 个大于第1 个则两者交换,否则什么动作都不做,继续比较第 1 个第2个-, * 这样依次类推,直至所有数据都"冒泡"到数据顶上. 冒泡排序的效率 O(N*N ),比较 N*N/2 ,交换N*N/4 . */ public class Bubble

JavaScript新手学习笔记3——三种排序方式(冒泡排序、插入排序、快速排序)

每种编程语言学到数组的时候,都会讲到排序算法,当时学C语言的时候,卡在排序算法.今天来总结一下javascript中如何实现三种排序算法. 1.冒泡排序(默认升序排列哦) 原理: 冒泡排序的原理,顾名思义,就是小数往上冒,大数往下沉.从第一个数开始,如果比第二个数大就交换位置,然后跟第三个数字进行比较大小,交换位置等. 举例一下,有数组[2,4,3,5,1] 第一次循环:2<4  不交换:4>3 交换:4<5不交换:5>1交换,故结果是[2,3,4,1,5]; 第二次循环:2<