【问题标题】:Quick Sort Implementation (Test for failure) in C++C++ 中的快速排序实现(失败测试)
【发布时间】:2017-02-05 09:35:26
【问题描述】:

我已经分配了在 C++ 中实现 Quicksort 的任务,并且我已经成功地编写了似乎可以工作的代码。当我测试我的算法是否失败时,当我让它在一个包含一百万个元素的二进制文件中对数字进行排序时,它崩溃了。请注意,我有两个文件,每个文件都有一百万个元素。其中一个是未排序的,另一个是“几乎排序的”,我的算法似乎只在对“几乎排序”的文件进行排序时失败。这是我的代码的样子:

    int partition(int arr[], int low, int high) 
{
    int pivotI = low; //pivot index
    int pivot = arr[pivotI];
    int temp = arr[low];
    arr[low] = pivot;
    arr[pivotI] = temp;
    int partitionI = low;
    low++;
    while (low <= high)
    {
        if (arr[low] >= pivot)
        {
            if (arr[high] <= pivot)
            {
                temp = arr[high];
                arr[high] = arr[low];
                arr[low] = temp;
                low++;
            }
            high--;
        }
        else if (arr[high] <= pivot)
        {
            low++;
        }
        else
        {
            low++;
            high--;
        }
    }
    if (low == high)
    {
        if (arr[low - 1] < pivot)
        {
            temp = arr[low];
        }
        else
        {
            temp = arr[low - 1];
        }
    }
    else
    {
        temp = arr[high];
    }
    arr[high] = arr[partitionI];
    arr[partitionI] = temp;
    return high;
}

void quickSort(int arr[], int left, int right)
{
    if (left < right)
    {
        int p = partition(arr, left, right);
        quickSort(arr, left, p);
        quickSort(arr, p + 1, right);
    }
}

*当我运行“几乎排序”的二进制文件时,我得到一个堆栈溢出错误。知道为什么会这样吗? 谢谢

【问题讨论】:

  • 调试器是解决此类问题的正确工具。 询问 Stack Overflow 之前,您应该逐行逐行检查您的代码。如需更多帮助,请阅读How to debug small programs (by Eric Lippert)。至少,您应该 [编辑] 您的问题,以包含一个重现您的问题的 Minimal, Complete, and Verifiable 示例,以及您在调试器中所做的观察。
  • 很可能递归太深了。

标签: c++ algorithm sorting stack-overflow quicksort


【解决方案1】:

如果在快速排序中使用第一个值作为枢轴值,则已经排序的列表是最坏的情况,因为枢轴将始终是分区中的最低值。这可以大大增加递归深度。每个递归调用都需要堆栈帧上的空间(由参数、局部变量和返回地址组成)。对于一百万个数字的几乎排序列表,您可能需要一次接近一百万个活动堆栈帧。这很容易耗尽可用的堆栈空间并产生错误。

你可以尝试不同的枢轴算法来解决这个问题,比如三的中位数。

【讨论】:

  • 另一种解决方案可能是不使用递归,而是使用std::stack
  • 您可以将中间元素用作枢轴,例如pivotI = (低+高)/2;
【解决方案2】:

避免堆栈溢出的一种方法是结合使用循环和递归。在每个 partition() 之后的 quicksort() 中,检查 if (p - left)

使用中位数的中位数可以将最坏情况的时间复杂度降低到 O(n log(n))

http://en.wikipedia.org/wiki/Median_of_medians

但常数因子因子更大,会减慢平均和最佳情况的快速排序。

【讨论】:

    猜你喜欢
    • 2014-04-17
    • 2011-03-29
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    • 2019-11-20
    • 2016-12-07
    相关资源
    最近更新 更多