分享一下我对C语言中冒泡排序算法的学习和理解(裂开了,足足写了一天,自闭中…)

文章目录

  • 冒泡排序
  • 算法原理
  • 实例演示
  • 时间复杂度
  • C语言实现代码
  • 加入用户输入程序
  • 对于上述程序bug的解决方案
  • 对算法进行封装及调用
  • 运行结果
  • 算法优化
  • 写在后面

冒泡排序


冒泡排序(Bubble Sort)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们的位置交换过来,走访数列重复地进行直到排序完成。因为越大(小)的元素经过交换会慢慢地"浮"到数列的顶端(尾端),就如同碳酸饮料中的气泡一样,故名“冒泡排序”。


算法原理

以从大到小降序排列为例。

  • 第一轮走访开始 ----> 比较相邻的元素- —> 如果第一个元素比第二个元素小,就交换他们的位置,把小的放到后面 ----> 如果第二个比第三个小,同样交换他们的位置,以此类推 ----> 第一轮走访结束

这个时候最小的数就“浮”到最右端了

  • 第二轮走访开始 ----> 比较相邻的元素- —> 如果第一个元素比第二个元素小,就交换他们的位置,把小的放到后面 ----> 如果第二个比第三个小,同样交换他们的位置,以此类推 ----> 第二轮走访结束

这时候倒数第二小的数就“浮”到倒数第二列了

  • 第三轮走访开始 ----> 比较相邻的元素- —> 如果第一个元素比第二个元素小,就交换他们的位置,把小的放到后面 ----> 如果第二个比第三个小,同样交换他们的位置,以此类推 ----> 第三轮走访结束

这时候倒数第三小的数就“浮”到倒数第三列了

  • 以此类推,最多经过n-1轮循环

所有元素从大到小排序完成


实例演示

对2 3 1 5 4进行从大到小的降序排列。

第一轮走访开始

2 3 1 5 4(比较2和3,交换位置)

3 2 1 5 4(比较2和1,不交换位置)

3 2 1 5 4(比较1和5,交换位置)

3 2 5 1 4(比较1和4,交换位置)

3 2 5 4 1(第一轮走访结束)

最小的数1已经在最后面了,因此第二轮排序只需要对前面四个数进行再比较。

第二轮走访开始

3 2 5 4 1(比较3和2,不交换位置)

3 2 5 4 1(比较2和5,交换位置)

3 5 2 4 1(比较2和4,交换位置)

3 5 4 2 1(第二轮走访结束)

第二小的数已经排在倒数第二个位置了,因此第三轮排序只需要对前面三个数进行再比较。

第三轮走访开始

3 5 4 2 1(比较3和5,交换位置)

5 3 4 2 1(比较3和4,交换位置)

5 4 3 2 1(第三轮走访结束)

至此,排序结束。


时间复杂度

  • 若文件的初始状态是正序的,一趟扫描即可完成排序。
    所需的关键字比较轮数C和记录移动轮数M均达到最小值:C=n-1M=0
    所以,冒泡排序最好的时间复杂度为O(n)
  • 若初始文件是反序的,需要进行n-1趟排序。每趟排序要进行n-i轮关键字的比较(1≤i≤n-1),且每轮比较都必须移动记录三轮来达到交换记录位置。
    在这种情况下,比较和移动轮数均达到最大值:C=[n(n-1) ]/2=O(n^2) , M=[3n(n-1)]/2=O(n^2)
    所以,冒泡排序的最坏时间复杂度为O(n^2)
  • 综上,冒泡排序总的平均时间复杂度为O(n^2)

C语言实现代码

#include<stdio.h>
#define N 10 int main(void)
{int arr[N] = { 0,3,2,5,8,4,7,6,9,1 };//创建一个大小为N的数组,方便理解算法int i = 0;//控制走访轮数int j = 0;//控制数组元素下标int temp = 0;//申请一个临时的空间(数组元素交换时需要一个临时空间)for (i = 0; i < N - 1; i++)//最多走访N-1轮{for (j = 0; j < N - 1- i; j++)//每一轮相邻元素只需比较N-1-i次即可{if (arr[j] < arr[j + 1]){temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}//for循环执行完毕,排序完成,依次打印出排序完成后的数组元素for (i = 0; i < N; i++)//变量i清零赋予新的意义:控制打印个数{printf("%d ", arr[i]);}return 0;
}

加入用户输入程序

//常见代码会让用户输入他要排序的数据个数,但是有时候用户也不知道自己有几个数
//所以我想实现的是用户只输入一次数据,程序自动计算个数,然后在进行排序的一个过程
//但是调试之后你会发现下面的程序     有bug!有bug!有bug!#include<stdio.h>int main(void)
{int arr[1000];//创建一个长度为1000的数组int length = 0;//存放用户输入数据的个数int i = 0;//控制用户输入数据个数int j = 0;int temp = 0;printf("请输入您要排序的数列,数与数之间用空格隔开\n");for(i = 0; getchar() != '\n';i++){scanf("%d", &arr[i]);if (arr[i] >= 0 && arr[i] < 1000){length++;}}printf("您总共输入了%d个数据,重新排序后的结果如下:\n",length);for (i = 0; i < length -1; i++)//i清零赋予新的意义:在这里控制走访论数{for (j = 0; j < length - 1 - i; j++){if (arr[j] < arr[j + 1]){temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}//for循环执行完毕,排序完成,依次打印出排序完成后的数组元素for (i = 0; i < length; i++)//变量i清零赋予新的意义:控制打印个数{printf("%d ", arr[i]);}return 0;
}

对于上述程序bug的解决方案

如果你认真测试了这个程序,你会发现程序有bug,程序会吞入用户输入的第一个字符,那么这个bug该如何解决呢。

(我真的整整搞了一下午才发现,这对于刚入门的我也太太太太难了吧,差点就自闭了)

解决方法一:让用户在输入数据之前先输入一个字符给getchar()

解决方案二:申请一个flag整型变量,在第一次获取用户数据时将getchar()短路掉

//方案二更好一点,下面是按照方案二更改后的正确代码
int main(void)
{int arr[1000] = { 0 };int length = 0;int i = 0;int j = 0;int temp = 0;int flag = 1;//防止getchar()吞掉用户输入字符printf("请输入您要排序的数列,数与数之间用空格隔开\n");for(i = 0; flag||getchar() != '\n';i++){if (i == 0) flag--;//在i==0的时候,把getchar()短路掉,防止吞入用户输入的第一个字符。scanf("%d", &arr[i]);if (arr[i] >= 0 && arr[i] < 1000){length++;}}printf("您总共输入了%d个数据,重新排序后的结果如下:\n",length);for (i = 0; i < length - 1; i++){for (j = 0; j < length - 1 - i; j++){if (arr[j] < arr[j + 1]){temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}for (i = 0; i < length; i++){printf("%d ", arr[i]);}return 0;
}

对算法进行封装及调用

#include<stdio.h>int arr[1000] ={ 0 } ;
int length =0;//对于“获取用户输入函数功能”的封装
void scanf_sort(int* arr)
{int i = 0;int flag = 1;printf("请输入您要排序的数列,数与数之间用空格隔开\n");for (i = 0; flag || getchar() != '\n'; i++){if (i == 0) flag--;scanf("%d", &arr[i]);if (arr[i] >= 0 && arr[i] < 1000){length++;}}printf("您总共输入了%d个数据,重新排序后的结果如下:\n", length);
}//对于“冒泡排序“算法的封装
void bubble_sort(int* arr)
{int i = 0;int j = 0;int temp = 0;for (i = 0; i < length - 1; i++){for (j = 0; j < length - 1 - i; j++){if (arr[j] < arr[j + 1]){temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}
}//对于排序完成后“数组打印”功能函数的封装
int print_sort(int* arr,int length)
{int i = 0;for (i = 0; i < length; i++){printf("%d ", arr[i]);}
}//函数调用
int main(void)
{scanf_sort(arr);bubble_sort(arr);print_sort(arr,length);return 0;
}

运行结果

虽然这个小小的程序就实现了简单的"计算用户输入数据的个数"和"排序"两个功能,但是我真的搞了一天哇,我太菜了…自闭中…


算法优化

3 2 0 1 4 5 6 7 8 9从大到小排序,经过一轮排序后会变成2 0 1 3 4 5 6 7 8 9

可以发现原序列的后半部分是已经排好顺序了,所以在进行第二轮比较中,没必要和4 5 6 7 8 9再进行多余的比较

用flag代表比较的轮次,k代表该每一轮的比较次数,该优化过程就是在每一轮次中都更新轮次flag的值,不断缩小冒泡排序原始轮次范围N,从而达到排序的最大效率,避免不必要的比较。

#include<stdio.h>
#define N 10int main()
{int arr[N] = { 3,0,1,2,4,5,6,7,8,9 };int i = 0;int j = 0;int k = 0;int temp = 0;int count = 1;int flag = 10;while (flag > 0){k = flag;//用k记录每一轮的比较次数flag = 0;//while循环结束条件for (j = 0; j < k - 1; j++)if (arr[j] > arr[j + 1]){temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;flag = j + 1;//记录符合交换条件的最终位置}if (flag)count++;//记录比较轮次}printf("比较轮次:%d\n", count);for (i = 0; i < N; i++){printf("%d ", arr[i]);}printf("\n");return 0;
}

写在后面

啊啊啊啊啊,终于写完了,裂开了,人没了,写了整整一天,文中的那个bug我搞了整整一下午,这也太虐我这个小白了吧,太难了,还有最后一个算法优化我没有完全敲出来,借鉴其他博主的,改了一点点,还没搞懂代码一步步的逻辑,明日再看。应该还有其他的优化方案吧,后面学算法和数据结构的时候再继续搞。

好累好累好累,给孩子点个赞吧。 好累好累好累,给孩子点个赞吧。 好累好累好累,给孩子点个赞吧。

穷且益坚,当bug找到的那一刻,还有算法函数封装完成的那一刻,我太激动了,这种感觉,这种感觉真的太爽了。

休息去了…

哦对,如果上边有啥写错的地方,还请各位大佬在评论区给我订正哈,谢谢。

C语言排序算法(一):冒泡排序相关推荐

  1. C语言实例——四种排序算法(冒泡排序、选择排序、插入排序、快速排序)

    C 语言排序算法 BB Time 一.冒泡排序 1.原理 2.代码 二.选择排序 1.原理 2.代码 三.插入排序 1.原理 2.代码 四.快速排序 1.原理 2.代码 3.操作过程 BB Again ...

  2. C语言排序算法之简单交换法排序,直接选择排序,冒泡排序

    C语言排序算法之简单交换法排序,直接选择排序,冒泡排序,最近考试要用到,网上也有很多例子,我觉得还是自己写的看得懂一些. 简单交换法排序 1 /*简单交换法排序 2 根据序列中两个记录键值的比较结果来 ...

  3. golang 排序_常用排序算法之冒泡排序

    周末无事,带娃之余看到娃娃在算数,想到了排序-尝试着把几种常用的排序算法跟大家聊一聊,在分析的后面我会用GoLang.PHP和JS三种语言来实现下. 常见的基于选择的排序算法有冒泡排序.插入排序.选择 ...

  4. 十大排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序

    冒泡排序.选择排序.插入排序.希尔排序.归并排序.快速排序.堆排序.计数排序.桶排序.基数排序的动图与源代码. 目录 关于时间复杂度 冒泡排序 选择排序 插入排序 希尔排序 归并排序 快速排序 堆排序 ...

  5. C语言排序算法(十种排序代码可跑

    C语言排序算法(十种排序代码可跑) 冒泡排序: 选择排序: 插入排序: 归并排序: 快速排序: 希尔排序: 堆排序: 计数排序: 桶排序: 基数排序: 以上就是所有代码,希望同学们好好学习!!! 冒泡 ...

  6. 冒泡和快速排序的时间复杂度_常用排序算法之冒泡排序

    周末无事,带娃之余看到娃娃在算数,想到了排序-尝试着把几种常用的排序算法跟大家聊一聊,在分析的后面我会用GoLang.PHP和JS三种语言来实现下. 常见的基于选择的排序算法有冒泡排序.插入排序.选择 ...

  7. Java排序算法:冒泡排序

    Java排序算法:冒泡排序 //创建数组并赋值int[] data = new int[] {11,10,55,78,100,111,45,56,79,90,345,1000};for(int i=0 ...

  8. 排序算法:冒泡排序、插入排序、选择排序、希尔排序

    相关博客: 排序算法:冒泡排序.插入排序.选择排序.希尔排序 排序算法:归并排序.快速排序 排序算法:桶排序.计数排序.基数排序 排序算法:堆排序 十大排序算法小结 一.冒泡排序: 1.算法原理: 冒 ...

  9. c语言排序算法 应用与实现,基于C语言排序算法改进与应用.doc

    基于C语言排序算法改进与应用 基于C语言排序算法改进与应用 摘 要:介绍了程序语言中排序的原理及应用,阐述了基于C语言的三种主要排序方法,提出了每种排序方法的改进,计算出改进后算法的时间复杂度,编写了 ...

  10. 数据结构与算法:十大排序算法之冒泡排序

    数据结构与算法:十大排序算法之冒泡排序 package array;import java.util.Arrays;//冒泡排序 //1.比较数组中两个相邻的元素,如果第一个数比第二个数大,我们就交换 ...

最新文章

  1. eeglab中文教程系列(14)-Working with ICA Components
  2. 当前只读状态:是_Raft 只读(read-only)优化
  3. 截取屏幕,并保存图片到本地(画廊)
  4. 表现与数据分离;前台MVC
  5. Java异常处理throws/throw
  6. 深度优先遍历解决连通域求解问题-python实现
  7. 你需要掌握的事件分发高阶知识
  8. Jzoj5237 最长公共子序列
  9. java 操作系统 模拟 daima_编写一个程序,利用Java语言模拟操作系统进程调度管理...
  10. 周志华-机器学习西瓜书-第三章习题3.3 编程实现对率回归
  11. h5优秀控件_HTML5优秀图表控件
  12. Python-图像-伪彩色图像处理
  13. 计算机教程无线路由器桥接上网,2个无线路由器桥接教程详细步骤
  14. 软件测试助理利弊,女生做软件测试的利弊都有什么?
  15. linux 2.6.28.7 各驱动代码位置(待验证,已验证为蓝色标识)
  16. linux3.0字符设备驱动,v4l2驱动3-linux3.0.8中v4l2_format详解
  17. EasyX教程(一)
  18. html使用阿里图标库(iconfont)制作字体图标
  19. 智能锁忘记密码怎么办
  20. emWin在PC上的模拟

热门文章

  1. my eclipse2014破解步骤(转载)
  2. 漫城cms免费漫画+小说cms系统
  3. 智慧家居·万物互联:我的智能花盆DIY之旅(ESP32)
  4. 字符串匹配算法知多少?
  5. 软件著作权统计源程序量,统计php代码行数
  6. 读《别闹了,费曼先生》 时的几点想法
  7. 算法导论答案网Solutions to Introduction to Algorithms Third Edition_开源免费完整
  8. 4万字长篇,详解平安集团全生态布局及大数据业务应用研究
  9. matlab示例程序,matlab示例程序
  10. 大白菜U盘启动盘手动去除捆绑第三方赞助软件