交换没有临时变量的数组元素

时间:2014-02-25 04:30:13

标签: c

当我使用以下代码进行快速排序交换时,它正在运行。

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;        
}

6 个答案:

答案 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()内,ab都指向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. 如果* a和* b都指向相同的值,则值为0
  2. 你可以溢出大值
  3. 使用3次分配和3次添加操作
  4. 效率不高

    它应该有效,除非你的编译器正在为你优化一些东西,或者你遇到上面的情况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