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

时间:2011-03-31 13:52:53

标签: c++ quicksort

我尝试了很多不同的方法来写这个,但大多数时候我陷入无休止的循环中。 这个版本的代码根本不对它进行排序,我不知道问题是什么。

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);
}

4 个答案:

答案 0 :(得分:3)

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

让它工作,然后尝试一个长度为2的数组。

一旦它正常工作,当你给它一个长度为3的数组时,很有可能它会起作用。

修改:

赞赏包含可重复的例子。

此代码在递归之前失败。第一步是选择一个枢轴元素并移动一些元素,直到枢轴元素不小于其左边的任何元素,并且不超过它的右边的任何元素。您的代码会丢失它认为是pivot元素的元素;它交换了枢轴元素,但似乎认为相同的位置仍然是枢轴。尝试用铅笔和纸做这个算法,你会明白我的意思。

答案 1 :(得分:1)

这项检查对我来说很奇怪

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

不应该至少

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

P.S。我认为这不是唯一的问题,而是一开始......

答案 2 :(得分:0)

在没有看到swap的情况下,我的第一个预感就是你的swap按值获取其参数。即它交换了两份副本,而不是参数本身。

答案 3 :(得分:0)

亲爱的,亲爱的。对不起乔,但事情对你的代码来说并不是那么好看。它需要许多计算机血管手术,即便如此,我也不确定它会成功。让我们写一个处方,我会让你用手术刀:

  1. 如果左> gt; =右,则返回。不要乱用1元素阵列。
  2. 用你最左边的元素交换你的枢轴元素(最右边也很好,但我必须选择一个)。最后,您将把它交换到分区之间的正确位置。您可以通过将最左边的元素(包含您的轴)与最左侧分区的最右边元素交换,如下一步所示。
  3. 现在我们需要分区。让我们做一个我们能想到的最简单的分区。当你刚开始使用快速排序时,我建议使用以下内容:[ < pivot | >= pivot | unsorted ]。这是我们每一步都想要的不变量。一开始,一切都将在未分类的分区中。最后,未分类的分区中没有任何内容。我们怎么做到这一点?

    1. 从数组中的left+1right循环。
    2. 如果元素小于pivot,我们使用正确的swap将其添加到[ < pivot ]分区(我留给你 - 你要跟踪左边两个分区之间的边界) 。如果不是,我们继续前进。
  4. 将枢轴放置到位后,阵列应该看起来像[ < pivot | pivot | >= pivot ]。快速分离最左边和最右边的分区,事情应该正在查找此代码。
  5. 尝试使用[ < pivot | unsorted | >= pivot ]分区之类的更好的东西(如果正确完成,可以更快地完成)。我认为你当前的实现是尝试进行这种分区,但除非我或j指向一个等于pivot的元素,否则不会进行任何交换。这种分区比较棘手,我建议在进入任何比赛之前给我们的代码一个脉冲。

    希望能够让你的代码成型,但这只是一个非常基本的快速排序。您应该研究Bentley-McIlroy分区和枢轴选择方法,以使其更先进。