繁体   English   中英

需要帮助(尝试)C ++中的快速排序算法

[英]Need help with (an attempt of) a quicksort algorithm in c++

我尝试了多种不同的方式来编写此代码,但大多数情况下,我陷入了无休止的循环。 此版本的代码根本不对它进行排序,我也不知道问题出在哪里。

void quickSort(int unsorted[], int left, int right) {
      int i = left, j = right;
      int pivot = (left + right) / 2;

      while (i == pivot || j == pivot) {
          if (unsorted[i] >= unsorted[pivot] && unsorted[pivot] >= unsorted[j])
              swap(unsorted[i], unsorted[j]);

          if (i < pivot)
              i++;
          if (j > pivot)
              j--;
      };

      if (left < j && unsorted[left] != unsorted[j])
          right = pivot, quickSort(unsorted, left, right);
      if (i < right && unsorted[right] != unsorted[i])
          left = pivot +1, quickSort(unsorted, left, right);

}

unsorted是一个数组,其中填充了0到200之间的100个随机值。

抱歉更新缓慢。 关于代码,我重写了大部分代码。 这是现在的样子:

void quickSort(int unsorted[], int left, int right) 
{
    int i = left, 
        j = right,
        count = 0;
    int pivot = (left + right) / 2;

    do
    {
          while (unsorted[i] < unsorted[pivot])
              i++;
          while (unsorted[j] > unsorted[pivot])
              j--;

          if (unsorted[i] >= unsorted[j] && i <= j)
          {
              swap(unsorted[i], unsorted[j]);
              i++;
              j--;
              count++;
          }
          if (i == pivot && unsorted[pivot] < unsorted[j] && count == 0)
          {
              swap(unsorted[i], unsorted[j]);
              i++;
              j--;
              count++;
          }
          if (j == pivot && unsorted[pivot] < unsorted[i] && count == 0)
          {
              swap(unsorted[i], unsorted[j]);
              i++;
              j--;
              count++;
          }

          if (i == j && unsorted[i] > unsorted[pivot] && count == 0)
          {
              swap(unsorted[i], unsorted[pivot]);
              i++;
              j--;
              count++;
          }
          if (i == j && unsorted[i] < unsorted[pivot] && count == 0)
          {
              swap(unsorted[i], unsorted[pivot]);
              i++;
              j--;
          }

          count = 0;

    } while (i < j);

    if (left < j)
        quickSort(unsorted, left, j);
    if (i < right)
        quickSort(unsorted, i, right);

}

我一直在尝试使用10个随机值一次又一次地尝试此代码,并且大多数时候都可以使用。 在某些情况下,它不起作用,我正在尝试找出时间。

一个不起作用的示例是以下值:160、151、159、112、7、121、105、48、186。

解决了。 删除了很多代码,使其变得更加简单,但至少可以正常工作。 甚至不知道您是否可以将其称为快速搜索,但这是最终版本:

void quickSort(int unsorted[], int left, int right) 
{
    int i = left, 
        j = right;
    int pivot = right;

    do
    {
        while (unsorted[i] < unsorted[pivot])
            i++;
        while (unsorted[j] > unsorted[pivot])
            j--;

        if (unsorted[i] >= unsorted[j] && i <= j)
        {
            swap(unsorted[i], unsorted[j]);
            i++;
            j--;
        }
    } while (i < j);

    if (left < j)
        quickSort(unsorted, left, j);
    if (i < right)
        quickSort(unsorted, i, right);
}

您没有在长度为1的数组上测试功能。

使它工作,然后尝试使用长度为2的数组。

一旦工作,给它一个长度为3的数组很有可能会工作。

编辑:

包含可复制示例的荣誉。

此代码在递归之前失败。 第一步是选择一个枢轴元素,然后移动一些元素,直到该枢轴元素不小于其左侧且不大于其右侧。 您的代码无法跟踪将哪个元素视为数据透视元素。 它替换掉了透视元素 ,但似乎认为同一位置仍然是透视。 到目前为止,尝试用铅笔和纸来工作该算法,您将明白我的意思。

这张支票对我来说似乎很奇怪

while (i == pivot || j == pivot)

至少不应该

while (i != pivot && j != pivot)

PS:我认为这不是唯一的问题,但是首先...

没有看到swap ,我的第一个直觉是您的swap按值接受参数。 即它交换两个副本,而不是参数本身。

噢亲爱的。 对不起,乔,但是对于您的代码而言,情况看起来并不好。 它需要进行许多计算机血管手术,即使那样,我也不确定它能否成功。 让我们写一个处方,我让你动用手术刀:

  1. 如果左> =右,则返回。 不要搞混1元素数组。
  2. 将枢轴元素与最左边的元素交换(最右边的也可以,但是我必须选择一个)。 最后,您将其交换到分区之间的正确位置。 您可以通过将最左边的元素(包含枢轴)与最左边的分区的最右边的元素交换来完成此操作,如下一步所示。
  3. 现在我们需要分区。 让我们做一个我们可以想到的最简单的分区。 当您刚开始使用quicksort时,我建议您使用以下方法: [ < pivot | >= pivot | unsorted ] [ < pivot | >= pivot | unsorted ] [ < pivot | >= pivot | unsorted ] 这就是我们在每个步骤中想要的不变性。 一开始,所有内容都将位于未排序的分区中。 最后,未排序的分区中将没有任何内容。 我们应该怎么做?

    1. 在数组中left+1right循环。
    2. 如果该元素小于轴,则使用正确的交换将其添加到[ < pivot ]分区中(我留给您-您需要跟踪左侧两个分区之间的边界)。 如果不是,我们继续。
  4. 将枢轴放置到位后,您的数组应类似于[ < pivot | pivot | >= pivot ] [ < pivot | pivot | >= pivot ] [ < pivot | pivot | >= pivot ] 快速排序最左边和最右边的分区,实际上应该在查找此代码。

尝试像[ < pivot | unsorted | >= pivot ] [ < pivot | unsorted | >= pivot ] [ < pivot | unsorted | >= pivot ]分区(如果正确完成,它将更快)。 我认为您当前的实现正在尝试进行这种分区,但是除非i或j指向等于枢轴的元素,否则不会进行任何交换。 这种划分比较棘手,我建议我们在任何比赛之前都给您一个代码脉冲。

希望这会使您的代码成形,但这只是一个非常基本的快速排序。 您应该研究Bentley-McIlroy分区,并选择合适的选择方法以使其更高级。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM