当我使用以下代码进行快速排序交换时,它正在运行。
void s(int *a, int *b)
{
int t = *a;
*a = *b;
*b = t;
}
但是,当我使用以下代码交换元素进行快速排序时,它无效。
void s(int *a, int *b)
{
*a = *a + *b;
*b = *a - *b;
*a = *a - *b;
}
我无法弄清楚代码有什么问题。
我在下面添加了快速排序代码以供澄清。
void qs(int *a, int l, int h){
if( l<h){
int pi = pa(a, l, h);
qs(a, l, pi-1); qs(a, pi+1, h);
}
}
int pa(int *a, int l, int h){
int p = a[h], lt = l-1, i;
for(i=l; i<=h-1; i++) if(a[i]<=p) s(&a[++lt], &a[i]);
s(&a[lt+1], &a[h]);
return lt+1;
}
答案 0 :(得分:1)
*a = *a + *b;
*b = *a - *b;
*a = *a - *b;
该代码是交换数字的经典技巧。问题必须在于传入的值。您需要验证您正在使用的指针是不一样的,并且您没有溢出问题。
答案 1 :(得分:1)
第二个功能有两个问题。其中一个,俞昊已经确定,但后来被删除,是你有可能签署整数溢出。
假设您只处理不会导致溢出的数字,第二个问题是如果两个指针指向同一个对象,则对象最终会以0
的值结束,无论值是多少它始于。
假设您已将变量c
初始化为17
,并使用swap(&c, &c)
调用swap:
.-----------.
\|/ |
+--'----+ +---+ +---+
| c: 17 | | a | | b |
+--.----+ +---+ +---+
/|\ |
`--------------------'
由于在swap()
内,a
和b
都指向c
,最后一次分配的结果会将值0
放入{{1}因为c
等同于*a = *a - *b
。
要解决溢出问题,可以通过确保参数符号相反来确保总和永不溢出。要修复“指向同一个对象”的问题,只需检查交换函数内的那个。
c = c - c
正如您所看到的,这已经比使用第一版交换功能复杂得多。如果你担心使用另一个变量可能会使程序以某种方式存在缺陷,那就把这些担忧放在一边。几乎所有用于商业开发的编译器都会识别交换,并为其生成最佳代码。
答案 2 :(得分:1)
交换是正确的,可能你的整体快速排序中有一个错误。或编译器优化的东西
答案 3 :(得分:0)
此代码适用于我。
#include <stdio.h>
void swap(int*, int*);
int main()
{
int x, y;
printf("Enter the value of x and y\n");
scanf("%d%d",&x,&y);
printf("Before Swapping\nx = %d\ny = %d\n", x, y);
swap(&x, &y);
printf("After Swapping\nx = %d\ny = %d\n", x, y);
return 0;
}
void swap(int *a, int *b)
{
*a = *a + *b;
*b = *a - *b;
*a = *a - *b;
}
尝试了,http://www.compileonline.com/compile_c_online.php
所以,我的观点是交换是正确的,我认为你的快速排序代码存在问题。
答案 4 :(得分:0)
我会使用第一种方式来交换值。
第二个看起来好像应该有效。但是范围有限并且不太好:
它应该有效,除非你的编译器正在为你优化一些东西,或者你遇到上面的情况1或2 ... 例如: a = 2 b = 3
*a = *a + *b; // *a = 2 + 3 = 5
*b = *a - *b; // *b = 5 - 3 = 2
*a = *a - *b; // *a = 5 - 2 = 3
答案 5 :(得分:0)
在进行快速排序时,在分区方法调用中,有时会在同一位置调用交换。 因此,这是swap方法中的这一行:
*a = *a + *b;
将意味着*a
和*b
现在都以(*a + *b)
作为其反映更改的相同位置。
交换之前最好先检查a!=b
。