C 語言中,swap 函式(值的交換) 用於交換變數的值。例如,當有兩個變數 a = 5、b = 10 時,使用 swap 函式可以將它們改為 a = 10、b = 5。 C++ 提供了 std::swap 這樣的標準函式庫,但 C 語言並沒有此類內建函式。因此,在 C 語言中需要自行實作 swap 函式。
為什麼在 C 語言中需要自行實作 swap 函式?
與 C++ 不同,C 語言的標準並未提供通用的 swap 函式。因此,需要實作可針對特定資料型別套用的自訂 swap 函式。此外,透過指標可以安全地使用函式交換變數的值。
本文將學習的內容
本文將說明在 C 語言中實作 swap 函式的方法,並介紹其應用,包括陣列與結構體的值交換方法,以及在排序演算法中的使用範例。學習以下內容,可加深對 C 語言程式設計的理解。
#include <stdio.h>
// swap函式(使用指標)
void swap(int *a, int *b) {
int temp = *a; // 將 a 的值暫存於暫存變數
*a = *b; // 將 b 的值賦給 a
*b = temp; // 將暫存變數的值(原本的 a)賦給 b
}
int main() {
int x = 5, y = 10;
printf("交換前: x = %d, y = %dn", x, y);
swap(&x, &y);
printf("交換後: x = %d, y = %dn", x, y);
return 0;
}
執行結果
交換前: x = 5, y = 10
交換後: x = 10, y = 5
說明
temp 暫存 a 的值
a 賦予 b 的值
b 賦予 temp 的值(原本 a 的值)
優缺點
方法
優點
缺點
使用暫存變數
可讀性高,且不易產生錯誤
會消耗暫存變數的記憶體
此方法因可讀性高且安全,在一般的 C 程式中最被推薦的方式。
2.2 使用 XOR 演算的swap函式
利用 XOR(排他或)運算,可在不使用暫存變數的情況下交換變數的值。
程式碼範例
#include <stdio.h>
// 使用 XOR 的 swap 函式
void swap(int *a, int *b) {
if (a != b) { // 防止傳入相同位址的情況
*a = *a ^ *b;
*b = *a ^ *b;
*a = *a ^ *b;
}
}
int main() {
int x = 5, y = 10;
printf("交換前: x = %d, y = %dn", x, y);
swap(&x, &y);
printf("交換後: x = %d, y = %dn", x, y);
return 0;
}
執行結果
交換前: x = 5, y = 10
交換後: x = 10, y = 5
優缺點
方法
優點
缺點
使用 XOR 演算
不需要暫存變數,記憶體消耗少
可讀性差,且容易產生錯誤
2.3 使用加減算的swap函式
與 XOR 相同,作為不使用暫存變數交換變數值的方法,使用加減算(加法與減法)的方法也存在。
程式碼範例
#include <stdio.h>
// 使用加減算的 swap 函式
void swap(int *a, int *b) {
*a = *a + *b;
*b = *a - *b;
*a = *a - *b;
}
int main() {
int x = 5, y = 10;
printf("交換前: x = %d, y = %dn", x, y);
swap(&x, &y);
printf("交換後: x = %d, y = %dn", x, y);
return 0;
}
#include <stdio.h>
// 值傳遞的swap函式(錯誤的做法)
void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
int main() {
int x = 5, y = 10;
printf("交換前: x = %d, y = %dn", x, y);
swap(x, y);
printf("交換後: x = %d, y = %dn", x, y);
return 0;
}
執行結果
交換前: x = 5, y = 10
交換後: x = 5, y = 10 ← 值未被交換!
說明
呼叫 swap(x, y) 時,函式會收到 x 與 y 的副本。
因此,即使在函式內交換 a 與 b,原本的 x 與 y 仍不會改變。
要解決此問題,需要使用「參照傳遞(call by reference)」。
3.2 使用指標的swap函式
透過使用指標,可將變數的位址傳遞給函式,直接修改其值。
使用指標的swap函式
#include <stdio.h>
// 正確的swap函式(使用指標)
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 5, y = 10;
printf("交換前: x = %d, y = %dn", x, y);
swap(&x, &y); // 傳遞位址
printf("交換後: x = %d, y = %dn", x, y);
return 0;
}
#include <stdio.h>
// swap函式
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 調整堆積的函式
void heapify(int arr[], int n, int i) {
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && arr[left] > arr[largest])
largest = left;
if (right < n && arr[right] > arr[largest])
largest = right;
if (largest != i) {
swap(&arr[i], &arr[largest]);
heapify(arr, n, largest);
}
}
// 堆積排序函式
void heapSort(int arr[], int n) {
for (int i = n / 2 - 1; i >= 0; i--)
heapify(arr, n, i);
for (int i = n - 1; i > 0; i--) {
swap(&arr[0], &arr[i]);
heapify(arr, i, 0);
}
}
int main() {
int arr[] = {5, 2, 9, 1, 5, 6};
int size = sizeof(arr) / sizeof(arr[0]);
printf("排序前的陣列: ");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("n");
heapSort(arr, size);
printf("排序後的陣列: ");
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
printf("n");
return 0;
}