我在理解来自K& R的快速排序算法(没有指针的简化版本)时遇到了问题。 Dave Gamble已经在explanation提供了详尽的解释。 但是我注意到,从稍微改变的字符串开始,我们可以在for循环的许多循环中获得没有交换。 首先是代码:
void qsort(int v[], int left, int right)
{
int i, last;
void swap(int v[], int i, int j);
if (left >= right) /* do nothing if array contains */
return; /* fewer than two elements */
swap(v, left, (left + right)/2); /* move partition elem */
last = left; /* to v[0] */
for (i = left + 1; i <= right; i++) /* partition */
if (v[i] < v[left])
swap(v, ++last, i);
swap(v, left, last); /* restore partition elem */
qsort(v, left, last-1);
qsort(v, last+1, right);
}
我的观点中的演练:
我们从CADBE开始;左= 0;右= 4; D是枢轴 所以根据算法我们用D交换D得到DACBE
last = left = 0
i = 1 if if(v 1&lt; v [0])这是真的所以我们用v 1交换v 1(因为last在运行前增加)所以没有变化,最后= 1,仍然有DACBE;
现在i = 2 if(v [2]&lt; v [0]) - &gt;是的,所以我们用v [2]交换v [2]再没有改变; last = 2
现在i = 3 if(v [3]&lt; v [0]) - &gt;是的,所以我们用v [3]交换v [3]没有改变AGAIN(!),last = 3
显然有些事情是错误的,算法什么都不做。 你的意见非常赞赏。我一定是错的,作者比我好; D 提前谢谢!
答案 0 :(得分:3)
循环从left + 1
到,包括 right
。 i=4
时,测试失败,last
不会增加。
然后递归调用BACDE
和left=0,right=2
排序left=4,right=4
。 (当D
是支点时,这是正确的。)
答案 1 :(得分:2)
嗯,恰好您的输入子数组ACBE
已经被D
分区(ACB
小于D
而E
是大于D
),因此分区周期不会实际交换任何值也就不足为奇了。
实际上,说它“无所作为”是不正确的。它不会对周期中的任何内容重新排序,因为您的输入数据不需要额外的重新排序。但它仍然做了一件事:它找到了last
的值,它表示较小的元素结束,较大的元素开始,即它将ACBE
分成ACB
和E
部分。循环以last == 3
结束,这是进一步递归步骤的分区点。