cs:app学习笔记(2):swap

  • swap
    • 两个数的交换
      • 说明
        • inplace_swap
        • swap
        • test_swap
      • 运行结果
    • 字符串首尾交换
      • csapp 所示的错误代码
        • 运行结果
        • 结果分析
      • 修改后的程序
        • 运行结果

swap

两个数的交换

#include 

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 

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 

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 

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 

你可能感兴趣的:(CS:APP,c)