【数据结构】八大排序之冒泡排序以及优化

一、设计思想

1、我们可以把冒泡排序理解为不断地将大数向后移动,小数向前移动的过程。
2、举例
(1)先定义两个变量 i 和 j ,初始状态都在0的位置,让 j 和 j + 1 位置的数据进行比较,如果 j 大,就进行数据交换,如果 j + 1大就不移动,一直 j++,直到这一趟更便利结束
(2)让 i ++,每进行一趟就++一次,原因是,我们用 i 来控制每一趟已经处理的已排序的个数。
在这里插入图片描述
在这里插入图片描述
(3)那问题是我们如何让j在已经排序好的元素前退出循环呢???
也就是在循环中 j 的边界值怎么算?
j < len - i - 1;

二、代码

#include<stdio.h>

void BubbleSort(int arr[], int len)
{
	int i = 0; 
	int j = 0;
	int tmp = 0;
	for (i; i < len-1 ; i++)
	{
		for (j = 0; j < len - i - 1; j++ )
		{
			if (arr[j + 1] < arr[j])
			{
				tmp = arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = tmp;
			}
		}
	}
}
int main()
{
	int arr[] = { 12, 3, 21, 32, 1, 34, 12, 35, 34 };
	int len = sizeof(arr) / sizeof(arr[0]);
	BubbleSort(arr, len);
	for (int i = 0; i < len; i++)
	{
		printf("%d  ", arr[i]);
	}
	printf("\n");
	return 0;
}

三、优化

优化 1:

如果数据在i = n 时已经排序完成,但是按照常规来说,数据要继续进行n +1 次等等。该如何解决??
方法:我们设置一个标记位flag = 0,如果进行交换就让标记位flag = 1,我们在加一个判断语句,如果flag = 0,说明没有进行交换,就退出循环。这样就可以防止在排序完成后,还继续进行外层循环的情况。

void BubbleSort(int arr[], int len)
{
	int i = 0; 
	int j = 0;
	int tmp = 0;
	int flag = 0;//标记发生交换
	
	for (i; i < len-1 ; i++)
	{
		int flag = 0;
		for (j = 0; j < len - i - 1; j++ )
		{
			if (arr[j + 1] < arr[j])
			{
				tmp = arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = tmp;
				flag = 1;
			}
		}
		if (flag = 0)//判断是否发生交换
		{
			break;
		}
	}
}

优化 2:

如果在一个数据中前面是无序的,而后面是有序的,那我们在用优化1进行操作时,每次前面部分都会进行交换数据,所以循环不会退出,我们怎样能让循环只进行前面无序数据的排序???
方法:在设置一个标志位pos = 0,每次把交换的下标 j 赋值给pos,直到最后一个交换位,让最后让pos = len - 1,这样i在进行判断时,只会执行到len - 1的位置。这样就有效防止了没有必要的交换判断。

void BubbleSort(int arr[], int len)
{
	int i = 0; 
	int j = 0;
	int tmp = 0;
	int pos = 0;
	int k = len - 1;
	int p = 1;
	for (i; i < k ; i++)
	{
		int flag = 0;
		for (j = 0; j < len - i - 1; j++ )
		{
			if (arr[j + 1] < arr[j])
			{
				tmp = arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = tmp;
				flag = 1;
				pos = j;
			}
		}
		k = pos;
		if (flag = 0)
		{
			break;
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值