万事开头难。重新开头更难。本来现在的水平写不出来个啥,可是不开始永远也无法开始。
重回这条不归路,视野啊、远见啊未必比那些纯新人好,只能更努力一点了。在现有见识的边界内,我对算法、数据结构、设计模式等异常重视,基础比想象的重要。即使有人编码几年了,这些基础依然很烂但却没影响拿工资,我也依旧重视。这些基础才是程序员的生命,它比想象的重要。
这些天开始看数据结构,任何数据结构的书开头部分(第1、2章或者导论)都会写一些概念性的东西。看的头疼,不过我还是很喜欢的,定义都是严谨的。虽然没有那么聪明的头脑,但是不影响我欣赏数学的严谨,最起码观赏总还是做得到的。蝇营狗苟的蹒跚于每行代码、实现细节、客户要求等的时候,我想还是要有一个心思去体会些纯的IT界的东西,然后联通所谓美学、哲学、方法论。
先从排序算法开始吧,我是现学现思考现记录,希望写下的东西值得保留,估计这东西要写一段时间了,一点点添加吧。
冒泡排序
全是自己表述的,黄底部分是我的想法,其他的没啥看头了。
冒泡是比较生动形象的表述这种排序算法的特点,石块沉入水中,冒出个泡来。大的往下沉、小的往上浮。第一次,找出最大的沉到最下面,第二次,在剩余的里面找出最大的,沉到下面……最后剩一个了,就是最轻的不用动了。所以如果n个数字排序,需要进行n-1趟:第1趟在n个数字里找出最大的;第2趟在n-1个数字里找出最大的;……第n-1趟在2个数字里找出最大的。
假设一个班级有n名学生,都参加了数据结构的考试,那么就有了n个成绩,即成绩数组arrScores[n]。用冒泡算法从小到大排下序吧。
按照算法思路:
(1)需要进行n-1趟挑选、调换。那么就是
for(int i = 1 ; i < n ; ++i)
这里有人喜欢i = n然后--i,或者喜欢i = 0,我认为都是不好的。程序是给人看的,既然外围的循环思路是进行n-1趟,那么自然应该是从1加到n-1,对应第1趟、第2趟……
(2)在第i趟里,挑选出剩余数目中的最大者。
for(int j = 1 ; j < n - i + 1 ; ++j )
if(第 j 个数据大于第 j+1 个数据) //交换
第i趟时,已经进行了i - 1趟,挑选出了i - 1个数字,所以剩余数目是n - (i - 1) = n- i + 1个,需要n-i次比较找出最大的,但在编写成绩时,我们需要对数组进行操作,而数组下标从0开始,因此内循环中j记录下标较合适,即
for(int j = 0 ; j < n - i ; ++j )
if(arrScores[ j ] >arrScores[ j+1]) ) //交换
这里有个问题,就是内循环中j必须取定值,即 0或者n-1,不可能是关于i的表达式,每次挑选都是从数组的一个方向开始,把最小的或者最大的数字放置到另一个方向,然后边界向开始的方向移动(即将排好的数字排除下次排序)。
完整的语句是
for(int i = 1;i < n;++i)
for(int j = 0;j<n - i;++j)
if(arrScores[j]>arrScores[j+1])
{
temp = arrScores[j];
arrScores[j] = arrScores[j+1];
arrScores[j+1] = temp;
}
当然,如果稍微优化一下,就是加一个标签,假设第i趟发现没有移动,即数组已经顺序排列,那么就不用继续了。
优化后的完整代码为:
int temp = 0;
bool change = true;
for(int i = 1;(i < n) && change;++i)
{
change =false;
for(int j = 0;j<n - i;++j)
if(arrScores[j]>arrScores[j+1])
{
temp = arrScores[j];
arrScores[j] = arrScores[j+1];
arrScores[j+1] = temp;
change = true;
}
}