【问题标题】:Implement quicksort algorithm in two ways but only one accepted?以两种方式实现快速排序算法但只接受一种?
【发布时间】:2015-11-06 14:43:06
【问题描述】:

我已经通过两种方式实现了快速排序算法。

quick_sort功能同理:

void quick_sort(int *a, int left, int right) {
    if (left < right) {
        int mid = partition(a, left, right);
        quick_sort(a, left, mid - 1);
        quick_sort(a, mid + 1, right);
}

partition 功能在两种实现方式中有所不同:

基于Robert Sedgewick的“算法”一书的第一种方式:

int random = rand() % (right - left + 1) + left;
exchange(&a[left], &a[random]);

int i = left;
int j = right + 1;
int pivot = a[left];

while (1) {
    while (a[++i] < pivot)
        if (i == right) break;
    while (a[--j] > pivot)
        if (j == left) break;

    if (i >= j) break;

    exchange(&a[i], &a[j]);
}

exchange(&a[left], &a[j]);

return j;

第二种方式基于《算法简介》一书,这种方式比第一种方式更容易理解:

int random = rand() % (right - left + 1) + left;
exchange(&a[right], &a[random]);

int pivot = a[right];
int j = left - 1;

int i;
for (i = left; i < right; i++) {
    if (a[i] <= pivot) {
        j++;
        exchange(&a[j], &a[i]);
    }
}

exchange(&a[j + 1], &a[right]);

return j + 1;

我已经在 Online Judge 网站上提交了两个实现:TSORT,但只有第一个实现被接受,第二个是 Time Limit Exceed。有细微的差别,但我找不到导致性能差距的那个,有人可以找到然后解释一下吗?

【问题讨论】:

  • 您是否尝试将一些 printf's/cout's 放入非工作分区函数中以试图找出它失败的原因?
  • 首先尝试使用确定性值而不是rand。
  • @LouisRicci 我不认为 OP 说它失败了。只是网上评委的表现比另一个好。
  • 很明显,第一个实现效率更高,因为它比第二个实现更少的交换。
  • @VioletaMarin 是的,但是交换的数量在这里并没有显着的性能,因为两个分区的复杂度为 O(N)。原来问题是当数组填充相等的元素时,分区位置总是在数组的末尾,这导致二次时间

标签: c algorithm sorting quicksort


【解决方案1】:

您的第一个是 Hoare 分区方案,而第二个是 Lomuto 分区方案。根据多个消息来源,Lomuto 的变体不应该在实践中使用,它唯一的优点是教学,因为它更容易理解。

一些这样的来源:

  1. https://en.wikipedia.org/wiki/Quicksort

    Hoare 方案比 Lomuto 的分区方案更有效,因为它平均交换次数减少了三倍,并且即使所有值都相等,也可以创建高效的分区。

  2. https://cs.stackexchange.com/questions/11458/quicksort-partitioning-hoare-vs-lomuto

    Lomuto 的方法简单易实现,但不应该用于实现库排序方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2020-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多