簡體   English   中英

僅在大型數組上出現合並排序分段錯誤

[英]Merge Sort Segmentation Fault Only On Large Arrays

我正在實施幾種不同的排序方法,由於某種原因,我的合並排序算法不適用於大型數據集。 排序將適用於 115,000 個單詞,但在達到 135,000 個單詞時停止工作。 一旦我達到這個高度,我最終會遇到分段錯誤。 我不明白段錯誤來自哪里。 排序適用於包含 5K 到 125K 字符串的文本文件。

readFile數組使用文本文件中的字數進行初始化。 調試時,傳遞給mergeSort()函數的最后一個數字似乎如下:

#0  0x0000000000402a87 in merge (inputString=0x7fffffbde790, from=0, mid=67499, to=134999) at mergeSort.cpp:102
    n1 = 67500
    n2 = 67500
    i = 0
    j = 0
    k = 32767
    L = <error reading variable L (value requires 2160000 bytes, which is more than max-value-size)>
    R = <error reading variable R (value requires 2160000 bytes, which is more than max-value-size)>
#1  0x0000000000402921 in mergeSort (inputString=0x7fffffbde790, from=0, to=134999) at mergeSort.cpp:88
    mid = 67499
void mergeSort(string readFile[], int from, int to) {
    if (from < to) {
        int mid = from + (to - from) / 2;
        mergeSort(readFile, from, mid);
        mergeSort(readFile, mid + 1, to);
        merge(readFile, from, mid, to);
    }
}
void merge(string readFile[], int from, int mid, int to) {
    int n1 = mid - from + 1;
    int n2 = to - mid;

    string L[n1];
    string R[n2];

    for (int i = 0; i < n1; i++) {
        L[i] = readFile[from + i];
    }
    for (int i = 0; i < n2; i++) {
        R[i] = readFile[mid + i + 1];
    }

    int i = 0;
    int j = 0;
    int k = from;

    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            readFile[k] = L[i];
            i++;
        } else {
            readFile[k] = R[j];
            j++;
        }
        k++;
    }
    while (i < n1) {
        readFile[k] = L[i];
        i++;
        k++;
    }
    while (j < n2) {
        readFile[k] = R[j];
        j++;
        k++;
    }
}

您將臨時數組分配為merge函數中的自動變量。 當這些數組的大小變得太大時,您將缺乏分配它們的堆棧空間並出現未定義的行為(例如堆棧溢出)。

要處理任意大的數組,您應該使用mallocnew分配臨時數組並相應地釋放它們。 要限制分配的數量,您可以在包裝器中分配一個臨時數組,並在mergeSort函數中遞歸地傳遞它。

這是在merge函數中分配臨時數組的簡單修復:

void merge(string readFile[], int from, int mid, int to) {
    int n1 = mid - from + 1;
    int n2 = to - mid;

    string *L = new string[n1];
    string *R = new string[n2];

    for (int i = 0; i < n1; i++) {
        L[i] = readFile[from + i];
    }
    for (int i = 0; i < n2; i++) {
        R[i] = readFile[mid + i + 1];
    }

    int i = 0;
    int j = 0;
    int k = from;

    while (i < n1 && j < n2) {
        if (L[i] <= R[j]) {
            readFile[k] = L[i];
            i++;
        } else {
            readFile[k] = R[j];
            j++;
        }
        k++;
    }
    while (i < n1) {
        readFile[k] = L[i];
        i++;
        k++;
    }
    while (j < n2) {
        readFile[k] = R[j];
        j++;
        k++;
    }
    delete[] L;
    delete[] R;
}

這是一個更復雜的版本,可能更有效,分配一個臨時數組:

void merge(string readFile[], size_t from, size_t mid, size_t to, string aux[]) {
    size_t i, j, k;

    for (i = from; i < to; i++) {
        aux[i] = readFile[i];
    }

    i = from;
    j = mid;
    k = from;

    while (i < mid && j < to) {
        if (aux[i] <= aux[j]) {
            readFile[k++] = aux[i++];
        } else {
            readFile[k++] = aux[j++];
        }
    }
    while (i < mid) {
        readFile[k++] = aux[i++];
    }
    while (j < to) {
        readFile[k++] = aux[j++];
    }
}

void mergeSort(string readFile[], size_t from, size_t to, string aux[]) {
    if (to - from > 1) {
        size_t mid = from + (to - from) / 2;
        mergeSort(readFile, from, mid, aux);
        mergeSort(readFile, mid, to, aux);
        merge(readFile, from, mid, to, aux);
    }
}

void mergeSort(string readFile[], size_t n) {
    string *aux = new string[n];
    mergeSort(readFile, 0, n, aux);
    delete[] aux;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM