下图为编写解决荷兰国旗问题的经典程序(红0白1蓝2):
但是实际运行结果(如下图)并不与预期相符,且只有首位为0时可能出现错误。
下面编者将对原因进行探讨:
Ⅰ.首先分析只有1和0的特殊情况:此时需要分首位为0和首位不为0两种情况。
一.首位为0(不止首位1个0)时:由于在程序运行过程中,首位元素始终不被next判断,造成实际触发互换机制与首位非0相比少了一次,进而造成某些情况下程序运行结果出错。
下面举几种出错情况:
1.当首位0和第二个零之间的1多于第二个0之后的0的数量时,程序运行结果必会出错。为了便于理解,可以认为第三个及以上的0起到了替换被夹着的1的作用。
例如:0 1 1 0 0运行结果为0 0 1 0 1;而 0 1 1 1 0 1 0 0 0运行结果为0 0 0 0 0 1 1 1 1。
2.当第1种错误情况未出现时,依然有可能出现错误情况。
例如:0 1 1 0 1 0 0 0;0 1 0 1 1 1 1 0 0 0 0;
此种情况出错的原理与第1种一致,可将其视为第1种情况的嵌套。当第二个0后面的0依次与夹着的1互换后,可能会再次出现两0夹1的结构(即第二个0后面的0多于夹着的1),原来的第二个0成为新结构中“第一个”零,此时判断方法与第1种情况类似,即判断两0夹1结构后面的0的个数是否多于结构中1的个数。
二.首位不为0时:程序结果不会出错。
Ⅱ.接下来分析只有2和1的特殊情况:此时仍然分析首位为2和首位不为2两种情况。
一.首位为2:由于无0存在首位一直是2,程序必出错。但除首位外,其余部分排列正常。
二.首位不为2:程序结果不会出错。
Ⅲ.最后分析0、1、2均存在的情况:分为首位为1、首位为0、首位为2三种情况。
一.首位为1:程序不会出错。
二.首位为2:程序不会出错。由于有0的存在,首位2会被换到后面,这就避免了Ⅱ(一)型的出错情况,程序也就不会出错。
三.首位为0:程序可能出错。经过大量试验可以发现,程序最终结果中2总在最后。那么我们可以套用Ⅰ型错误情况进行分析。
1.一组两0夹1:当只存在首位0和第二个0组成的两0夹1结构时,后面的1与2等价,不会影响结果,判断方法与Ⅰ(一)一致。
2.一组两0夹2:当只存在首位0和第二个0组成的两0夹2结构时,next读取到2就会触发后调机制将2向末尾调。若换回来的是1,程序继续执行,无变化;若换回来的是0,触发前调机制将0向前移动,换回来的必是1,相当于最后面的0先替换两0所夹元素而非排序较前的0。判断方法仍与Ⅰ(一)一致。
2.一组两0夹1、2:当next读取到两0所夹1时,无变化。当next读取到两0所夹2时,触发后调机制将2向后移动,若换回来的是1,程序继续执行,无变化;若换回来的是0,触发前调机制将0向前移动,换回来的必是1,相当于最后面的0先替换两0所夹元素而非排序较前的0。综上,我们依然可以通过Ⅰ(一)的方法进行判断。
3.多组两0夹1、2:此时原理及判断方法与Ⅰ(2)完全一致,此处不再赘述,建议读者自行思考检验理解程度。
现在关于荷兰国旗问题运行出错的分析到此结束,总而言之,是程序设计存在漏洞,进而导致对于一些特殊数据无法得出正确结果。
本人学识有限,如有错误之处还望指正。