【问题标题】:std::partition segfault issuestd::partition 段错误问题
【发布时间】:2019-03-19 08:00:59
【问题描述】:

只是为了好玩,我使用std::partition() 实现了快速排序,但遇到了段错误。我找到了一个示例实现here,它只是略有不同并且可以工作。虽然我可以看到其实施效率的优势,但我不明白为什么我的会出现段错误。唯一的区别是我没有做第二个std::Partition 以避免将与枢轴相同的值传递给以后的递归调用。谁能发现我的问题?

#include <algorithm>
#include <vector>
#include <iostream>

template <typename iter> void quick_sort(iter first, iter last)
{
    if ( std::distance( first, last ) <= 1 )
    {
        return;
    }

    auto pivot = *std::next( first, std::distance( first, last ) / 2 );

#if 0 //works
    iter midpoint1 = std::partition( first, last, [pivot](const auto& x)->bool{ return ( x < pivot ); } );
    iter midpoint2 = std::partition( midpoint1, last, [pivot](const auto& x)->bool{ return !( pivot < x ); } );
    quick_sort( first, midpoint1 );
    quick_sort( midpoint2, last );
#else //segfaults
    iter midpoint = std::partition( first, last, [pivot](const auto& x){ return ( x < pivot ); } );
    quick_sort( first, midpoint );
    quick_sort( midpoint, last );
#endif
}

int main()
{
    std::vector<int> to_sort = {2,1,7,4,6,9,2,1,5,8,9,4,7,4,3,7,4,8,3,8,9};

    quick_sort( std::begin( to_sort ), std::end( to_sort ) );

    for ( auto n : to_sort )
    {
        std::cout << n << ',';
    }

    std::cout << '\n' << std::flush;
}

【问题讨论】:

  • 您永远对一个元素范围进行排序(或者更确切地说,直到堆栈溢出)。范围永远不会减少。
  • 不会被if ( first == last ) return;抓到
  • 检查空范围。
  • 如果 first == last 变为 true,您正在处理一个 范围,而不是包含 1 个元素的范围
  • 就像在快速排序实现中通常的那样,它是 off-by-1 问题,很容易编写!在这种情况下,会被迭代器符号稍微掩盖。

标签: c++ sorting recursion quicksort partition


【解决方案1】:

考虑一个序列,其中您选择的枢轴是最小元素。

然后您的分区将导致一个空序列(您停止递归)和原始序列。

重复直到堆栈溢出,或者通过尾调用优化,系统磨损。

顺便说一句,在您说有效的代码中,您曾经使用过较大的&gt;,但您应该只使用较小的&lt;

【讨论】:

  • 旁注,已修复。我将不得不更多地考虑我的终止条件,或者更有可能的是,传递给递归调用的范围。
  • 另一个问题是我很愚蠢并且忘记了 std::partition 实际上并不能确保我选择的枢轴位于小于它的值和大于它的值之间。相反,它只是确保所有小于枢轴的数字都在左侧。因此,第二个 std::partition 是必要的,以确保枢轴位于您期望的位置。
猜你喜欢
  • 2023-03-04
  • 1970-01-01
  • 2019-12-19
  • 1970-01-01
  • 2010-12-03
  • 1970-01-01
  • 1970-01-01
  • 2020-02-07
  • 2012-02-10
相关资源
最近更新 更多