C选择和冒泡排序程序心得

来源:互联网 发布:洲际巡航导弹知乎 编辑:程序博客网 时间:2024/05/17 23:30

好的,今天C语言课为了应付期末考试教了选择和冒泡排序法,本着“直接抄现成代码P用没有”的观念我很决绝的没有抄老师给的代码,听完思路以后回来自己写了一遍。

先说冒泡的代码吧

//使用冒泡法对一个int数组进行排序#include<stdio.h>void swap (int *a, int *b);int main (void){int ar[5], time1 = 0, time2 = 0, num = 0;printf("Please enter 5 intgers:");for ( num = 0; num <= 4; num++)scanf("%d", &ar[num] );for ( time1 = 0; time1 < 4; time1++){for ( time2 = 0 , num = 0; time2 < 5 - time1; time2++, num++){if (ar + num > ar + num + 1)swap( ar + num, ar + num + 1 );}}for ( num = 0; num <= 4; num++)printf("%d\t", ar[num] );printf("Done.\n");return 0;}void swap (int *a, int *b){int temp = *a;*a = *b;*b = temp;}

恩,很明显失败了。原因很SB,排序的二次循环中的判断条件(即第12行)...........翻译一下应该是“如果ar+num的大小超过ar+num+1”。先不说从数学上来说这绝壁是错的,而且ar作为一个数组名,这样计算的结果肯定是地址啊前一个数组元素的地址肯定小于后一个的地址啊.........我的原意应该是“如果ar中第num个元素的大小大于ar中第num+1个元素”。刚开始的时候还没发现错误在这里,真是耻辱..........

找到了bug,调试以后产生了2.0版本(雾),如下

//使用冒泡法对一个int数组进行排序#include<stdio.h>void swap (int *a, int *b);int main (void){int ar[5], time1 = 0, time2 = 0, num = 0;printf("Please enter 5 intgers:");for ( num = 0; num <= 4; num++)scanf("%d", &ar[num] );for ( time1 = 0; time1 < 4; time1++){for ( time2 = 0 , num = 0; time2 < 5 - time1; time2++, num++){if (ar[num] > ar[num + 1])swap( ar + num, ar + num + 1 );}}for ( num = 0; num <= 4; num++)printf("%d\t", ar[num] );printf("Done.\n");return 0;}void swap (int *a, int *b){int temp = *a;*a = *b;*b = temp;}

(其实就是改了那个判断条件......

编译通过,然后调试,结果不尽人意.......


其他的都没什么问题,但那个4是从哪冒出来的???

我的内心是崩溃的...........

找错误过程:检查了一下输入和输出的差别,输入中的42没有出现在输出中,42恰好是最大的那个,于是我重新换了输入,把42换成了另一个数,但仍是输入中最大的(原谅我没有截图......),输入结果和第一次相同,其他数字排列大小顺序正确,但唯独最大的那个不见了,而且每次ar[1]都会替换成4,思考一下,目测是在排序时对数组元素进行处理时超过了下标。重新检查了几遍排序部分,二次循环中退出的条件确实不太对,即time2<5-time1(在这里我就不讲究缩进了)。举例验证,外层第一次循环时time1=0,那么二层退出条件应该是time2<5,由于对比的元素是num和num+1,此时num=5没有问题,但num+1为6,超出了数组的大小,也就是说最后一次对比时弄到了一个不知道什么玩意的东西和当时数组中最大的元素进行了对比,导致最大元素被舍弃,未知元素被保留。

恩,场面极度混乱,我已经完全不知道我在干嘛了........

解决问题很简单,把内层循环退出条件换成time2<4-time1即可

于是产生了V3.0(雾):

//使用冒泡法对一个int数组进行排序#include<stdio.h>void swap (int *a, int *b);int main (void){int ar[5], time1 = 0, time2 = 0, num = 0;printf("Please enter 5 intgers:");for ( num = 0; num <= 4; num++)scanf("%d", &ar[num] );for ( time1 = 0; time1 < 4; time1++){for ( time2 = 0 , num = 0; time2 < 4 - time1; time2++, num++){if (ar[num] > ar[num + 1])swap( ar + num, ar + num + 1 );}}for ( num = 0; num <= 4; num++)printf("%d\t", ar[num] );printf("Done.\n");return 0;}void swap (int *a, int *b){int temp = *a;*a = *b;*b = temp;}
这次也只改了一个细节,调试结果:


OK完全没有问题,虽然我觉得这代码有点冗余,应该还能缩减,鉴于时间原因我就得过且过了(躺)。


然后说选择排序法

有了冒泡的经验,这次写代码少了很多弯路,但还是有个地方让我纠结了半天:上课时说的选择法是在循环中定义一个变量作为一个“伪指针”,它实际上是数组的下标,通过控制下标的数字来在数组中遍历一次找到最小的放到第一个或者最后一个(也可以是最大的)原版的代码好像是这样的:


好吧我忘了...................我真忘了...........为了保证我回来时写的代码是我自己的思路我特地没有去记.....

没关系无伤大雅,我只记得和我写的在思路上可能有点不一样,直接上代码:

//使用选择法来对一个数组排列大小#include<stdio.h>void swap (int *a, int *b);int main (void){int ar[5], time1 = 0, time2 = 0, min = 0, num = 0;printf("Please enter 5 intgers:\n");for ( time1 = 0; time1 <= 4; time1++)scanf("%d", &ar[time1]);for ( time1 = 0; time1 < 4; time1++){for ( time2 = 0, num = time1; time2 < 4 - time1; time2++){//从time1开始计数,用ar[min]遍历一次time1后的数组元素,直接将最小的换到ar[min]if ( ar[min] > ar[num]){swap (ar + min, ar + num);}}min++;//数组排列的结果应该是从小到大,因此在二层循环过后就不需要再计算ar[time1]之前的元素了}for ( time1 = 0; time1 <= 4; time1++)printf("%d ", ar[time1]);printf("Done.\n");return 0;}void swap (int *a, int *b){int temp = *a;*a = *b;*b = temp;}
思路:注释写的很明白了(躺)

编译通过,开始调试:
不得不说这个错误就有点莫名奇妙了......直接看输入输出没找到结果,只能回去翻代码了,不过问题倒是能确定在排序部分了。

第一遍查看,没发现错误.....

第二遍,还是没有.....

第三遍,找到了........

尼玛下标num没变啊!!!(╯‵□′)╯︵┻━┻

这比较个P啊?不是只有ar[0]和ar[1]比较了么?(╯‵□′)╯︵┻━┻

怀着剖腹的心情改掉了bug........

V2.0如下:

//使用选择法来对一个数组排列大小#include<stdio.h>void swap (int *a, int *b);int main (void){int ar[5], time1 = 0, time2 = 0, min = 0, num = 0;printf("Please enter 5 intgers:\n");for ( time1 = 0; time1 <= 4; time1++)scanf("%d", &ar[time1]);for ( time1 = 0; time1 < 4; time1++){for ( time2 = 0, num = time1; time2 < 4 - time1; time2++, num++){//从time1开始计数,用ar[min]遍历一次time1后的数组元素,直接将最小的换到ar[min]if ( ar[min] > ar[num]){swap (ar + min, ar + num);}}min++;//数组排列的结果应该是从小到大,因此在二层循环过后就不需要再计算ar[time1]之前的元素了}for ( time1 = 0; time1 <= 4; time1++)printf("%d ", ar[time1]);printf("Done.\n");return 0;}void swap (int *a, int *b){int temp = *a;*a = *b;*b = temp;}
调试结果如下:
成功,搞定

不管怎么说在做选择法的时候总算没有出现超出数组下标的情况,我还是有点欣慰的......


其实今天还教了链表,不过鉴于今天时间比较紧,就没做这方面的练习了。明天会先熟悉一下链表的知识,鉴于我对于链表还处于asshole状态,我决定先从书上抄几个栗子理解一下。做完链表之后再把今天的两个练习倒过来做一遍,即原来按从大到小,现在按从小到大。

最后还是要吐槽一下,尼玛C语言上课有我们这么上的么?(╯‵□′)╯︵┻━┻,毛都没听懂啊下节课就开始讲下一节了,是人干的事么?!

最后的最后,我还是要说:primer plus上第十章“指针和数组”是我做的笔记最多的一章...........前面的内容画画重点就能懂,这一章尼玛我要把所有的代码全部翻译一遍才能懂这程序是干嘛的,有些地方还要重点标出来那些数组名和指针的详细属性.........

第十章了,前面九章加起来的笔记都没有这一章长..........

0 0
原创粉丝点击