在K& R第二版,第5.11节,第107页:
void qsort(void *v[], int left, int right, int (*comp)(void *, void *))
{
int i, last;
void swap(void *v[], int, int);
if (left >= right)
return;
swap(v, left, (left + right)/2);
last = left;
for (i = left+1; i <= right; i++)
if ((*comp)(v[i], v[left]) < 0) /* Here's the function call */
swap(v, ++last, i);
swap(v, left, last);
qsort(v, left, last-1, comp);
qsort(v, last+1, right, comp);
}
然而,我对&#34;交换(v,左,(左+右)/ 2);&#34;感到困惑。我认为这是无用的......这句话的目的是什么?
答案 0 :(得分:1)
如果没有句子,如果数组V []是随机数据则没有问题。
但是,如果V []是排序数据,则不会遇到交换,
并且变量 last 不会更改。
因此,最后的qsort()等同于qsort(v, left+1, right, comp)
。
这意味着在递归调用中只有一个元素减少了。
当函数中的比较次数为n时,
比较需要n +(n-1)+(n-2)+ ... + 1 = n(n + 1)/ 2次才能完成。
如果n很大,则需要很长时间。
此外,如果V []非常大,则可能遇到堆栈溢出错误。
该声明的存在是为了防止它们
此外,(left + right) / 2
应为left + (right - left) / 2
防止溢出错误。
答案 1 :(得分:0)
此交换用于拾取枢轴元素并将其置于最左侧位置。然后,变量last
用于计算更大的元素数量远远超过右侧分区的数据。我们实际上并没有计算数字 - 但只是右边分区最左边元素的位置。在那之后,我们可以安全地将枢轴放回到它所属的位置(恰好在右侧分区的左侧) - 这是第二个swap
所做的 - 并且免费形成左侧分区,因为我们确切知道所有不是枢轴或右分区的元素必须属于左边的分区。
尽管如此,我强烈建议您只需拿一张纸,写一些随机整数数组并尝试逐行浏览代码以查看分区过程是如何执行的。