我睡过了问题Quicksort drama的答案,并希望从头开始重新编码,使用call-by-reference var实现你的提示。再说一遍:我再也找不到任何失败。我将代码逐一与您的程序进行比较,但我找不到问题。以下代码在编译/运行期间生成异常(外部:地址为11602的SIGSEV)
program quicksort;
var
iArray : array[0..8] of integer;
procedure fillArray(var iArray : array of integer);
begin;
iArray[0] := 3;
iArray[1] := 1;
iArray[2] := 8;
iArray[3] := 4;
iArray[4] := 9;
iArray[5] := 0;
iArray[6] := 8;
iArray[7] := 2;
iArray[8] := 5;
end;
procedure writeArray(iArray : array of integer);
var i:integer;
begin
for i:=low(iArray) to high(iArray) do begin
write(iArray[i]);
end;
writeln('');
end;
procedure quickSort(var iArray : array of integer; links : integer; rechts:integer);
var
l,r,pivot, temp: integer;
begin
if (rechts > links) then begin
l := links;
r := rechts;
pivot := iArray[(rechts+links) div 2];
while (l<r) do begin
while (iArray[l] < pivot) do l:=l+1;
while (iArray[r] > pivot) do r:=r-1;
if (l<=r) then begin
temp := iArray[l];
iArray[l] := iArray[r];
iArray[r] := temp;
end;
end;
if (links < r) then quickSort(iArray, links, r);
if (l < rechts) then quickSort(iArray, l, rechts);
end;
end;
begin
fillArray(iArray);
quickSort(iArray,low(iArray),high(iArray));
writeArray(iArray);
end.
答案 0 :(得分:4)
交换的代码块,交换完成后也需要递增l
并递减r
:
if (l <= r) then
begin
temp := iArray[l];
iArray[l] := iArray[r];
iArray[r] := temp;
inc(l); // <-- this was missing
dec(r); // <-- as was this
end;
完整的程序,以及其他一些小的整理:
program quicksort24340509;
var
iArray: array [0 .. 8] of integer;
Procedure fillArray(var iArray: array of integer);
begin;
iArray[0] := 3;
iArray[1] := 1;
iArray[2] := 8;
iArray[3] := 4;
iArray[4] := 9;
iArray[5] := 0;
iArray[6] := 8;
iArray[7] := 2;
iArray[8] := 5;
end;
Procedure writeArray(const iArray: array of integer);
var
i: integer;
begin
for i := low(iArray) to high(iArray) do
begin
write(iArray[i], ' ');
end;
writeln;
end;
Procedure quickSort(var iArray: array of integer; links, rechts: integer);
var
l, r, pivot, temp: integer;
begin
if (rechts > links) then
begin
l := links;
r := rechts;
pivot := iArray[(rechts + links) div 2];
while l < r do
begin
while iArray[l] < pivot do inc(l);
while iArray[r] > pivot do dec(r);
if l <= r then
begin
temp := iArray[l];
iArray[l] := iArray[r];
iArray[r] := temp;
inc(l);
dec(r);
end;
end;
if links < r then
quickSort(iArray, links, r);
if l < rechts then
quickSort(iArray, l, rechts);
end;
end;
begin
fillArray(iArray);
quickSort(iArray, low(iArray), high(iArray));
writeArray(iArray);
readln;
end.
<强>输出强>
0 1 2 3 4 5 8 8 9
您的版本失败而没有丢失的行的原因是对quickSort
的递归调用在错误的范围内运行。
例如,根据您输入的
3 1 8 4 9 0 8 2 5
分区步骤在9
上转动并导致
3 1 8 4 5 0 8 2 9
现在,递归步骤应该是对枢轴左侧的所有值进行排序,并将所有值排序到右侧。我们将枢轴单独留下,因为分区确保它处于最终位置。
枢轴右侧没有值,所以我们应该对0到7的范围进行递归调用。但是如果你检查代码会发生什么,你会发现它没有。相反,它会对0到8的范围进行递归调用。这本身就是一个良性的,但是一旦范围变小,在停止条件下,就会有所不同。尝试让您的程序对这些值进行排序:
1 2
代码在1
上转动。在分区结束时,我们有:
links = 0
rechts = 1
l = 0
r = 0
因此,我们递归调用quickSort
作为范围传递l
和rechts
。但这与我们最初制作的电话完全相同。因此,这会导致堆栈溢出。
所以重点是我们必须确保当我们在一个数据透视表上进行分区时,我们会将该数据透视表从未来所有递归调用quickSort
中排除。如果我们不这样做,我们不会细分问题,并且递归不会终止。