归并排序数组合并流程困惑及给定Pascal代码填空求助
归并排序数组合并逻辑解析及代码填空指导
正在学习归并排序的数组合并流程,需严格遵循给定的Pascal代码(该代码支持升序/降序排序)。目前已理解代码除填空外的大部分内容,包括Merge过程的初始合并逻辑,但对其中一个子数组遍历完成后剩余元素的处理逻辑,以及后续的代码填空部分完全困惑,请求解析该部分逻辑并指导完成填空。
待填空的原始代码
const max = 200000; MaxDisp = 20; type list = array[1..max] of real; var a: list; na: longint; is_asc:boolean; procedure GenList(var L: list; n: longint); var i: longint; begin randomize; for i := 1 to n do begin L[i] := random; end; end; procedure DispList(L: list; n: longint); var i: longint; begin for i := 1 to MaxDisp do begin if i <= n then begin writeln(i:10, ' - ', L[i]:0:10); end; end; if n > MaxDisp then begin writeln(n - MaxDisp, ' more ...'); end; end; procedure sort(var L: list; n: longint;is_asc:boolean); procedure Merge(L1,L2,R1,R2:longint); var M:list;//this is C i1,i2,i,j,num:longint; begin i1:=L1; i2:=L2; j:=1; while (i1<=R1) and (i2<=R2) do begin if (is_asc and (L[i1] <= L[i2])) or (not is_asc and (L[i1] >= L[i2])) then begin M[j]:=L[i1]; j:=j+1; i1:=i1+1; end else begin M[j]:=L[i2]; j:=j+1; i2:=i2+1; end; end; if(i1>R1) and (i2<=R2) then for i:=i2 to R2 do begin M[j]:=L[i]; j:=j+1; end else if (i2>R2) and (i1<=R1) then for i:=i1 to R1 do begin M[j]:=L[i]; j:=j+1; end; num:=R2 - L1 + 1; i:=L1; for j:=1 to num do begin L[i]:=M[j]; i:=i+1; end end; procedure MSort(LL,RR:longint); var mid:integer; begin if LL<RR then begin mid:=(LL+RR) div 2; MSort(LL,mid); MSort(mid+1,RR); Merge(LL,mid,mid+1,RR); end end; begin MSort(1,n); end; function is_sorted(L: list; n:longint;is_asc:boolean): boolean; var i: longint; flag: boolean; begin flag := true; i := 1; while flag and (i < n) do begin flag := ((L[i]<=L[i+1]) and (is_asc)) or (not(is_asc) and (L[i]>=L[i+1])); i := i + 1; end; is_sorted := flag; end; begin na := MaxDisp; GenList(a, na); writeln(na, ' random items:'); DispList(a, na); writeln('Press <Enter> to sort the list in ascending order ...'); readln; is_asc := true; sort(a, na,is_asc); DispList(a, na); writeln('Sorted in ascending order: ', is_sorted(a, na,is_asc)); write('Press <Enter> to continue ...'); readln; end.
关键逻辑解析
剩余元素处理逻辑
归并排序的Merge过程负责将两个已排序的子数组(L[L1..R1]和L[L2..R2])合并到临时数组M中:
- 初始循环:同时遍历两个子数组,根据升序/降序规则选择较小(或较大)的元素放入
M,直到其中一个子数组遍历完毕。 - 剩余元素处理:
- 若第一个子数组(
L1..R1)已遍历完,第二个子数组(L2..R2)剩余的元素本身就是有序的(因为子数组已经过排序),直接全部追加到M的末尾即可。 - 反之,若第二个子数组已遍历完,将第一个子数组的剩余元素直接追加到
M末尾。
这一步不需要再做比较,因为剩余元素的顺序已经符合排序要求,且都大于(升序)或小于(降序)已经合并到M中的元素。
- 若第一个子数组(
代码填空说明
- 冗余代码删除:原
while循环内的j:=________;是多余的,因为每次循环中已经执行了j:=j+1,直接删除该行。 - 第一个剩余元素循环:
for i:=i2 to R2 do—— 遍历第二个子数组的剩余元素;M[j]:=L[i]; j:=j+1;—— 将元素放入M并移动指针。 - 第二个剩余元素循环:
for i:=i1 to R1 do—— 遍历第一个子数组的剩余元素;M[j]:=L[i]; j:=j+1;—— 同上。 - 总元素数计算:
num:=R2 - L1 + 1—— 合并的元素范围是从L1到R2,总数量为末尾索引减起始索引加1。 - 原数组复制:
i:=L1—— 从原数组的起始位置开始覆盖;L[i]:=M[j]; i:=i+1;—— 将临时数组M的有序元素复制回原数组L的对应位置。 - 额外修正:原代码的排序条件逻辑错误,将
(is_asc and (L[i1]<L[i2])) or not is_asc and (L[i1]<L[i2])修正为(is_asc and (L[i1] <= L[i2])) or (not is_asc and (L[i1] >= L[i2])),否则升序/降序判断失效;同时补充num的变量声明,以及主程序中is_asc的赋值。
内容的提问来源于stack exchange,提问作者user1039203
相关产品推荐
相关产品推荐

