C 为什么这种快速排序有效?
我发现这种快速排序分区方法既令人困惑又错误,但它似乎是有效的。我指的是注意:他们在文章的最后还有一个C实现,但它与他们的伪代码有很大的不同,所以我不在乎这一点 我也用C写过这样的代码,尽量忠实于伪代码,即使这意味着要做一些奇怪的C代码:C 为什么这种快速排序有效?,c,algorithm,quicksort,C,Algorithm,Quicksort,我发现这种快速排序分区方法既令人困惑又错误,但它似乎是有效的。我指的是注意:他们在文章的最后还有一个C实现,但它与他们的伪代码有很大的不同,所以我不在乎这一点 我也用C写过这样的代码,尽量忠实于伪代码,即使这意味着要做一些奇怪的C代码: #include <stdio.h> int partition(int a[], int p, int r) { int x = a[p]; int i = p - 1; int j = r + 1; whil
#include <stdio.h>
int partition(int a[], int p, int r)
{
int x = a[p];
int i = p - 1;
int j = r + 1;
while (1)
{
do
j = j - 1;
while (!(a[j] <= x));
do
i = i + 1;
while (!(a[i] >= x));
if (i < j)
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
else
{
for (i = 1; i <= a[0]; ++i)
printf("%d ", a[i]);
printf("- %d\n", j);
return j;
}
}
}
int main()
{
int a[100] = //{8, 6,10,13,15,8,3,2,12};
{7, 7, 6, 2, 3, 8, 4, 1};
partition(a, 1, a[0]);
return 0;
}
并产生以下输出:
1 6 2 3 8 4 7-1
在我看来,这是一个正确的结果:轴(a[r]=a[7]
)已到达其最终位置
但是,如果我在以下算法中使用初始分区函数:
void Quicksort(int a[], int p, int r)
{
if (p < r)
{
int q = partition(a, p, r); // initial partitioning function
Quicksort(a, p, q);
Quicksort(a, q + 1, r); // I'm pretty sure q + r was a typo, it doesn't work with q + r.
}
}
void快速排序(int a[],int p,int r)
{
if(p
。。。这似乎是一个正确的排序算法。我在很多随机输入上测试了它,包括所有长度为20的0-1数组
我还尝试将此配分函数用于选择算法,但未能产生正确的结果。它似乎是有效的,但作为快速排序算法的一部分,它甚至非常快
因此,我的问题是:
我认为分区是正确的。7是支点。原始数组被划分为一个长度为5的子数组,其中包含小于或等于7的元素,以及一个长度为2的子数组,其中包含大于或等于7的元素。From(我强调了我认为直接解决您问题的部分): 这是就地分区 算法。它将部分分割开来 左索引和右索引之间的数组的 对,包括移动所有 元素小于或等于 数组[pivotIndex]到 子阵列,留下所有更大的 它们后面的元素。在 处理它也会找到最终结果 枢轴元素的位置,该位置 它回来了它会临时移动 将图元旋转到轴的末端 子阵列,这样它就不会进入 方法。因为它只使用 交换,最后的名单也一样 元素作为原始列表。通知 一个元素可以被交换 在达到其极限之前多次 最后的位置。还应注意到这一点 如果轴在中重复 在输入阵列中,它们可以被分散 穿过左子阵列,可能在 随机顺序。这并不代表一个错误 分区失败,进一步 排序将重新定位并最终 把它们粘在一起
这可能是您缺少的吗?您正在混淆项目的索引和iten值 看你的头球
int partition(int a[], int p, int r) ;
现在,如果我们将数组a上的数据类型更改为某种奇怪的数据类型,您将看到问题所在
int partition( Otherdatatype a[], int p, int r) ;
您可以使用从main中调用函数
partition(a, 1, a[0]);
请参阅问题a[0]是a[0]中项目的值,而不是索引值
假设代码中[0]的值为200,只需将第一项的值更改为200,就会出现运行时错误“尝试访问超出范围的内存”,因为
通过将[0]=200作为值r传递到分区中,然后跟踪分区内发生的情况
需要记住的是,这是分区头中的一个排序例程。数组a中的列表可能与索引的类型不同。。标题的p和r显然是指索引位置的索引,a是要排序的列表
因此,排序的主要开始是
partition(a, 0, items_in_array-1);
你明白为什么吗?数组a从[0]运行。。。a[项目\u在\u数组-1中]
因此,在上面的示例中,您已经将8个值预加载到数组中,因此来自main的分区调用应该是
partition(a, 0, 7);
从上面往下延伸就是它的样子
void swap(int *a, int *b)
{
int x;
x = *a;
*a = *b;
*b = x;
}
int partition(int s[], int l, int h)
{
int i;
int p;/* pivot element index */
int firsthigh;/* divider position for pivot element */
p = h;
firsthigh = l;
for (i = l; i < h; i++)
if(s[i] < s[p]) {
swap(&s[i], &s[firsthigh]);
firsthigh++;
}
swap(&s[p], &s[firsthigh]);
return(firsthigh);
}
void quicksort(int s[], int l, int h)
{
int p;/* index of partition */
if ((h - l) > 0) {
p = partition(s, l, h);
quicksort(s, l, p - 1);
quicksort(s, p + 1, h);
}
}
int main()
{
int a[100] = //{8, 6,10,13,15,8,3,2,12};
{7, 7, 6, 2, 3, 8, 4, 1};
quicksort(a, 0, 7);
return 0;
}
无效交换(int*a,int*b)
{
int x;
x=*a;
*a=*b;
*b=x;
}
整数分区(整数s[],整数l,整数h)
{
int i;
int p;/*枢轴元素索引*/
int firsthigh;/*枢轴元件的分隔器位置*/
p=h;
第一高=l;
对于(i=l;i0){
p=分区(s、l、h);
快速排序(s、l、p-1);
快速排序(s、p+1、h);
}
}
int main()
{
int a[100]=/{8,6,10,13,15,8,3,2,12};
{7, 7, 6, 2, 3, 8, 4, 1};
快速排序(a,0,7);
返回0;
}
你的意思是它是正确的,因为a[1..5]
有元素=7
?这是真的,但选定的轴不应该到达其最终位置吗?根据我的教科书和维基百科,应该是这样的。在您给出的第一个链接中,quicksort然后对[1..5]和[6..7]进行排序。只有在wikipedia链接中,a[6]的最终值必须是7,因为这里a[1..5]和a[7..7]是在递归调用中排序的。有趣的是,我没有这样想。我一直认为分区算法应该返回pivot元素的最终位置。谢谢你的解释。稍后我会接受你的回答,让其他人也有机会对这个算法发表评论。是的,正如Henrik所说,它是有效的,但重新排序轴心是一种非常浪费的方式。它有一个不同于维基百科的排序不变量([=p]vs[p])。通常情况下,您不会看到以这种方式进行快速排序的原因是它没有那么有效。使用枢轴将产生更多的旋转
void swap(int *a, int *b)
{
int x;
x = *a;
*a = *b;
*b = x;
}
int partition(int s[], int l, int h)
{
int i;
int p;/* pivot element index */
int firsthigh;/* divider position for pivot element */
p = h;
firsthigh = l;
for (i = l; i < h; i++)
if(s[i] < s[p]) {
swap(&s[i], &s[firsthigh]);
firsthigh++;
}
swap(&s[p], &s[firsthigh]);
return(firsthigh);
}
void quicksort(int s[], int l, int h)
{
int p;/* index of partition */
if ((h - l) > 0) {
p = partition(s, l, h);
quicksort(s, l, p - 1);
quicksort(s, p + 1, h);
}
}
int main()
{
int a[100] = //{8, 6,10,13,15,8,3,2,12};
{7, 7, 6, 2, 3, 8, 4, 1};
quicksort(a, 0, 7);
return 0;
}