在本篇文章中,我们将通过实操一个小题目,来理解与运用冒泡排序

冒泡排序是什么,怎么工作的?

冒泡排序是一种排序算法,它可以将一堆无序/乱序的元素,排列成有序的元素。

它的工作方式就和在水底吐泡泡一样:一次吐一个泡泡,泡泡吐出来后向上冒,而当这个泡泡向上冒的运动结束时,它的位置处于当前水的最高处(水面)。

如图:

【冒泡排序】思想与运用_升序


我们每一次冒泡的过程中,都会从第一个数开始,不断地向后进行比较。

以排升序(从小到大排)为列:

有数列 4 3 2 1

第一趟冒泡(本趟冒泡排序中,共要执行 n - 1次冒泡,n为元素的个数):

4 和 3比, 4 大,则4冒上来。数列变为 3 4 2 1

然后4 再与 2比较,4 大, 4再冒上来。数列变为 3 2 4 1

然后4 再与 1比较,4 大, 4再冒上来。数列变为 3 2 1 4

此时第一趟冒泡走完,数列的最后一个数已经是数列中最大的元素。

再进行第二趟冒泡排序,此时水面下下降一个元素,本次排序只需执行 n - 1 -1 次。(因为最后一个元素已经排序完成,无需再进行比较)。

以此下去,一共要执行n - 1趟冒泡。(因为最后一个元素已经被动地放在了它该在地地方,无需排序)。

运用:

我们刚刚已经学会了冒泡排序地工作原理,现在我们运用冒泡排序来解一个小题目,来加深冒泡排序地理解。

题目描述:

输入4个整数,要求按由小到大的顺序输出。

解题思路:

直接运用冒泡排序算法,进行升序的重新排列。

代码实现:

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <assert.h>

#define SIZE 4

//冒泡排序
void Bubble_sort(int*  const p, int num)
{
	assert(p);

	int i = 0;//控制总冒泡的次数
	int j = 0;//控制每一次冒泡时,需要操作的元素数量
	int tem = 0;//进行交换时的临时变量
	int flag = 0;//标志位,记录是否发生元素交换

	//num个元素,即需要进行num - 1次冒泡
	for (i = 0; i < num - 1; i++)
	{
		//每次进入循环,标志位重置为0
		flag = 0;

		//每次减少1个数(每次冒泡完成,即有1个数已被排序完成)
		//
		//j不能等于数组的最后一个元素
		//所以结束条件为: num - i - 1
		//因为:
		// 1.j为最大下标时, 执行*(action + j + 1),会造成越界访问
		// 2.j不是最大下标时,*(action + j + 1)已经被排序结束,无需再进行比较
		for (j = 0; j < num - i - 1; j++)
		{
		
		
			if (j != num - i - 1)
			{
				//如果前面的数大于后面的数,则需要替换
				if (*(p + j) > *(p + j + 1))
				{
					tem = *(p + j);
					*(p + j) = *(p + j + 1);
					*(p + j + 1) = tem;

					//发生交换,更新标志位
					flag = 1;
				}
			}
		}

		//如果一轮中为发生任何排序,说明排序已经完成,可提前结束排序
		if (!flag)
		{
			break;
		}
	}

}

int main()
{
	int arr[SIZE] = { 0 };
	int i = 0;

  //录入元素
	for (i = 0; i < SIZE; i++)
	{
		scanf("%d", &arr[i]);
	}
	
  //进行排序
	Bubble_sort(arr, SIZE);

  //输出排序好的数列
	for (i = 0; i < SIZE; i++)
	{
		printf("%d ", arr[i]);
	}
	
	return 0;
}

运行结果:

【冒泡排序】思想与运用_冒泡排序_02