[英]How does the following quicksort method works?
我为教育目的编写了自己的Quicksort方法。 为了改进它,我看了一下.NET源代码,看看如何实现LINQ OrderBy()
方法。
我找到了以下Quicksort方法 :
void QuickSort(int[] map, int left, int right) {
do {
int i = left;
int j = right;
int x = map[i + ((j - i) >> 1)];
do {
while (i < map.Length && CompareKeys(x, map[i]) > 0) i++;
while (j >= 0 && CompareKeys(x, map[j]) < 0) j--;
if (i > j) break;
if (i < j) {
int temp = map[i];
map[i] = map[j];
map[j] = temp;
}
i++;
j--;
} while (i <= j);
if (j - left <= right - i) {
if (left < j) QuickSort(map, left, j);
left = i;
}
else {
if (i < right) QuickSort(map, i, right);
right = j;
}
} while (left < right);
}
我试图了解内部运作。 AFAIK看起来与Hoare分区方案非常相似,但有一些轻微的优化。
我不清楚的是:
if (j - left <= right - i)
的结果if (j - left <= right - i)
) do { ... } while (left < right)
? 是因为我们只按照上面的建议递归枢轴的一侧吗? if (i < j)
条件测试? 不是break;
声明之前够吗? 相比之下,这是我的实际实现Quicksort看起来如何(直接实现Hoare分区方案)
void QuickSort(int[] map, int left, int right)
{
if (left < right)
{
int i = left - 1;
int j = right + 1;
int x = map[left + ((right - left) >> 1)];
while (true)
{
do { i++; } while (Compare(map[i], x) < 0);
do { j--; } while (Compare(map[j], x) > 0);
if (i >= j) break;
int temp = map[i];
map[i] = map[j];
map[j] = temp;
}
QuickSort(map, left, j);
QuickSort(map, j + 1, right);
}
}
为什么我们在分区后只递归枢轴的一侧? (取决于if的结果(j - 左<=右 - i))
最小化递归深度(和堆栈使用)。 当我们尽快处理较大的分区并仅对较小的分区进行递归时,深度不会超过log(n)
为什么我们在整个事情上有{...} while(左<右)?
对left
和right
后的项进行排序,因此这些索引在所有数组都已排序时满足
为什么在交换之前有if(i <j)条件测试?
只是为了避免不必要的交换等于索引
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.