具有Hoare分区方案的Quicksort算法返回原始未排序列表

时间:2019-02-26 08:59:45

标签: c++ algorithm sorting quicksort

我曾尝试用Hoare的分区方案实现Quicksort算法,但是当我在测试列表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; } } 上运行它并打印出来时,我得到的数字是原始顺序。有人可以帮我发现我在做什么错吗?下面是我的实现。

{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"; 上的Quicksort算法,请使用以下代码:

412
123
57
12
1
5

控制台输出为

if (left - right <= 1)

修改

修复了应为if (right - left <= 1)的错误Segmentation fault: 11之后,程序遇到错误{{1}}。这使我相信我正在尝试访问超出范围的内容。

2 个答案:

答案 0 :(得分:4)

算法的分区部分未正确实现。特别是,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);
   }
}

可测试的HERE

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

答案 1 :(得分:2)

我认为代码的问题(或至少一个问题)是以下几行:

.hasOwnProperty()

这始终考虑整个列表,而不仅考虑未排序的部分。您应该使用限制索引 { "name": "admin@test.org", "oldPassword": "1234", "newPassword": "12345" } sort(list, 0, endIndex - 1); sort(list, endIndex + 1, list.size() - 1);

left