Delphi 自定义快速排序实现中的SIGSEV

Delphi 自定义快速排序实现中的SIGSEV,delphi,pascal,quicksort,Delphi,Pascal,Quicksort,我仔细考虑了这个问题的答案,想从头开始重新编码,用callbyreference变量实现您的提示。然后,我再也找不到我犯过的任何错误了。我将代码与您的程序逐一进行比较,但找不到问题所在。以下代码在编译/运行期间在地址11602处生成一个异常外部:SIGSEV program quicksort; var iArray : array[0..8] of integer; procedure fillArray(var iArray : array of integer); begin;

我仔细考虑了这个问题的答案,想从头开始重新编码,用callbyreference变量实现您的提示。然后,我再也找不到我犯过的任何错误了。我将代码与您的程序逐一进行比较,但找不到问题所在。以下代码在编译/运行期间在地址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.

交换的代码块也需要在交换完成后增加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;
分区步骤以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
因此,我们递归地将传递l和rechts的快速排序称为范围。但这和我们最初打的电话完全一样。因此,这会导致堆栈溢出


所以关键是,我们必须确保当我们在一个轴上进行分区时,我们将该轴从所有将来对快速排序的递归调用中排除。如果我们不这样做,我们就不会细分问题,递归也不会终止

交换的代码块也需要在交换完成后增加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;
分区步骤以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
因此,我们递归地将传递l和rechts的快速排序称为范围。但这和我们最初打的电话完全一样。因此,这会导致堆栈溢出


所以关键是,我们必须确保当我们在一个轴上进行分区时,我们将该轴从所有将来对快速排序的递归调用中排除。如果我们不这样做,我们就不会细分问题,递归也不会终止

多谢各位。不递增/递减有什么问题?值被交换,l仍然小于r,while循环应该继续,因为它是一个不同的算法。根本不起作用的人。您会注意到您的原始版本有所不同。是的,但为什么它不起作用?我的例子是输入3 1 8 4 9 0 8 2 5枢轴:第一轮后9,l为49,r为85:它们互换。那么数组是:3 1 8 4 5 0 8 2 9为什么我必须inc/和dec?如果我不这样做,下一个回合l将inc和r将由两个内部while循环dec。无论如何,您使用的源文本是什么?有无数种不同的方法来实现分区。很容易看出您的代码无法进行分区。为什么要将代码从以前的可用版本更改为不可用的版本?您的源文本是否告诉您这样做?我添加了一些分析,说明了堆栈溢出的原因谢谢。不递增/递减有什么问题?值被交换,l仍然小于r,while循环应该继续,因为它是一个不同的算法。根本不起作用的人。您会注意到您的原始版本有所不同。是的,但为什么它不起作用?我的例子是输入3 1 8 4 9 0 8 2 5枢轴:第一轮后9,l为49,r为85:它们互换。那么数组是:3 1 8 4 5 0 8 2 9为什么我必须inc/和dec?如果我不这样做,下一个回合l将inc和r将由两个内部while循环dec。无论如何,您使用的源文本是什么?有无数种不同的方法来实现分区。很容易看出您的代码无法进行分区。为什么要将代码从以前的可用版本更改为不可用的版本?你的源文本告诉你这样做了吗?我添加了一些分析来说明为什么会出现堆栈溢出这是堆栈溢出的边缘话题,它不是一个调试会话的站点
你的代码曾经有过一个过于本地化的原因,这很容易。为了增加它对网站未来访问者有用的机会,你应该编辑它,使其具有一个有意义的标题,让遇到与你相同问题的人可以搜索到,格式正确的代码和没有德语参数名。你能,请开始养成正确缩进的习惯?这是堆栈溢出的边缘话题,它不是一个调试代码会话的网站,一旦有一个过于本地化的密切原因,它会很容易。这会增加它对网站未来访问者有用的机会,你应该对它进行编辑,使它有一个有意义的标题,一些遇到与你相同问题的人可以搜索到的东西,格式正确的代码,并且没有德语参数名。请你开始养成正确缩进的习惯好吗?