【问题标题】:Hoare partitioning code used in Quicksort (ref Cormen book) runs into infinite loopQuicksort(参考 Cormen 书)中使用的 Hoare 分区代码运行到无限循环
【发布时间】:2017-09-23 07:47:42
【问题描述】:

我使用 Cormen Algorithms 书中的 Hoare 分区对 Quicksort 进行编码。我无法在我的代码中发现任何错误,它看起来就像书中的伪代码。

swapping i, j : 0, 8
-2 2 -5 -3 6 0 1 0 -1 4

swapping i, j : 1, 3
-2 -3 -5 2 6 0 1 0 -1 4
p is: 2

swapping i, j : 0, 1
-3 -2 -5 2 6 0 1 0 -1 4
p is: 0

完成上述交换后,此代码最终会在子数组{-3, -2} 上进行分区。对于这个subarray,主元是-3partition() returns 0index (j)。由于该子数组已经在0th index 位置使用枢轴-3 进行了排序,因此每次快速排序时都不会进行任何更改。所以 qsort 永远循环。

谁能告诉我这与书中的 Hoare 分区有何不同,如果相同,为什么这不起作用?

void swap(int *a, int i, int j) {
        cout << "swapping i, j : " << i << ", " << j << endl;
        int tmp = a[i];
        a[i] = a[j];
        a[j] = tmp; }

int partition(int *a, int len) {
        int pivot = a[0];

        int i = -1, j = len;
        while (true) {
               while ( ++i && a[i] < pivot && i< j) {}
               while (--j && a[j] > pivot && i <j) {}
               if (i < j )
                  swap(a, i, j);
               else 
                  return j ;
        } }

void qsort(int a[], int len) {
        int p = partition(a, len);
        cout << "p is: " << p << endl;
        qsort(a, p);
        qsort(a+p, len - p ); }

int main(int argc, char *argv[]) {
        int a[10] = {-1, 2, -5, -3, 6, 0, 1, 0, -2, 4};
        qsort(a, 10); }

【问题讨论】:

  • swapping i, j : 0, 1 何时发生?你的意思是swapping i, j : 0, 2
  • 交换 i, j : 0, 1 表示交换输入的数组 'a' 的索引 0 和索引 1 处的值正在交换。
  • 我明白了,但我认为索引 02 在第二次调用 qsort(a, 3) 期间被交换了
  • 向 OP 添加了原始数组在每次交换后的外观。第三次交换后,p为0,子数组为{-3, -2}
  • 第二次交换后,p = 2。然后在partition(a, 3) 中,i 变为0(正如你所说的那样),但j 变为2(而不是1),因为-5 &lt; -2-2pivot

标签: c++ algorithm quicksort partitioning hoare-logic


【解决方案1】:

在答案中扩展我的评论,partition() 返回 基于 0 的索引,但您需要将数组长度(长度为 基于 1)传递给 @ 987654322@,所以一定是:

void qsort(int a[], int len)
{
    int p = partition(a, len);
    cout << "p is: " << p << endl;
    qsort(a, p + 1); // note p+1 instead of p
    qsort(a + p + 1, len - (p + 1)); // note p+1 instead of p
}

试运行将如下所示:

swapping i, j : 0, 8
-2 2 -5 -3 6 0 1 0 -1 4

swapping i, j : 1, 3
-2 -3 -5 2 6 0 1 0 -1 4
p is: 2

现在您必须调用qsort(a, 3),因为您想对子数组-2 -3 -5 进行排序。此外,qsort(a+3, 7) 用于子数组2 6 0 1 0 -1 4

【讨论】:

  • 这似乎是正确的,需要进行 qsort(a, p+1) 调用。所以我知道在将子数组索引 0 到 p 分区后是 = 枢轴。分区可以返回 i ==j 吗?我想有趣的是,Cormen 书中提到,如果我们选择 a[len -1] 作为枢轴,那么这段代码将进入一个无限循环的数组,其中 a[len -1] 是最大元素。当 a[0] 是最小元素并且 a[0] 是枢轴(上面的代码就是这样做的)时,必须有一个对应的无限循环情况。对于这种情况,分区应该返回什么?
  • 你上面说的用例恐怕我没看懂。
猜你喜欢
  • 1970-01-01
  • 2016-02-12
  • 2018-10-01
  • 1970-01-01
  • 2014-12-23
  • 2014-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多