冒泡排序算法

一、前言

排序是程序开发中极为常见的操作,而冒泡排序是最为经典的基础排序算法。它的逻辑清晰易懂、代码实现简洁,因而成为每一位编程初学者的入门必修课。本文会讲清楚冒泡排序的逻辑和实现方法。

二、理解冒泡排序

冒泡排序的核心思想是:两两相邻元素进行比较。我们以下面一个数组为例:

int arr[10] = { 10,9,8,7,6,5,4,3,2,1 };

假设我们想要将数组中的元素按升序排列。所谓“升序”,无非就是“把大的元素放在后面”。那么我们先从第1、2个元素开始判断。由于这两个元素10、9不符合“先小后大”的顺序,我们对这两个元素进行交换,交换后的数组内容变成了:

9,10,8,7,6,5,4,3,2,1

接下来我们再把第2、3个元素进行比较。仍然不符合升序,那么进行交换:

9,8,10,7,6,5,4,3,2,1

以此类推。当我们进行了9次比较与交换后,数组内容就变成了:

9,8,7,6,5,4,3,2,1,10

最大的数字10被交换到了最后,待在了它应该在的位置上。

以上的过程,就称为“一趟排序”。

我们再进行一趟排序,会发现第二大的数字9也到了它应该在的位置上:

8,7,6,5,4,3,2,1,9,10

由此可见,在冒泡排序算法中,一趟排序可以将1个数字放在正确的位置上,而且总是先解决位置在最后的数字,再依次向前解决剩下的数字。

此外,在第二趟排序中,我们发现:由于最大的数字10已经在正确的位置上,我们其实可以省略最后一次比较和交换,只进行8次。那么以此类推,每进行一趟排序,一趟中所需要的比较和交换次数就少一次。

那么排序一组数据一共需要多少趟呢?

假设我们需要排序n个元素。由于一趟排序可以解决1个元素,那么进行(n-1)趟排序之后,剩下的最后一个元素肯定也在正确的位置上了。所以我们一共只需进行(n-1)趟排序。

再回顾以上的过程,我们发现在每一趟排序里,都是最大的数字从杂乱的数据中一点一点移动到最后,正如水中的气泡浮到水面的过程。这就是“冒泡排序”得名之由。

三、冒泡排序算法的代码实现

3.1 实现

我们将冒泡排序的过程封装成一个函数,那么这个函数需要两个参数:待排序的数组arr和需要进行排序的元素个数sz。首先,我们需要一个运行(sz - 1)次的循环,代表一共进行(sz - 1)趟排序。

void bubble_sort(int arr[], int sz)
{
	int i;
	for (i = 0; i < sz - 1; i++)
	{
		
	}
}

由于每进行一趟排序,一趟排序内部需要进行的比较和交换次数就少一次,所以每趟内部需要一个运行(sz - 1 - i)次的循环,代表相邻元素比较和交换的次数。

void bubble_sort(int arr[], int sz)
{
	int i;
	for (i = 0; i < sz - 1; i++)
	{
		int j;
		for (j = 0; j < sz - 1 - i; j++)
		{
            
		}
	}
}

最后我们写出比较和交换相邻元素的过程。

void bubble_sort(int arr[], int sz)
{
	int i;
	for (i = 0; i < sz - 1; i++)
	{
		int j;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

现在我们就完成了冒泡排序的全过程。我们创建一组实验数据进行测试:

int main()
{
	int arr[10] = { 3,5,4,7,9,10,1,8,2,6 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	int i;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

运行结果如下:

成功完成了排序。

3.2 优化

以上代码确实可以完成排序,但是,如果还没有进行完(sz - 1)趟排序,数据就已经完成排序了,后面的排序趟数就多余了。

为了优化代码,我们可以设置一个整型变量flag,flag为1时代表数据已经有序,不需要再排列,flag值为0时代表还需要继续排列。

在每一趟中我们先将flag值设置为1,也就是假设数据已经有序。

在相邻元素比较、交换的if语句中,加上一句flag = 0,如果这个语句被执行,就说明发生了交换,也就是数据仍没有完全排列好。

如果一趟排序完成后flag值仍为1,说明这一趟没有进行交换,也就说明数据已经排列完成了。此时我们就用break语句来结束循环。

void bubble_sort(int arr[], int sz)
{
	int i;
	for (i = 0; i < sz - 1; i++)
	{
		int flag = 1;//假设这一趟已经有序
		int j;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				flag = 0;//发生交换,说明没有排列完成
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
		if (flag == 1)//没发生交换,已经排列好了,不需要再进行后续排序
			break;
	}
}

优化后的代码只会进行1趟多余的排序(需要一趟排序来判断数据是否已经有序)。

以上就是文章的全部内容。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值