如果给你一连串的数字让你按照从小到大的顺序排列你会怎么办呢?挨个比较吗?我这有一种好玩的排序方法叫做冒泡排序。其实,冒泡法排序是C 语言中,较经典的一种排序方法。哈哈哈,经典不经典我不知道,反正我接触的第一种排序方法就是它。冒泡法,顾名思义,就像小水泡一样,轻的往上飘,重者往下落。
我想到一个场景:相传在天地还没有诞生以前,宇宙是漆黑混沌一团。盘古开天辟地,轻者往上飘形成天,浊着往下沉形成地。哈哈哈!冒泡法排序和盘古开天辟地很相似。
理论定义部分不想过多的描述。举一个例子吧:
例如,有5个数:5、9、3、6、4。他们分别住在A,B,C,D,E五个房子里。当然了,你也可以把它们想象成,分别蹲在A,B,C,D,E五个坑位里。在坑里干啥,自己想象。
冒泡法排序是这样玩的:两个数分别两两比较,如果前者大于后者,他们两个就要互换位置,也就是它俩要换坑位。
第一趟:首先,A坑中的5要和B坑的9比较。显然5>9是错误的。那换坑失败。A坑里还是5,B坑里还是9。然后B坑里的9要和C坑里的3比较。显然9>3 。B和C互换位置。现在B坑里是3,C坑里是9。换坑继续。C坑里的9 要和D坑里的6 比较。显然,9和6要互换位置的。此时,C坑里是6 ,D坑里是9。换坑仍在继续。D坑里的9 要和E坑里的4比较。显然,他俩是要互换的。
经过第一趟比较下来,现在这五个坑里分别是5、3、6、4、9 就如开天辟地一样,这五个数中最大的往下“沉”。第一趟下来,最大的数沉到了最下边。
我们还发现,第一趟比较了4次就把最大的数“沉”底了。那么第二趟我只需要比较A、B、C、D就可以了吧!
第二趟:A坑里的5和B坑里的3比较。5>3,5和3互换。A坑里是3,B坑里是5。B坑里的5和C坑里的6 比较。显然两者位置不互换。换坑继续。C坑里的6和D坑的4比较。6和4互换。现在C坑里是4 ,D坑里是6。
那现在A,B,C,D,E五个坑里的数字是怎样的呢?它们是:3、5、4、6、9 。经过第二趟的比较,已经把第二大的数沉到了第二大的位置。
除此之外,我们还发现:第二趟我们比较了三次
那么第三趟我们只需要比较两次就可以了。经过比较同样的道理,我们可以把第三大的数字沉下去的。第三趟的比较结果是:3、4、5、6、9
第四趟只需要比较一次,也就是A坑和B坑的位置就可以。第四趟的比较结果是:3、4、5、6、9 。
这四趟下来,轻者为天,浊者为地。将一堆错乱无序的数字,按照从小到大的顺序排列开来。天地分明,世界也变得有秩序起来。
这就是所谓的冒泡法排序。
从这里面我们可以找到一些规律。5个数相比较时。我们需要比较4趟。第一趟需要比较4次,第二趟比较3次,第三趟比较2次,第四趟比较1次。
那10个数字相比较呢?也是同样的道理。数字少的时候还可以操作。但数字一多,是不是就显得有点繁琐了呢!是的,但是我们可以找一个人来帮我们做,它从不嫌累,非常喜欢这种重复性的工作,而且它的速度要比我们一般人要快的多。它就是——计算机。
只有计算机是不够的,没有人操纵它,也没有人对它下达指令,它是不会听你的话的。但是遇到一个问题,我怎么对它下达指令,它怎么才能让它完全服从与我呢!大家都知道,计算机是只认识二进制的0和1 的,其余的它一概听不懂,你说的再多,无非就是对牛弹琴。
就像懂你的人无须过多的解释,一个眼神,一个动作,就能懂你。有的人,解释的再多或者长篇大论对它丝毫不起作用。扯远了,咱还是继续冒泡吧!
这时就出现了一个中间者或者第三者,无所谓,你怎么称呼它都可以。这个中间者呢,本领很大。既能听懂计算机的话,也能理解人的意图。人想要计算机做什么,先把意图给这个中间者说,中间者理解了以后,再转述给计算机,让计算机来执行命令。
那这个中间者这么牛掰,是何许人也人。他就是大名鼎鼎的高级语言。它的家族呀,人丁兴旺。有汇编语言、C语言、C++、JAVA语言,还有Python等。
今天呢,我们就用C语言来实现10个数字从小到大的排序。
话不多说,先展示一下我写的一段代码:
C语言的一些语法规则在这里就不多说了。有兴趣的话可以找一些资料多了解一下。说不定一下子,你也会成为大神级别的人物了呢!在这里推荐谭浩强的《C程序设计》很不错的,我在业余时间里也会时不时的看一点。有时自己不够自律,也有时确实有一些乱七八糟的事,时间被切的很碎。时间挤一挤还是有的,说到底还是自己的原因。
嗯,写到这里就完了吗?不是的。在练习冒泡法排序时遇到了一些问题。想不明白,所以才会有了这篇更文。
起初在敲写代码时,在for{i=0;j<9-J;i++},这里多了一个“=”,变成了for{i=0;j<=9-J;i++},这样呢,就使每趟比较时,多比较了一次。所以一直得不到预期的结果。后来,经过多次分析,找到问题所在。
没找到问题的所在时,很是疑惑。
像上面的例子,最大的数777为什么没有了?为什么会凭空出现了一个26?26究竟是哪来的呢?
我又做了以下实验:
让它只比较一趟。将for(j=0;j<9;j++) 中改为 for(j=0;j<1;j++)
发现,最大的数7776,本应该沉到最底的,但是却被横空出世的26代替了。
后来的后来,刹那间,我找到了答案。会不会和ACSII码有关。嗯,还真是。
ACSII码中26是特殊字符,代表的意思是替代。
我们还是用前面5个数字比较的例子证明。
例如还是有5个数:5,9,3,6,4。他们分别住在A,B,C,D,E五个房子里,(五个坑位也可以)。
在第一趟比较的时候,按照常规的思路,5个数第一遍应该比较4次。那比较的结果应该是5、3、6、4、9 。但是,因为写代码时,多写了一个等于号。也就是在for{i=0;j<4-J;i++},这里多了一个“=”,变成了for{i=0;j<=4-J;i++},那么就会使本应该比较4次的,却比较5次。
那第五次应该怎么比较呢。
按理说应该是E坑里的9和下一个坑位中的数字比较。下一个坑位没有呀!只有5个坑位,去哪弄第六个坑位呢!那么计算机就会虚拟一个坑位“F”,那F坑位里的数字是多少呢?就是ASCII码中的26。是一个特殊字符,代表替代的意思。第五次比较,应该就是E中的9和虚拟坑位F中的26相比较。26大,9小,他们两个是不会互换位置的。那最终得出的结果依然会是正确的。
究竟什么时候不正确呢?在从小到大升序排列,当输入的数字大于26时,就会出现错误。
例如E坑位里的数字是27,那显然E坑位里的数字是要和虚拟坑位里的数字互换位置的。如果原本是5、27、3、6、4的话,按照错误的代码,第一趟比较的结果就应该是5、3、6、4、26。就会出现错误。
也就是说,如果输入的数据中有大于26的话,计算机在第一趟比较时,就会把最大的那个数,替换成26,在后续的比较过程中,用26参与比较。
那这样,777的突然消失和26在第三个坑位凭空出现就可以自圆其说了。
不知道我的解释是否合理。本来还想有奖竞答呢!哈哈哈!有不同的观点,只要能说服我,同样有奖!