C语言实现冒泡排序算法的示例详解

 更新时间:2022年04月02日 09:57:32   作者:飞向星的客机  
这篇文章主要介绍了C语言如何实现冒泡排序算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1. 问题描述

对N个整数(数据由键盘输入)进行升序排列。

2. 问题分析

对于N个数因其类型相同,我们可利用 数组 进行存储。

冒泡排序是在 两个相邻元素之间进行比较交换的过程将一个无序表变成有序表。

冒泡排序的思想:首先,从表头开始往后扫描数组,在扫描过程中逐对比较相邻两个元素的大小。

若相邻两个元素中,前面的元素大于后面的元素,则将它们互换,称之为消去了一个逆序。

在扫描过程中,不断地将两相邻元素中的大者往后移动,最后就将数组中的最大者换到了表的最后,这正是数组中最大元素应有的位置。

然后,在剩下的数组元素中(n-1个元素),重复上面的过程,将次小元素放到倒数第 2 个位置。

不断重复上述过程,直到剩下的数组元素为 0 为止,此时的数组就变为了有序。

假设数组元素的个数为 n nn,在最坏情况下需要的比较总次数为:((n−1)+(n−2)+...+2+1)=n(n−1)/2。

3. 算法设计

冒泡排序的过程我们用示意图简单的表示,从整个排序过程中寻找规律,n个元素只需比较n−1次即可。

假设一个数组中有 7 个元素,现在对这 7 个元素进行排序,只需比较 6 轮即可得到所要的有序序列。

示意图中最后加粗的数字即为经过一轮交换位置固定的数字。示意图如下:

动图演示

清楚了冒泡排序的过程,我们再来看一个动态图

4. 程序设计

设计一

数组名用 a 表示、数组下标用 j 表示,数组中相邻两个元素的下标可表示为 a[j]、a[j+1] 或 a[j-1]、a[j]。

在利用数组解决问题时需要注意数组下标不要越界。

假如定义一个整形数组 int a[n],则数组元素下标的取值范围是0~(n−1),下标小于0或者大于n−1 都视为下标越界。

如果相邻元素采用 a[j]、a[j+1] 表示的话,则下标取值范围是0~(n−2);

若采用 a[j-1]、a[j] 表示,下标取值范围则是1~(n−1)

设计二

数组元素互换 也是经常遇到的一类题型,一般这种情况我们需要 借助一个中间变量 才可以完成,对于许多初学者来说经常犯的一个错误是:对两个元素直接相互赋值,而不借助中间变量。

我们先来看生活中的一个例子:

在蓝墨水瓶中装有蓝墨水,红墨水瓶中装有红墨水;现在我们要把蓝墨水放到红墨水瓶中,红墨水放到蓝墨水瓶中。

做法是先找一个白色空瓶(作用相当于程序中的中间变量):

首先将蓝墨水倒入白色空瓶: t=a[i] 或 t=a[i+1];

接着将红墨水倒入蓝墨水瓶:a[i]=a[i+1] 或 a[i+1]=a[i];

最后将白瓶中的蓝墨水倒入红墨水瓶:a[i+1]=t 或 a[i]=t;

经过这 3 步就完成了红墨水与蓝墨水的互换。如果不借助白色空瓶,直接把蓝墨水倒入红墨水瓶,或把红墨水倒入蓝墨水瓶,这样必将破坏原来所存储的内容。

第一轮的交换过程可以用简单的程序段进行表示:

第二轮交换过程(最后一个元素经过第一轮比较已经确定,不需要再次进行比较):

第三轮交换过程(最后两个元素已经确定,不需要再次进行比较):

结论

由上面的程序段发现,第一轮比较的判定条件为 j < n-1;

第二轮为 j < n-2;

第三轮为 j < n-3;

依次类推,第 i 轮的循环判定条件必为 j < n-i。

在编程过程中我们可以用两层循环来控制,第一层循环控制交换的轮数,第二层循环控制每轮需要交换的次数。

5. 流程框架

6. 代码实现

假设有下面一组无序数组,我们要对它进行升序排序

完整代码

#include <stdio.h>

//冒泡排序函数
void BubbleSort(int arr[], int len)
{
	int i;
	int j;
	int temp;
	for (i = 0; i < len - 1; i++) //控制比较的轮数
	{
		for (j = 0; j < len - 1 - i; j++) //控制每轮比较的次数
		{
			if (arr[j] > arr[j + 1]) //数组相邻两个元素进行交换
			{
				temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;

			}
		}

	}

}

//输出函数
void print(int arr[], int len)
{
	int i;
	for (i = 0; i < len; i++)
	{
		printf("%3d ", arr[i]);
	}
}

int main()
{

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

	BubbleSort(arr, 10);

	printf("The data after sorted:\n");
	print(arr, 10);

	printf("\n");

	return 0;
}

运行结果

代码贴图

7. 问题拓展

常用的排序方法除了上述的冒泡排序外,还有选择排序、插入排序、快速排序和堆排序等,下面简单介绍一下 选择排序。

选择排序思想:

扫描整个线性表,第一轮比较拿数组中的第一个元素与其他元素进行比较,遇到比第一个元素小的则进行交换;

再拿着交换之后的第一个元素接着上次比较的位置与后面的元素进行比较,直到扫描到线性表的最后,从中选出最小的元素,将它交换到表的最前面(这是它应有的位置)。

第二轮比较的时候从第二个元素开始,依次与第三个、第四个直到最后一个比较,在比较过程中有比第二个元素小的进行交换,接着与后面的元素比较;

对剩下的子表采用同样的方法,直到子表为空。在最坏情况下需要比较n(n−1)/2 次。

选择排序如下

#include <stdio.h>

//选择排序
void selectSort(int arr[], int len)
{
	int i;
	int j;
	for (i = 0; i < len - 1; i++)
	{
		int min = i;//假设第一个元素是最小的
		for (j = i + 1; j < len; j++)
		{
			if (arr[j] < arr[min])
			{
				min = j;//保存最小元素的下标
			}
		}
		//交换
		int temp = arr[min];
		arr[min] = arr[i];
		arr[i] = temp;
	}
}

//输出
void print(int arr[], int len)
{
	for (int i = 0; i < len; i++)
	{
		printf("%3d ", arr[i]);
	}
}

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

	selectSort(arr, 10);

	printf("The data after sorted:\n");
	print(arr, 10);

	printf("\n");

	return 0;
}

运行结果

代码贴图

不同排序法的效率是不同的,不同需求情况下可选择不同的方法。

到此这篇关于C语言实现冒泡排序算法的示例详解的文章就介绍到这了,更多相关C语言冒泡排序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C语言代码实现扫雷小游戏

    C语言代码实现扫雷小游戏

    这篇文章主要为大家详细介绍了C语言代码实现扫雷小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-02-02
  • C++中sting类的简单实现方法

    C++中sting类的简单实现方法

    这篇文章主要介绍了C++中sting类的简单实现方法的相关资料,需要的朋友可以参考下
    2016-08-08
  • 老生常谈C++的单例模式与线程安全单例模式(懒汉/饿汉)

    老生常谈C++的单例模式与线程安全单例模式(懒汉/饿汉)

    下面小编就为大家带来一篇老生常谈C++的单例模式与线程安全单例模式(懒汉/饿汉)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-12-12
  • C语言实现磁盘映射

    C语言实现磁盘映射

    磁盘映射技术通过将文件映射到内存中,提高了文件操作的效率,本文就来介绍一下C语言实现磁盘映射,感兴趣的可以了解一下
    2024-09-09
  • C语言冒泡排序法的实现(升序排序法)

    C语言冒泡排序法的实现(升序排序法)

    这篇文章主要介绍了C语言冒泡排序法的实现(升序排序法),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • C语言植物大战数据结构二叉树递归

    C语言植物大战数据结构二叉树递归

    这篇文章主要为大家介绍了C语言植物大战数据结构二叉树递归,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • c++ 指针与引用的区别介绍及使用说明

    c++ 指针与引用的区别介绍及使用说明

    指针与引用看上去完全不同(指针用操作符*和->,引用使用操作符.),但是它们似乎有相同的功能,感兴趣的朋友可以了解下啊,或许本文对你有所帮助,好了,话不多说,切入正题
    2013-01-01
  • sigsetjmp的用法总结

    sigsetjmp的用法总结

    sigsetjmp()会保存目前堆栈环境,然后将目前的地址作一个记号,而在程序其他地方调用siglongjmp()时便会直接跳到这个记号位置,然后还原堆栈,继续程序的执行
    2013-09-09
  • C语言正则表达式详解 regcomp() regexec() regfree()用法详解

    C语言正则表达式详解 regcomp() regexec() regfree()用法详解

    C语言处理正则表达式常用的函数有regcomp()、regexec()、regfree()和regerror(),这里就为大家介绍一下,需要的朋友可以参考一下啊
    2018-04-04
  • Qt使用QPainter绘制3D立方体

    Qt使用QPainter绘制3D立方体

    这篇文章主要为大家详细介绍了Qt使用QPainter绘制3D立方体,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-08-08

最新评论