【基础向】冒泡排序详解


冒泡排序

冒泡排序是一种简单的排序思想,即通过比较和交换,使较小(或较大)的数据逐渐向一端移动。


算法原理

以从小到大排序为例:
1.遍历数据(除了最后一个)。
2.使被遍历的数据与其后一个数据作比较,若比后一个大,则交换。
3.重复 1,2 直到排序完成(优化)。


 算法可视化


图片来自http://sc.chinaz.com/jiaobendemo.aspx?downloadid=8201830910379
每次遍历总会使得某一个数据被安排在正确的位置上。
那么我们只要遍历 “n - 1” 次即可完成排序。


实现


 简单实现

  • 详细注释:
//===============冒泡排序简单实现
void BubbleSort(int* array,int count)
//array为欲排序数组的指针,通过这个指针可以直接操作传入的数组
//count为数组元素个数
{
	int i, j, temp;//temp在交换数据时作为第三方变量使用
	for (j = 0; j < count - 1; j++)
	{
	//j < count - 1外层循环进行了 “count - 2” 次
	//使得前 “count - 1” 个数据排在了正确的位置上,那么剩下一个数据当然也在正确的位置上
		for (i = 0; i < count - 1 - j; i++)
		{
		//对于 i < count - 1 - j
		//每次内层循环总会把一个数据放置得尽可能靠后,也就是说靠后的 j 个数据已经排好序,没必要继续遍历
			if (array[i] > array[i+1] 
			{//如果当前数据比后面的数据大
							//交换数据
				//这是三个语句,为了简洁就写在一起了
				temp = array[i+1]; array[i+1] = array[i]; array[i] = temp;
			}
		}
	}
}
  • 去掉注释:
//===============冒泡排序简单实现
void BubbleSort(int* array,int count)
{
	int i, j, temp;
	for (j = 0; j < count - 1; j++)
	{
		for (i = 0; i < count - 1 j; i++)
		{
			if (array[i] > array[i + 1])
			{
				temp = array[i + 1]; array[i + 1] = array[i]; array[i] = temp;
			}
		}
	}
}

 优化

  对于上述算法,我们知道:外层循环每循环一次,就会把一个数据排在正确的位置,那么如果有一个或多个数据本来就在正确的位置上呢?
  思考,如果向我们刚才研究的 BubbleSort() 函数中传入这样一组数据:

2 1 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22

  我们发现,排序实际上在第一次外层循环结束时就已经完成了。
  而外层循环却保证自身会循环 “count - 1” 次,所以即使排序已经完成,算法依然会傻傻地运行下去:

for (j = 0; j < count - 1; j++){}

  为了解决这个问题,我们只要判断某次外层循环是否发生过数据交换即可。
  如果本次没有发生交换,那么说明排序已经结束,可以直接输出结果。
  那么我们可以定义一个标志位来实现这样的算法:

  int flag;
  • 代码如下:
//===============冒泡排序优化版本
void BubbleSort_adv(int * a,int count)
{
	int i, j, temp, flag;//标志,0 为未发生交换,1 为发生过交换
	for (j = 0; flag == 1; j++)
	{//外层循环条件变为 “已发生交换” 
		flag = 0;//内层循环开始时,我们认为还未发生交换
		for (i = 0; i < count - 1 - j; i++)
		{
			if (a[i] > a[i + 1])
			{
				temp = a[i + 1]; a[i + 1] = a[i]; a[i] = temp;
				flag = 1;//发生交换,flag置 1
			}
		}
	}
}
  • 去掉注释:
//===============冒泡排序优化版本
void BubbleSort_adv(int * a,int count)
{
	int i, j, temp, flag;
	for (j = 0; flag == 1; j++)
	{
		flag = 0;
		for (i = 0; i < count - 1 - j; i++)
		{
			if (a[i] > a[i + 1])
			{
				temp = a[i + 1]; a[i + 1] = a[i]; a[i] = temp;
				flag = 1;
			}
		}
	}
}

  使用clock()函数,比较算法的运行效率:

  • 代码:
//重复跑一千万次
......
	start = clock();
	for ( i = 1; i <= 10000000; i++)
	{
		BubbleSort(a.array,9);//为了方便对排序序列的初始化,这里是将数组包装在了结构体中。
		a = b;//结构体可以直接赋值。
		//关于结构体赋值,这里存在一些问题,不过不会影响本次的结果,我们下次再讨论。
	}
	printf("优化前:%lfs
",(double) (clock() - start)/CLK_TCK);


	start = clock();
	for ( i = 1; i <= 10000000; i++)
	{
		BubbleSort_adv(a.array,9);
		a = b;
	}
	printf("优化后:%lfs
",(double) (clock() - start)/CLK_TCK);
......
  • 输出:
    在这里插入图片描述

反向

  以上给出的算法均与算法可视化一致,为从小到大排列。
  若想改变排序方向,只需要做一个微小的改动

//===============冒泡排序优化版本(从大到小)
void BubbleSort_adv(int * a,int count)
{
	int i, j, temp, flag;
	for (j = 0; flag == 1; j++)
	{
		flag = 0;
		for (i = 0; i < count - 1 - j; i++)
		{
			if (a[i] < a[i + 1])//改动这里的符号
			{
				temp = a[i + 1]; a[i + 1] = a[i]; a[i] = temp;
				flag = 1;
			}
		}
	}
}

原文地址:https://www.cnblogs.com/gaolihai/p/13149772.html