快速排序的 C++ 实现中的运行时错误

Posted

技术标签:

【中文标题】快速排序的 C++ 实现中的运行时错误【英文标题】:Runtime errors in C++ implementation of quicksort 【发布时间】:2011-08-23 23:32:34 【问题描述】:

我正在编写一个快速排序的实现来提高我的 C++ 技能,但是我遇到了一个让我很困惑的错误。该算法似乎在大约 25% 的时间内运行良好,但在另外 75% 的时间里我一直遇到错误,程序报告分段错误或堆栈溢出。如果有人可以提供帮助,将不胜感激。提前致谢。

#include <iostream>
#include <string.h>
#include <ctime>
using namespace std;

#define size 20

void printSet(int* set);
int* quicksort(int* set, int l);
int* concat(int* less, int countL, int* greater, int countG);

int main()

    srand(time(NULL));
    int* set;
    set = new int[size];
    for(int i=0; i<size; i++)
        set[i]=rand()%200;
    printSet(set);
    set = quicksort(set, size);
    printSet(set);
    delete set;
    int i;
    cin>> i;
    return 0;


int* quicksort(int* set, int l)

    //cout<<"QS\n";
    if (l <= 1)
        return set;
    int*      less = new int[l];
    int*   greater = new int[l];
    int pivotIndex = rand() % l, 
          pivotVal = set[pivotIndex],
            countL = 0,
            countG = 0;

    for(int i=0; i<l; i++)
    
        if (set[i] < pivotVal)
            less[countL++]=set[i];
        else
            greater[countG++]=set[i];
    
    set = concat(quicksort(less, countL), countL, quicksort(greater, countG), countG);

    return set;


int* concat(int* less, int countL, int* greater, int countG)

    //cout<<"concat\n";
    int* set;
    set = new int[size];

    int i;

    for(i=0; i<countL; i++)
        set[i]=less[i];
    for(int j=0; j<countG; j++)
        set[i+j]=greater[j];

    return set;


void printSet(int* set)

    cout<<"******************\nPrinting Set\n";
    for(int i=0; i< size; i++)
    
        cout<<i<<": "<<set[i]<<endl;
    

【问题讨论】:

错误到底是什么意思? 错误是什么?尝试使用调试器单步执行。 您的quicksort 函数和concat 函数也存在内存泄漏。 你的越来越小的数组也永远不会被删除。在大型数据集上,这可能会泄漏大量内存。编辑:打败它 我刚刚编辑了问题以包括报告了哪些错误(我在我的机器上运行了几次)。希望这可以澄清事情! 【参考方案1】:

我相信你的错误之一是在 main 的这一行:

delete set;

这里的问题是set 是一个用new[] 分配的数组。要释放它的内存,您需要通过对delete[] 的匹配调用来删除它。这可以通过将行重写为来解决

delete[] set;

此外,您的代码在某些情况下有机会无限递归。特别是,假设您尝试对包含两个 0 副本的列表进行排序。在这种情况下,请考虑以下代码将做什么:

for(int i=0; i<l; i++)

    if (set[i] < pivotVal)
        less[countL++]=set[i];
    else
        greater[countG++]=set[i];

set = concat(quicksort(less, countL), countL, quicksort(greater, countG), countG);

由于您的枢轴元素为 0(这是唯一的选择!),您将遍历数组并将数组中的两个 0 放入 greater。因此,当您在 greater 上递归调用 quicksort 时,您最终将递归地尝试对开始时完全相同的范围进行排序,从而导致无限递归。

要解决此问题,请尝试更新您的代码,以便将您分成三组 - 小于枢轴的元素、大于枢轴的元素和等于枢轴的元素。您仍然会在更小和更大的范围上递归,但您不会在相等的值上递归调用自己。这将确保始终在比您开始时更小的范围内调用递归。

最后,正如其他人所指出的,您当前的实现会泄漏大量内存,因为您从未释放任何您构建的临时数组。为避免这种情况,请考虑将您对原始数组的使用替换为 std::vector,它自己进行内存管理并且不会泄漏任何内存。此外,它还使得将数组拆分为区域变得更加容易,因为您只需使用 push_back 来追加元素。

希望这会有所帮助!

【讨论】:

我编译了代码,但由于您所描述的,他正在发生堆栈溢出。 +1 @Seth Carnegie- 是的,我用 gdb 和 valgrind 运行它来发现这些错误。我希望我抓住了一切! 所以这就是为什么 OP 认为没有必要发布错误消息。 感谢大家的帮助!我真的很感激。 @Luke- 很高兴能帮上忙!如果这回答了您的问题,请务必将答案标记为已接受以标记问题已解决。

以上是关于快速排序的 C++ 实现中的运行时错误的主要内容,如果未能解决你的问题,请参考以下文章

C++ 合并排序分段错误?

C++ 运行时错误中的字符串

在 C++ 中为结构读取二进制文件的运行时错误

从逆序 C++ 访问向量时出现运行时错误 [关闭]

合并排序代码中的分段错误

C++ 并行就地基数排序