一、交换算法
C语言交换两个数的3种实现方法(附完整示例)
交换两个数是C语言基础操作,以下提供3种核心实现方式,涵盖「通用无风险」「无临时变量」等场景,附原理、代码和优缺点分析。
方法1:临时变量法(最推荐,通用无风险)
核心思路
定义一个临时变量作为"中转站",先保存其中一个数的值,再完成交换,是最基础、通用且无副作用的方法,适用于所有数据类型(int/float/double等)。
代码示例
c
#include <stdio.h>
// 交换整数(通用版,可适配其他类型)
void swap(int *a, int *b) {
int temp; // 临时变量
temp = *a; // 保存a的值到临时变量
*a = *b; // 把b的值赋给a
*b = temp; // 把临时变量(原a值)赋给b
}
// 测试交换浮点数(仅需修改类型)
void swap_float(float *a, float *b) {
float temp;
temp = *a;
*a = *b;
*b = temp;
}
int main() {
// 测试交换整数
int x = 10, y = 20;
printf("交换前:x=%d, y=%d\n", x, y);
swap(&x, &y); // 传地址(指针),才能修改原变量
printf("交换后:x=%d, y=%d\n\n", x, y);
// 测试交换浮点数
float m = 3.14, n = 6.28;
printf("交换前:m=%.2f, n=%.2f\n", m, n);
swap_float(&m, &n);
printf("交换后:m=%.2f, n=%.2f\n", m, n);
return 0;
}
优点&缺点
- ✅ 优点:逻辑简单、无溢出风险、适配所有数据类型(整数/浮点/字符等);
- ❌ 缺点:需要额外占用1个临时变量的内存(可忽略,几乎无影响)。
方法2:算术运算法(不用临时变量,仅适用于数值类型)
核心思路
利用「加减运算」抵消值的差异,无需临时变量,但仅适用于整数/浮点型,且两个大数相加可能触发溢出(超出数据类型取值范围)。
代码示例
c
#include <stdio.h>
void swap(int *a, int *b) {
*a = *a + *b; // a = 原a + 原b
*b = *a - *b; // b = (原a+原b) - 原b = 原a
*a = *a - *b; // a = (原a+原b) - 原a = 原b
}
int main() {
int x = 5, y = 8;
printf("交换前:x=%d, y=%d\n", x, y);
swap(&x, &y);
printf("交换后:x=%d, y=%d\n", x, y);
return 0;
}
优点&缺点
- ✅ 优点:无需临时变量,代码简洁;
- ❌ 缺点:
- 仅适用于数值类型(无法交换字符/字符串等);
- 整数相加可能溢出(如
a=2^30,b=2^30,相加后超出int范围); - 若
a和b指向同一地址(swap(&x, &x)),结果会变为0(逻辑错误)。
方法3:位运算法(异或,仅适用于整数)
核心思路
利用异或运算(^) 的特性:
- 一个数异或自身等于0(
a^a=0); - 一个数异或0等于自身(
a^0=a); - 异或满足交换律和结合律(
a^b^c = a^(b^c))。
仅适用于整数类型(char/int/long等),无溢出风险。
代码示例
c
#include <stdio.h>
void swap(int *a, int *b) {
if (a == b) return; // 避免同一地址异或后变为0
*a = *a ^ *b; // 步骤1:a = 原a ^ 原b
*b = *a ^ *b; // 步骤2:b = (原a^原b) ^ 原b = 原a
*a = *a ^ *b; // 步骤3:a = (原a^原b) ^ 原a = 原b
}
int main() {
int x = 100, y = 200;
printf("交换前:x=%d, y=%d\n", x, y);
swap(&x, &y);
printf("交换后:x=%d, y=%d\n", x, y);
return 0;
}
优点&缺点
- ✅ 优点:无需临时变量、无溢出风险、仅操作二进制位,效率高;
- ❌ 缺点:
- 仅适用于整数类型(无法交换浮点/字符);
- 可读性差(需理解异或特性);
- 若
a和b指向同一地址,结果会变为0(需加判断规避)。
关键注意事项
- 传参方式:上述代码均用「指针传参」,因为C语言默认是"值传递",直接传变量会复制一份值,无法修改原变量;
- 选型建议 :
- 日常开发/通用场景:优先用「临时变量法」(无坑、易维护);
- 嵌入式/内存极度受限场景:用「位运算法」(仅整数);
- 避免用「算术运算法」(溢出风险高);
- 扩展适配 :若需交换其他类型(如
double/char),只需修改临时变量法的类型即可,无需改逻辑。