使用霍尔分区方案的快速排序算法返回原始未排序列表



我试图使用Hoare的分区方案来实现QuickSort算法,但是当我在测试列表{412, 123, 57, 12, 1, 5}上运行它,然后将其打印出来时,我以原始顺序获得数字。有人可以帮我发现我做错了什么吗?以下是我的实施。

void Quicksort::sort(std::vector<int> &list)
{
   sort(list, 0, list.size() - 1);
}
void Quicksort::sort(std::vector<int> &list, int left, int right)
{
   if (left - right <= 1) return; // no need to partition a single element
   int pivot = left + (right - left) / 2; // <=> (left+right)/2, but avoids overflow
   int endIndex = partition(list, pivot, left, right); 
   sort(list, 0, endIndex - 1);
   sort(list, endIndex + 1, list.size() - 1);
}
int Quicksort::partition(std::vector<int> &list, int pivot, int left, int right)
{
   while (true)
   {
      while (list[left] < list[pivot])
         left++;
      while (list[right] > list[pivot])
         right--;
      if (left != right)
         std::swap(list[left], list[right]);
      else
         return left;
   }
}

要在列表上调用QuickSort算法{412, 123, 57, 12, 1, 5}我使用以下代码:

std::vector<int> numbers = {412, 123, 57, 12, 1, 5};
Quicksort::sort(numbers);
for (int i = 0; i < numbers.size(); i++)
   std::cout << numbers[i] << "n";

控制台输出为

412
123
57
12
1
5

编辑

修复了应该是if (right - left <= 1)的错误if (left - right <= 1)后,程序遇到错误Segmentation fault: 11。这使我相信我正在尝试访问距离的东西。

该算法的分区部分未以正确的方式实现。特别是,left可能比right大,而这

if (left != right)
     std::swap(list[left], list[right]);
//             ^^^^^^^^^^

可以从范围访问向量。

查看以下片段:

int partition(std::vector<int> &list, int left, int right)
{
   // I'm calculating the pivot here, instead of passing it to the function
   int pivot = list[left + (right - left) / 2];
   while (true)
   {
      while (list[left] < pivot)
         left++;
      while (list[right] > pivot)
         right--;
      // Stop when the pivot is reached 
      if (left >= right)
         return right;
      // Otherwise move the elements to the correct side 
      std::swap(list[left], list[right]);
   }
}
void sort(std::vector<int> &list, int left, int right)
{
    // Execute only if there are enough elements
   if (left < right) 
   {
       int pivot = partition(list, left, right);
       // As NiVer noticed, you have to limit the range to [left, right]
       sort(list, left, pivot - 1); 
       sort(list, pivot + 1, right);
   }
}

可在此处测试。

也考虑使用迭代器以更通用的方式实现这些功能。

我相信代码的问题(或至少一个问题)是行:

sort(list, 0, endIndex - 1);
sort(list, endIndex + 1, list.size() - 1);

这始终考虑整个列表,而不仅仅是剩下的未分类部分。您应该使用限制索引leftright

sort(list, left, endIndex - 1);
sort(list, endIndex + 1, right);

相关内容

  • 没有找到相关文章

最新更新