簡體   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