【发布时间】:2021-06-12 21:55:15
【问题描述】:
请考虑 Cormen、Leiserson、Rivest 和 Stein 的经典算法教科书 Introduction to Algorithms 中的快速排序“lomuto partition”方案。
PARTITION(A, p, r)
x = A[r]
i = p - 1
for j = p to r - 1
if A[j] <= x
i = i + 1
exchange A[i] with A[j]
exchange A[i + 1] with A[r]
return i + 1
在实现这个算法之后,我发现它不能正常工作,最多只能偏离 1 个元素。 然后我开始计算一个解决方案,最后想出了以下有效的 C 代码。我已经在代码中评论了算法的工作原理。
int quickSortPartition(int *array, int beginIndex, int endIndex) // end index = array length - 1.
{
int pivotIndex = beginIndex; // first element as pivot.
int pivotValue = array[pivotIndex]; // initial pivot value.
int i = beginIndex + 1; // start loop with i being 2nd index.
while(i < endIndex) // loop running until end of array.
{
if(array[i] > array[i + 1]) // comparing the 2 elements ahead of pivot.
{
swap(array, i, i + 1); // swapping the 2 elements if prev element > next element.
}
if(array[i] < pivotValue) // comparing element at pivot index with the next index element.
{
swap(array, pivotIndex, i); // swapping if next element is less than element at pivot index.
++pivotIndex; // incrementing pivot index by 1 ONLY when swap occurs.
}
++i; // drive loop.
}
if(array[pivotIndex] > array[pivotIndex + 1]) // at the very end, compare whether the element to the right of pivot is > element at pivot index.
{
swap(array, pivotIndex, pivotIndex + 1); // swapping if next element is less than element at pivot index.
++pivotIndex; // incrementing pivot index by 1 ONLY when swap occurs.
}
return pivotIndex; // returning new pivot index.
}
我的实现效率是否低于书中所谓的“lomuto 分区”?当然,它们都是 O(n),但是就数字原子操作而言,比如一次迭代中的赋值和比较呢?它对大规模案例的效率有显着影响吗? 为什么这本书的算法不起作用?它缺少什么? 我也很感激关于如何进一步简化我的代码的建议。
其他后续信息:
- 我已经用python实现了本书的代码。
def quicksort(A, p, r):
if p < r:
q = partition(A, p, r)
quicksort(A, p, q - 1)
quicksort(A, q + 1, r)
def partition(A, p, r):
x = A[r]
i = p - 1
for j in range(p, r - 1):
if A[j] <= x:
i = i + 1
A[i], A[j] = A[j], A[i]
A[i + 1], A[r] = A[r], A[i + 1]
return i + 1
array = [2, 55, 43, 12, 65, 72, 41, 18, 6]
print(array)
quicksort(array, 0, len(array) - 1)
print(array)
结果:
unsorted: [2, 55, 43, 12, 65, 72, 41, 18, 6]
sorted: [2, 6, 41, 43, 12, 55, 65, 72, 18]
如您所见,排序失败。 另外,如果我将 len(array) 用于第三个参数,则会出现溢出错误。
- 至于我的 C 代码使用我的算法并且可以工作,这是我的头文件,你可以测试一下。
#ifndef A1_H
#define A1_H
// am1n
#include<stdio.h>
#include<stdlib.h>
void printArray(int *array, int arrayLength)
{
int i = 0;
--arrayLength;
for(i = 0; i < arrayLength; ++i)
{
printf("%d, ", array[i]);
}
printf("%d.\n", array[i]);
}
void swap(int *array, int a, int b)
{
if(array[a] != array[b])
{
int tempValue = array[a];
array[a] = array[b];
array[b] = tempValue;
}
}
int fastSortPartition(int *array, int beginIndex, int endIndex) // end index = array length - 1.
{
int pivotIndex = beginIndex; // first element as pivot.
int pivotValue = array[pivotIndex]; // initial pivot value.
int i = beginIndex + 1; // start loop with i being 2nd index.
while(i < endIndex) // loop running until end of array.
{
if(array[i] > array[i + 1]) // comparing the 2 elements ahead of pivot.
{
swap(array, i, i + 1); // swapping the 2 elements if prev element > next element.
}
if(array[i] < pivotValue) // comparing element at pivot index with the next index element.
{
swap(array, pivotIndex, i); // swapping if next element is less than element at pivot index.
++pivotIndex; // incrementing pivot index by 1 ONLY when swap occurs.
}
++i; // drive loop.
}
if(array[pivotIndex] > array[pivotIndex + 1]) // at the very end, compare whether the element to the right of pivot is > element at pivot index.
{
swap(array, pivotIndex, pivotIndex + 1); // swapping if next element is less than element at pivot index.
++pivotIndex; // incrementing pivot index by 1 ONLY when swap occurs.
}
return pivotIndex; // returning new pivot index.
}
void fastSort(int *array, int beginIndex, int endIndex)
{
if(beginIndex < endIndex)
{
int pivotIndex = fastSortPartition(array, beginIndex, endIndex);
fastSort(array, beginIndex, pivotIndex - 1);
fastSort(array, pivotIndex + 1, endIndex);
}
}
#endif
【问题讨论】:
-
这样:'在实现这个算法后,我发现它不能正常工作'你的意思是你注意到一些特定的数组没有被正确处理——对吗?如果是这样,你能显示致命的数组吗?
-
如果你能展示你的实现也很好。
-
这条评论有误:
// end index = array length - 1. -
不,这是正确的,我已经实现了数组长度为-1。由于是前向比较,否则最后一次迭代会溢出。
-
我相信您的代码不起作用。但我不相信这是 Lomuto 算法。成千上万的程序员从书中学到,你是第一个遇到错误的机会微乎其微。想说服我吗?展示你的实现和数据。
标签: c algorithm sorting quicksort