swap
两个数的交换
#include <stdio.h>
void inplace_swap(int *x, int *y){
*x = *x ^ *y;
*y = *x ^ *y;
*x = *x ^ *y;
}
void swap(int *x, int *y){
int swap;
swap = *x;
*x = *y;
*y = swap;
}
void test_swap(int a, int b){
printf ("initial a = %d b = %d\n",a, b);
inplace_swap(&a, &b);
printf ("inplace swap a = %d b = %d\n",a, b);
swap(&a, &b);
printf ("normal swap a = %d b = %d\n",a, b);
}
int main(int argc, char const *argv[])
{
int a = 2, b = 1;
test_swap(a, b);
return 0;
}
说明
inplace_swap
- 第一个是使用位运算来进行两个数的交换,也就是就地交换,不需要另外设置一个变量达到交换的目的。
void inplace_swap(int *x, int *y){
*x = *x ^ *y;
*y = *x ^ *y;
*x = *x ^ *y;
}
- 但是在cs:app上所说的,这种交换没有任何的优势,只是一个智力游戏罢了。
swap
- 使用指针进行交换与传递。
void swap(int *x, int *y){
int swap;
swap = *x;
*x = *y;
*y = swap;
}
test_swap
void test_swap(int a, int b){
printf ("initial a = %d b = %d\n",a, b);
inplace_swap(&a, &b);
printf ("inplace swap a = %d b = %d\n",a, b);
swap(&a, &b);
printf ("normal swap a = %d b = %d\n",a, b);
}
int main(int argc, char const *argv[])
{
int a = 2, b = 1;
test_swap(a, b);
return 0;
}
运行结果
initial a = 2 b = 1
inplace swap a = 1 b = 2
normal swap a = 2 b = 1
字符串首尾交换
cs:app 所示的错误代码
#include <stdio.h>
void inplace_swap(int *x, int *y){
*x = *x ^ *y;
*y = *x ^ *y;
*x = *x ^ *y;
}
void reserve_array(int a[], int cnt){
int first, last;
for (first = 0, last = cnt-1;
first <= last;
first++,last--)
inplace_swap(&a[first], &a[last]);
}
void test_reserve_array(int a[], int len){
int i, j;
for (i = 0; i < len; i++)
printf ("%d ", a[i]);
printf("\n");
reserve_array(a, len);
for (i = 0; i < len; i++)
printf ("%d ", a[i]);
printf("\n");
}
int main(int argc, char const *argv[])
{
int l[5] = {0, 1, 2, 3, 4};
int m[6] = {0, 1, 2, 3, 4, 5};
printf ("wrong swap: \n");
printf ("No 1: \n");
test_reserve_array(l, 5);
printf ("No 2: \n");
test_reserve_array(m, 6);
return 0;
}
运行结果
wrong swap:
No 1:
0 1 2 3 4
4 3 0 1 0
No 2:
0 1 2 3 4 5
5 4 3 2 1 0
结果分析
- 当数组元素为偶数时,结果正确。
- 当数组元素为奇数时,结果错误,中间元素为零。
- 原因在于:
for (first = 0, last = cnt-1;
first <= last;
first++,last--)
中的first <= last;
当奇数时,first与last相同,&a[first], &a[last]
是同一个地址,调用inplace_swap
就会出错。
具体例子,详见下面的程序。
#include <stdio.h>
void inplace_swap(int *x, int *y){
*x = *x ^ *y;
printf ("first step:%d %d \n",*x,*y);
*y = *x ^ *y;
printf ("second step:%d %d \n",*x,*y);
*x = *x ^ *y;
printf ("third step:%d %d \n",*x,*y);
}
void swap(int *x, int *y){
int swap;
swap = *x;
*x = *y;
*y = swap;
}
void test_swap(int a, int b){
printf ("initial a = %d b = %d\n",a, b);
inplace_swap(&a, &b);
printf ("inplace swap a = %d b = %d\n",a, b);
swap(&a, &b);
printf ("normal swap a = %d b = %d\n",a, b);
}
int main(int argc, char const *argv[])
{
int a = 5, b = 5;
printf ("when inplace_swap(&a, &b):\n");
inplace_swap(&a, &b);
printf ("inplace swap a = %d b = %d\n",a, b);
printf ("\n\n");
printf ("when inplace_swap(&a, &a):\n");
inplace_swap(&a, &a);
printf ("inplace swap a = %d b = %d\n",a, b);
return 0;
}
运行结果:
when inplace_swap(&a, &b):
first step:0 5
second step:0 5
third step:5 5
inplace swap a = 5 b = 5
when inplace_swap(&a, &a):
first step:0 0
second step:0 0
third step:0 0
inplace swap a = 0 b = 5
- 传入同一个地址,就会在
first step
中奖变量全部修改掉。注意指针的问题。
修改后的程序
#include <stdio.h>
void inplace_swap(int *x, int *y){
*x = *x ^ *y;
*y = *x ^ *y;
*x = *x ^ *y;
}
void reserve_array(int a[], int cnt){
int first, last;
for (first = 0, last = cnt-1;
first < last;
first++,last--)
inplace_swap(&a[first], &a[last]);
}
void test_reserve_array(int a[], int len){
int i, j;
for (i = 0; i < len; i++)
printf ("%d ", a[i]);
printf("\n");
reserve_array(a, len);
for (i = 0; i < len; i++)
printf ("%d ", a[i]);
printf("\n");
}
int main(int argc, char const *argv[])
{
int l[5] = {0, 1, 2, 3, 4};
int m[6] = {0, 1, 2, 3, 4, 5};
printf ("right swap: \n");
printf ("No 1: \n");
test_reserve_array(l, 5);
printf ("No 2: \n");
test_reserve_array(m, 6);
return 0;
}
- 将
<=
改成<
。
运行结果
right swap:
No 1:
0 1 2 3 4
4 3 2 1 0
No 2:
0 1 2 3 4 5
5 4 3 2 1 0