cs:app學習筆記(2):swap

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 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章