繁体   English   中英

快速排序算法中的分段错误(核心转储)

[英]Segmentation fault (core dumped) in quick sort algorithm

下面是我的 Quick sort i C 代码。我收到了 Segmentation fault Core Dumped。 我努力解决这个问题,但一无所获。

#include<stdio.h>

int divide(int a[], int p, int q) {
    int mid, i, lastsmall, temp;

    mid = (p + q)/2;
    temp = a[mid];
    a[mid] = a[p];
    a[p] = temp;
    int pivot = a[p];
    lastsmall = p;

    for (i = p + 1; i <= q; i++) {
        if (a[p] > pivot)
            continue;
        else {
             lastsmall++;
             temp = a[i];
             a[i] = lastsmall;
             lastsmall = a[i];
        }
    }
    return lastsmall;
}

void quick(int a[], int p, int q) {
    int pivot;
    if (p < q) {
        pivot = divide(a, p, q);
        quick(a, p, pivot);
        quick(a, pivot + 1, q);
    }
}

int main() {
    int ar[10], i;

    printf("Enter the list\n");
    for (i = 0; i < 10;i++)
        scanf("%d", &ar[i]);
    quick(ar, 0, 9);
    for (i = 0; i < 10; i++)
        printf("%d ", ar[i]);
    return 0;
}

编辑添加一些解释

段错误很容易在第 26 行中查明,逐一。 我无法理解你的divide函数,所以我只是在Rosetta的伪代码之后实现了对枢轴的搜索。 发现它简单易懂。

#include<stdio.h>
int divide(int a[], int low, int high)
{
  int pivot, tmp;

  // Yes, you can choose other start values.
  pivot = (low + high)/2;

  while (low <= high) {
    while (a[low] < a[pivot]) {
      low++;
    }
    while (a[high] > a[pivot]) {
      high--;
    }
    if (low <= high) {
      tmp = a[low];
      a[low] = a[high];
      a[high] = tmp;
      low++;
      high--;
    }
  }
  return pivot;
}

void quick(int a[], int p, int q)
{
  int pivot;
  if (p < q) {
    pivot = divide(a, p, q);
    // Here was your segfault
    quick(a, p, pivot - 1);
    quick(a, pivot + 1, q);
  }
}

int main()
{
  int ar[10], i;
  printf("Enter the list\n");
  for (i = 0; i < 10; i++) {
    scanf("%d", &ar[i]);
  }
  quick(ar, 0, 9);
  for (i = 0; i < 10; i++) {
    printf("%d ", ar[i]);
  }
  return 0;
}

一个真正的实现将涉及大量的指针处理、一个比较元素的函数、作为函数指针传递,以及大量的优化。 例如参见GLibC 实现

上面承诺的编辑

枢轴本身可以是任何东西,只要它在输入中的某个地方,它甚至可以是恒定的,就像我以前那样。 许多论文都写了关于枢轴的选择,它们唯一的共同点是结论:这取决于预期的输入。

我在外部while循环中放置了一个计数器(可能更好地计算比较次数)并生成了 100 到 10,000 之间的 100 个随机整数一百次。 “回合”的平均次数是为了返回

  • low = 168.55
  • --low = 185.67
  • high = inf(显然)
  • ++high = 174.87
  • pivot = 216.04(即:始终是每第二次调用增加一的起始索引)

如果我将枢轴更改为几何平均值的底面,我会得到

  • low = 153.22
  • --low = 152.65
  • high = inf
  • ++high = 151.88
  • pivot = 134.85

计算实际的比较次数,并使用 100,000 个 10 到 1,000,000 之间随机整数元素的数组(枢轴仍然是几何平均值),一百次运行的平均比较

  • low = 12762491.95
  • --low = 12756154.17
  • high = inf
  • ++high = 12702092.52
  • pivot = 13121675.81

与设置为几何平均值的枢轴相同

  • low = 12749755.60
  • --low = 12801865.60
  • high = inf
  • ++high = 12705592.10
  • pivot = 13113604.20

有些人可能会说调用quick() (调用divide()比使用常数因子的次数多一点)是一个更好的衡量标准,他们也是对的。 这次只有10回合。

相同的

  • low = 1281068.00
  • --low = 1225781.20
  • high = inf
  • ++high = 1221477.00
  • pivot = 1048575.00

相同,输入从低到高排序

  • low = 1280983.80
  • --low = 1225749.80
  • high = inf
  • ++high = 1221376.80
  • pivot = 1048575.00

相同,输入从高到低排序

  • low = 1281025.80
  • --low = 1225738.80
  • high = inf
  • ++high = 1221632.20
  • pivot = 1048575.00

使用 WhozCraig 提出的divide()进行测试:

未排序输入:1333671.00 排序输入(从低到高):1333513.60 排序输入(从高到低):1333594.80

运行时稳定,但速度也慢了一点(对于给定的输入!)。

结论:对于均匀分布的、随机的、密集的输入集,将枢轴设置为lowhigh之间的几何平均值似乎可以节省最多的比较。 返回开始枢轴或稍后计算的更优化值之一在比较中存在显着但非常小的因素,但在对quick()实际调用中却有相当大的差异。

对于其他输入集和其他枢轴值(您也可以使用多个枢轴)以及不同的体系结构,这有所不同。

优化quicksort确实有可能浪费很多时间,所以要谨慎!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM