我尝试了很多不同的方法来写这个,但大多数时候我陷入无休止的循环中。 这个版本的代码根本不对它进行排序,我不知道问题是什么。
void quickSort(int unsorted[], int left, int right) {
int i = left, j = right;
int pivot = (left + right) / 2;
while (i == pivot || j == pivot) {
if (unsorted[i] >= unsorted[pivot] && unsorted[pivot] >= unsorted[j])
swap(unsorted[i], unsorted[j]);
if (i < pivot)
i++;
if (j > pivot)
j--;
};
if (left < j && unsorted[left] != unsorted[j])
right = pivot, quickSort(unsorted, left, right);
if (i < right && unsorted[right] != unsorted[i])
left = pivot +1, quickSort(unsorted, left, right);
}
unsorted
是一个数组,填充了0到200之间的100个随机值。
我很抱歉更新缓慢。 关于代码,我重写了大部分内容。 这就是现在的样子:
void quickSort(int unsorted[], int left, int right)
{
int i = left,
j = right,
count = 0;
int pivot = (left + right) / 2;
do
{
while (unsorted[i] < unsorted[pivot])
i++;
while (unsorted[j] > unsorted[pivot])
j--;
if (unsorted[i] >= unsorted[j] && i <= j)
{
swap(unsorted[i], unsorted[j]);
i++;
j--;
count++;
}
if (i == pivot && unsorted[pivot] < unsorted[j] && count == 0)
{
swap(unsorted[i], unsorted[j]);
i++;
j--;
count++;
}
if (j == pivot && unsorted[pivot] < unsorted[i] && count == 0)
{
swap(unsorted[i], unsorted[j]);
i++;
j--;
count++;
}
if (i == j && unsorted[i] > unsorted[pivot] && count == 0)
{
swap(unsorted[i], unsorted[pivot]);
i++;
j--;
count++;
}
if (i == j && unsorted[i] < unsorted[pivot] && count == 0)
{
swap(unsorted[i], unsorted[pivot]);
i++;
j--;
}
count = 0;
} while (i < j);
if (left < j)
quickSort(unsorted, left, j);
if (i < right)
quickSort(unsorted, i, right);
}
我一直在用10个随机值反复尝试这个代码,它大部分时间都可以工作。在某些情况下它不起作用,我想弄清楚什么时候。
当它不起作用的一个例子是值为:160,151,159,112,7,121,105,48,186。
解决了它。删除了很多代码,使它更简单,但至少它的工作原理。 甚至不知道你是否可以称之为快速搜索,但这是最终版本:
void quickSort(int unsorted[], int left, int right)
{
int i = left,
j = right;
int pivot = right;
do
{
while (unsorted[i] < unsorted[pivot])
i++;
while (unsorted[j] > unsorted[pivot])
j--;
if (unsorted[i] >= unsorted[j] && i <= j)
{
swap(unsorted[i], unsorted[j]);
i++;
j--;
}
} while (i < j);
if (left < j)
quickSort(unsorted, left, j);
if (i < right)
quickSort(unsorted, i, right);
}
答案 0 :(得分:3)
您没有在长度为1的数组上测试您的函数。
让它工作,然后尝试一个长度为2的数组。
一旦它正常工作,当你给它一个长度为3的数组时,很有可能它会起作用。
修改:
赞赏包含可重复的例子。
此代码在递归之前失败。第一步是选择一个枢轴元素并移动一些元素,直到枢轴元素不小于其左边的任何元素,并且不超过它的右边的任何元素。您的代码会丢失它认为是pivot元素的元素;它交换了枢轴元素,但似乎认为相同的位置仍然是枢轴。尝试用铅笔和纸做这个算法,你会明白我的意思。
答案 1 :(得分:1)
这项检查对我来说很奇怪
while (i == pivot || j == pivot)
不应该至少
while (i != pivot && j != pivot)
P.S。我认为这不是唯一的问题,而是一开始......
答案 2 :(得分:0)
在没有看到swap
的情况下,我的第一个预感就是你的swap
按值获取其参数。即它交换了两份副本,而不是参数本身。
答案 3 :(得分:0)
现在我们需要分区。让我们做一个我们能想到的最简单的分区。当你刚开始使用快速排序时,我建议使用以下内容:[ < pivot | >= pivot | unsorted ]
。这是我们每一步都想要的不变量。一开始,一切都将在未分类的分区中。最后,未分类的分区中没有任何内容。我们怎么做到这一点?
left+1
到right
循环。 [ < pivot ]
分区(我留给你 - 你要跟踪左边两个分区之间的边界) 。如果不是,我们继续前进。 [ < pivot | pivot | >= pivot ]
。快速分离最左边和最右边的分区,事情应该正在查找此代码。尝试使用[ < pivot | unsorted | >= pivot ]
分区之类的更好的东西(如果正确完成,可以更快地完成)。我认为你当前的实现是尝试进行这种分区,但除非我或j指向一个等于pivot的元素,否则不会进行任何交换。这种分区比较棘手,我建议在进入任何比赛之前给我们的代码一个脉冲。
希望能够让你的代码成型,但这只是一个非常基本的快速排序。您应该研究Bentley-McIlroy分区和枢轴选择方法,以使其更先进。