COBOL冒泡排序仅对表末尾元素排序问题排查
问题分析与修正
你遇到的问题核心有两个,导致排序只完成了第一轮就停止了:
1. 内层循环的CNT2没有在外层循环迭代时重置
第一次内层循环结束后,CNT2已经被加到了6。之后每次进入外层循环时,PERFORM UNTIL CNT2>5的条件直接成立,内层循环完全不执行,自然不会继续排序剩下的元素。
2. 外层循环终止条件不合理
对于包含5个元素的数组,冒泡排序只需要4次外层循环(每轮把一个最大元素移到末尾,4轮后所有元素有序),而你的代码写的是PERFORM UNTIL CNT>6,会导致多余的循环迭代。
另外,你的当前逻辑其实更偏向选择排序(拿当前元素和后面所有元素比较交换),而非标准的冒泡排序(相邻元素两两比较,逐步把大元素“冒泡”到末尾)。如果目标是实现冒泡排序,我们可以调整逻辑;如果想保留类似选择排序的写法,也需要修正CNT2的重置问题。
修正后的冒泡排序代码
下面是符合标准冒泡排序逻辑的修正版本,我会标注关键修改点:
IDENTIFICATION DIVISION. PROGRAM-ID. BubbleSort. DATA DIVISION. WORKING-STORAGE SECTION. 01 TVAR PIC 9(4). 01 CNT PIC 9(1) VALUE 1. 01 CNT2 PIC 9(1) VALUE 1. 01 ARR. 05 ARRELEMENT PIC 9(4) OCCURS 5 TIMES. 01 TABLELENGTH PIC 9(1) VALUE 5. 01 SWAPPED-FLAG PIC X(1) VALUE 'N'. // 新增:标记本轮是否有交换,优化冒泡排序 PROCEDURE DIVISION. DISPLAY "Enter 5 numbers: ". PERFORM INPUT-PARA VARYING CNT FROM 1 BY 1 UNTIL CNT>5. DISPLAY "Pre Bubble-Sort: ". PERFORM PRINT-PARA VARYING CNT FROM 1 BY 1 UNTIL CNT>5. PERFORM BBLSORT-PARA. DISPLAY "Post Bubble-Sort: ". PERFORM PRINT-PARA VARYING CNT FROM 1 BY 1 UNTIL CNT>5. STOP RUN. INPUT-PARA. ACCEPT ARRELEMENT(CNT). PRINT-PARA. DISPLAY "Table element: " ARRELEMENT(CNT). BBLSORT-PARA. INITIALIZE CNT SWAPPED-FLAG. PERFORM UNTIL CNT >= TABLELENGTH OR SWAPPED-FLAG = 'N' MOVE 'N' TO SWAPPED-FLAG. // 初始化为无交换 PERFORM VARYING CNT2 FROM 1 BY 1 UNTIL CNT2 > TABLELENGTH - CNT IF ARRELEMENT(CNT2) > ARRELEMENT(CNT2 + 1) THEN DISPLAY ARRELEMENT(CNT2) " IS > " ARRELEMENT(CNT2 + 1) MOVE ARRELEMENT(CNT2) TO TVAR MOVE ARRELEMENT(CNT2 + 1) TO ARRELEMENT(CNT2) MOVE TVAR TO ARRELEMENT(CNT2 + 1) MOVE 'Y' TO SWAPPED-FLAG. // 标记有交换 END-IF END-PERFORM ADD 1 TO CNT GIVING CNT END-PERFORM. END PROGRAM BubbleSort.
关键修改说明:
- 新增
SWAPPED-FLAG:如果某一轮没有发生任何交换,说明数组已经有序,可以提前终止排序,优化效率。 - 外层循环条件改为
UNTIL CNT >= TABLELENGTH OR SWAPPED-FLAG = 'N':既保证最多执行4次循环,又能提前结束。 - 内层循环改为
VARYING CNT2 FROM 1 BY 1 UNTIL CNT2 > TABLELENGTH - CNT:每完成一轮外层循环,末尾的CNT个元素已经有序,不需要再比较,减少不必要的迭代。 - 内层循环比较相邻元素(
CNT2和CNT2+1):这是标准冒泡排序的核心逻辑,每次把当前未排序部分的最大元素“冒泡”到末尾。
如果你想保留原逻辑(类似选择排序)
如果你的初衷是写选择排序(拿当前元素和后面所有元素比较,把最小元素放到当前位置),只需要修正CNT2的重置问题即可:
BBLSORT-PARA. INITIALIZE CNT. PERFORM UNTIL CNT >= TABLELENGTH MOVE CNT + 1 TO CNT2. // 外层循环每次重置CNT2为当前位置的下一位 PERFORM UNTIL CNT2 > TABLELENGTH IF ARRELEMENT(CNT) > ARRELEMENT(CNT2) THEN DISPLAY ARRELEMENT(CNT) " IS > " ARRELEMENT(CNT2) MOVE ARRELEMENT(CNT) TO TVAR MOVE ARRELEMENT(CNT2) TO ARRELEMENT(CNT) MOVE TVAR TO ARRELEMENT(CNT2) END-IF ADD 1 TO CNT2 GIVING CNT2 END-PERFORM ADD 1 TO CNT GIVING CNT END-PERFORM.
这样修改后,输入5、4、3、2、1就能得到正确的升序结果1、2、3、4、5了。
内容的提问来源于stack exchange,提问作者Glycemic Beg
相关产品推荐
相关产品推荐

