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

时间:2016-09-14 01:41:40

标签: c segmentation-fault quicksort

下面是我的快速排序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;
}

1 个答案:

答案 0 :(得分:-1)

已编辑以添加一些解释

第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 implementation

上面承诺的 EDIT

只要它在输入的某个地方,它就可以通过任何东西,它甚至可以像以前一样保持不变。关于枢轴的选择已经写了很多论文,他们唯一共同点就是结论:它取决于预期的输入。

我在外部while循环中放置了一个计数器(概率更好,可以计算比较次数)并生成100个随机整数,介于10到10,000之间。平均数&#34;轮次&#34;是为了回归

  • low = 168.55
  • --low = 185.67
  • high = inf(显然)
  • ++high = 174.87
  • pivot = 216.04(即:始终为每秒呼叫增加1的起始索引)

如果我将枢轴更改为几何平均值的底线我

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

计算实际的比较次数以及10到1,000,000之间的100,000个随机整数元素的数组(数值仍是几何平均数),平均比较100次

  • 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()时相当大。

对于其他输入集和其他数据透视值(您也可以使用多个支点)以及不同的体系结构也不同。

确实可以浪费大量时间来优化快速排序,所以要小心!