冒泡排序及其代码优化(C语言实现)

定义

冒泡排序是从第一个元素开始,重复走访要排序的元素,如果两个元素位置相反,则进入交换,最后使得整个数组是一个有序数组。

冒泡排序(未优化)

算法思想

假设原数组为{3,1,7,8,2,5,3,6},数组为整型数组,数组长度为8。
在这里插入图片描述
根据冒泡排序的定义,我们从第一个元素开始,以数组长度为循环次数,开始进行比较:

  1. 比较 3 和 1
    在这里插入图片描述
    由于3>1,故交换位置:

  2. 比较 3 和 7
    在这里插入图片描述

    由于3<7,故不交换位置:
    在这里插入图片描述

  3. 比较 7 和 8
    在这里插入图片描述

    由于7<8,故不交换位置:

  4. 比较 8 和 2
    在这里插入图片描述

    由于8>2,故交换位置:
    在这里插入图片描述

  5. 比较 8 和 5
    在这里插入图片描述

    由于8>5,故交换位置:
    在这里插入图片描述

  6. 比较 8 和 3
    在这里插入图片描述

    由于8>3,故交换位置:
    在这里插入图片描述

  7. 比较 8 和 6
    在这里插入图片描述

    由于8>6,故交换位置:
    在这里插入图片描述
    此时,第一大轮循环比较结束,我们开始进行第二~N轮循环比较。
    循环比较的过程为
    在这里插入图片描述

当进行数组长度次大轮循环比较后,我们可以得到一个完全有序的数组,即
在这里插入图片描述

代码实现(未优化版)

#include<stdio.h>
//打印数组
void print(int a[], int length)
{
	for (int i = 0; i < length; i++) {
		printf(" %d", a[i]);
	}
	printf("\n");
}
void bubble1(int a[], int length)
{
	//i,j为循环变量,temp为中间变量
	int i, j, temp = 0;
	//打印原数组
	printf("原数组为:");
	print(a, length);
	//进行大轮循环
	for (i = 0; i < length - 1; i++) {
		//寻找每一次大循环内的最大值
		for (j = 0; j < length - 1; j++) {
			//判断是否需要交换位置
			if (a[j] > a[j + 1]) {
				//交换位置
				temp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = temp;
			}
		}
	}
	//打印排序后的数组
	printf("冒泡排序后的数组为:");
	print(a, length);
}
int main()
{
	int a[8] = { 3,1,7,8,2,5,3,6 };
	bubble1(a, 8);
}

优化比较次数

算法思想

我们观察下图:
在这里插入图片描述

通过观察,我们不难发现:每次比较后,我们都能固定数组中的一位元素,由于我们是增序排列,所以每次固定的一位元素都是靠右固定,并且,我们发现固定元素的位置与循环次数存在关系,即:固定元素位置(数组下标)=数组长度-循环次数,然而如果数组除第一个元素外,其他元素位置都是固定的,那么相等于数组的第一个元素位置也是固定的。所以,我们可以根据此原理进行优化。

代码实现(优化比较次数)

#include<stdio.h>
//打印数组
void print(int a[], int length)
{
	for (int i = 0; i < length; i++) {
		printf(" %d", a[i]);
	}
	printf("\n");
}
void bubble1(int a[], int length)
{
	//i,j为循环变量,temp为中间变量
	int i, j, temp = 0;
	//打印原数组
	printf("原数组为:");
	print(a, length);
	//进行大轮循环
	for (i = 0; i < length - 1; i++) {
		//寻找每一次大循环内的最大值
		//length -1 -i -->优化了比较次数,使得固定的元素不再进行比较
		for (j = 0; j < length - 1 - i; j++) {
			//判断是否需要交换位置
			if (a[j] > a[j + 1]) {
				//交换位置
				temp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = temp;
			}
		}
	}
	//打印排序后的数组
	printf("冒泡排序后的数组为:");
	print(a, length);
}
int main()
{
	int a[8] = { 3,1,7,8,2,5,3,6 };
	bubble1(a, 8);
}

优化冒泡次数

算法思想

我们看另一个数组:
在这里插入图片描述
这个数组是有序的,但如果按上边的代码进行冒泡排序,我们不难发现,它还是正常的跑完了,没有在有序的时候进行跳出循环,浪费了很多资源。所以,我们能不能设置个变量,判断数组是否有序。如果判断到数组有序后,我们直接跳出循环,不再进行冒泡呢?
设想,如果设置个bool型变量"res",如果交换,则改变res值,如果不变,则说明了这次循环没有交换元素,此时数组是有序的。
在这里插入图片描述

代码实现(优化冒泡次数)

#include<stdio.h>
//打印数组
void print(int a[], int length)
{
	for (int i = 0; i < length; i++) {
		printf(" %d", a[i]);
	}
	printf("\n");
}
void bubble1(int a[], int length)
{
	//i,j为循环变量,temp为中间变量
	int i, j, temp = 0;
	//打印原数组
	printf("原数组为:");
	print(a, length);
	//进行大轮循环
	for (i = 0; i < length - 1; i++) {
		//定义判断有序标志
		bool res = false;
		//寻找每一次大循环内的最大值
		for (j = 0; j < length - 1 - i; j++) {
			//判断是否需要交换位置
			if (a[j] > a[j + 1]) {
				//交换位置
				temp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = temp;
				//如果交换,则不有序-->res=true
				res = true;

			}
		}
		//如果res等于初始值,则说明元素未交换,数组已有序,结束冒泡排序
		if (!res)
			break;
	}
	//打印排序后的数组
	printf("冒泡排序后的数组为:");
	print(a, length);
}
int main()
{
	int a[8] = { 1,2,3,4,5,6,7,8 };
	bubble1(a, 8);
}

进一步优化比较次数

算法思想

根据“优化比较次数”代码思想,我们发现“固定元素位置(数组下标)=数组长度-循环次数”这个规律,接下来,我们观察下表:
在这里插入图片描述
能看到,当确定 8 的位置时,其实,我们不用在循环到”8前边那个位置,因为我们比较的时候,比较的是—— a[j] 和 a[j+1] 的关系,所以对于第一大轮循环
在这里插入图片描述

当我们确定到 8 的位置后,我们下一次循环可以只循环到 3 的位置,如果 3<6 ,则我们交换两者位置,把 3 的数组下标记录下来,继续进行下一次循环,如果 3>6 ,则直接进行下一次循环。当这轮循环进行结束后,最终记录下来的数组下标就是下一次循环比较的次数。

代码实现(进一步优化比较次数)

#include<stdio.h>
//打印数组
void print(int a[], int length)
{
	for (int i = 0; i < length; i++) {
		printf(" %d", a[i]);
	}
	printf("\n");
}
void bubble1(int a[], int length)
{
	//i,j为循环变量,temp为中间变量
	int i, j, temp = 0;
	//记录比较次数
	int n = length - 1;
	//打印原数组
	printf("原数组为:");
	print(a, length);
	//进行大轮循环
	while (1) {
		//设置比较结束位置
		int last = 0;
		//寻找每一次大循环内的最大值
		for (j = 0; j < n; j++) {
			//判断是否需要交换位置
			if (a[j] > a[j + 1]) {
				//交换位置
				temp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = temp;
				last = j;

			}
		}
		n = last;
		//如果n==0,说明,未发生交换,数组有序,结束冒泡
		if (n == 0)
			break;
	}
	//打印排序后的数组
	printf("冒泡排序后数组为:");
	print(a, length);
}
int main()
{
	int a[8] = { 3,1,7,8,2,5,3,6 };
	bubble1(a, 8);
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值