同学用C++编写了一个快速排序的程序,实现如下功能:
1,用一个数组包含原始数据;2,用一个数组包含每个原始数据的地址;3,利用快速排序算法,对第二个数组进行排序。
很显然,排序的交换操作与原始数据的存储分开进行,是为了节省时间。
算法写出来了,程序编译运行了,但是:排序前和排序后,输出的结果居然是一样的。
我最初的想法是:既然排序前后输出一样,那么很可能是根本没有发生交换[1]。
然而看了同学的代码,似乎又没有这种错误;此外,他是按照书上的示例敲的代码,虽然现在水货书很多,但一般敢拿出手运行的代码(不是伪代码),出错的可能性不大[2]。
第二种可能性是:数据在发生交换以后,又因为程序中某个书写错误,被换回去了。这种错误比较麻烦,因为我必须读懂算法才行。如果要是一行行读懂、然后一行行检查,这个时间完全可以让我重新写一遍新的算法!
我不希望读算法,另外,我觉得同学既然写出了这个算法,而且他确实明白快速排序的实现机制,那么至少框架上,不会有大的问题。所以,“书写错误”可能性较大[3]。
我在VC中定义了观察变量,观察每个数组元素的变化情况(指针数组)。在调试过程中,我直接将断点设置在swap操作上,判断它是否中断[4]。经测试发现,数组发生了变化:错误没像我预计的那么简单,但是很清楚:一定是逻辑上出问题了。
既然是逻辑错误,那么一定在运算的过程中发生问题(到现在为止,我对同学的代码基本上没有阅读)。我需要从算法运行过程中,产生的数据,定位“逻辑错误”的所在[5]。
耐心地跟踪程序,顺便花了快速排序的步骤流程:每一步发生交换,数组会是什么样子。交换指针其实和交换原始数据是一样的,所以,理解上一点也不困难。老实说,这本书上的排序算法和以前学的还有点不同,在最开始的时候搞了个swap操作,将最中间的元素放到数组开始——故弄玄虚,没有必要,BS一下这个作者。
突然灵光一闪:4、9交换以后,为什么又被交换成9、4了[6]?计算机是不会错的,它一定是在进行了某次“比较”之后,发现“条件符合”,就将两个元素交换了。
当我将注意力集中到这个地方时,swap函数的嫌疑已经大大减轻了,sort函数的开始有一些初始化代码,也很容易排除嫌疑。再结合“比较逻辑”这个线索,我将目光集中在if语句和接下来的交换操作上:果然,一个下标的写错了。p[start]被写成了p[current],对着书上代码看一看,OK了。
[1] 记得在最初学习C语言“传值”的时候,swap函数很可能出现这种情况。
[2] 其实在这个时候,如果想要排除这种可能,不妨花一点点时间,换几组测试数据多试几次。如果每次都输入输出一致,那么“根本没有发生交换”的可能性会较大;如果某次不一致,那这种错误的可能性就排除了。
[3] 在这个时候,我其实应该问问他算法的书写过程是怎样的——这对于我定位错误很有帮助。事后我才知道,同学是先阅读算法、代码,然后按照算法的思路进行默写;而不是照着书本一行行地敲代码。他思路上的理解失误,就很可能导致程序的书写错误。
[4] 如果从头到尾都没有发生swap操作,那么可想而知,数组根本没有变化,输入输出也就是一致的了。
[5] 否则,建议重写程序;如果有兴趣的话,前后对比。
[6] 在最开始我就应该想到:数组操作最容易出错的地方是哪里?下标!