swap函數 进阶探讨与实现

相信以下這個C程序非常多人都見過啦。當時自己看 美少女战士谭浩强 写的那本书上的解释。反正我当时是没看太懂详细是什么意思。谱架啊~~~

#include <stdio.h>

void swap(int x, int y)
{
    int temp = x;
    x = y;
    y = temp;
}

int main()
{
    int n, m;
    while(~scanf("%d %d", &n, &m)) {
        swap(n, m);
        printf("%d <--> %d\n", n, m);
    }
    return 0;
}

看结果。这个swap函数是一点用都没有啦,所以嘞,下面的程序就是帮助理解滴:

#include <stdio.h>

void swap(int x, int y)
{
    printf("The formal parameter X's address : %d\n", &x);
    printf("The formal parameter Y's address : %d\n", &y);
    printf("--------------------------------------------\n");
    int temp = x;
    x = y;
    y = temp;
    printf("The formal parameter X's address : %d\n", &x);
    printf("The formal parameter Y's address : %d\n", &y);
    printf("--------------------------------------------\n");
}

int main()
{
    int n, m;
    while(~scanf("%d %d", &n, &m)) {
        printf("The actual parameter N's address : %d\n", &n); //呢个actual 同埋formal系实參,形參唧意思。
        printf("The actual parameter M's address : %d\n", &m);
        printf("--------------------------------------------\n");
        swap(n, m);
        printf("%d <--> %d\n", n, m);
    }
    return 0;
}

执行结果:

从执行结果能够看到实參与形參的地址是不一样滴。所以。你改变形參内存地址存储的值不会影响到实參内存地址中存储的值。 实參与形參的结合仅仅是值传递。而不是地址传递。

所以从这个“实參向形參传递地址”这个思路其中能够实现swap函数的功能:

#include <stdio.h>

void swap(int *x, int *y)
{
    int temp = *x;
    *x = *y;
    *y = temp;
}

int main()
{
    int n, m;
    while(~scanf("%d %d", &n, &m)) {
        swap(&n, &m);   //传递的是地址,所以形参與实参相应共用同一段地址。
        printf("%d <--> %d\n", n, m);
    }
    return 0;
}

或者用第二种思路啦,“引用”,引用变量是已定义的变量的别名,它与这个变量共同指向同一段地址,它会随着引用变量值的改变而改变;

#include <stdio.h>

void swap(int &x, int &y)
{
    int temp = x;
    x = y;
    y = temp;
}

int main()
{
    int n, m;
    while(~scanf("%d %d", &n, &m)) {
        swap(n, m);
        printf("%d <--> %d\n", n, m);
    }
    return 0;
}

悄悄告訴你,還有一種方法啦,哈哈:

#include <stdio.h>

int swap(int &a, int &b)
{
    a = a ^ b;
    b = a ^ b;
    a = a ^ b;
}

int main()
{
    int n, m;
    while(~scanf("%d %d", &n, &m)) {
        swap(n, m);
        printf("%d <--> %d\n", n, m);
    }
    return 0;
}

或者:

void swap(int *x, int *y)
{
    *y = *x ^ *y;
    *x = *x ^ *y;
    *y = *x ^ *y;
}

這個是運用到了二進制邏輯運算 + 每個元素的加法逆元 a ^ a = 0, 假设想好好理解一下的話,自己推導一下就能够了,挺簡單的~~

时间: 2024-10-14 09:52:59

swap函數 进阶探讨与实现的相关文章

學習日記:函數和對象

2016-2-21 1. Living without an aim is like sailing without a compass. 生活沒有目標,猶如航海沒有羅盤. 2. 無論是現實世界還是計算機世界,可讀性都是相當重要的,因為這涉及到人們的意識或者是認識效率,一般文字比數字的可理解性和可讀性要好,圖片的可讀性最強. a) 一般數學是比較抽象的,因為其中充滿著各種阿拉伯數字和已經不能再簡化的希臘字符. b) 數學家的得意之作就是覺得自己是在世界科學界的最巔峰. c) 我們能用數學工具處理

對比:莫比烏斯反演與歐拉函數

最近題讓我非常困惑,貌似我現在已經完全分不清楚哪些題用莫比烏斯反演,哪些用歐拉函數. 下面簡單總結一下,莫比烏斯反演處理的是 求segma(gcd(x,y)) 1<=x<=n,1<=y<=m (見<能量項鍊>) gcd(x,y) = k   1<=x<=n 1<=y<=m  求x,y對數 (見<bzoj 2301  problem b>) 莫比烏斯反演原來是解決以上問題2的,大體思路是 設F(a,b,k)表示1<=x<=a

SQL窗口函數一例

需求: MSSQL,列出服務實例中所有數據庫的如下信息: 數據庫ID.數據庫名.創建日期.數據文件類型.數據文件大小.數據庫總大小.文件所在路徑. 寫法(後面的百分比為所花時間占比): -- 连接子查询 (47%) WITH cte_TotalSize AS ( SELECT database_id ,CAST(SUM(size) AS FLOAT)/128 AS [TotalSize(MB)] FROM sys.master_files GROUP BY database_id ) SELEC

SQL窗体函數一例

需求: MSSQL,列出服務實例中全部數據庫的例如以下信息: 數據庫ID.數據庫名.創建日期.數據文件類型.數據文件大小.數據庫總大小.文件所在路徑. 寫法(後面的百分比為所花時間占比): -- 连接子查询 (47%) WITH cte_TotalSize AS ( SELECT database_id ,CAST(SUM(size) AS FLOAT)/128 AS [TotalSize(MB)] FROM sys.master_files GROUP BY database_id ) SEL

ORACLE字符拆分函數,返回結果集

ORACLE不能像MSSQL那樣支持直接返回表類型,所以要先創建一種自定義類型.這裏用到的是嵌套表(Nested Table). -- Nested Table CREATE OR REPLACE TYPE split_str IS TABLE OF VARCHAR(100); / -- Function CREATE OR REPLACE FUNCTION fn_Split ( p_Str VARCHAR2, p_Delimiter VARCHAR2 ) RETURN split_str PI

js匿名函數

(function($){})(jquery) == (function($){})(jQuery) 实际上是匿名函数 用于存放开发插件的代码 作用(非常有用): 这种写法的最大好处是形成闭包.在(function($) {…})(jQuery)在内部定义的函数和变量只能在此范围内有效.   形成是否函数函数.私有变量的概念.比如: var i=3; function init(){ alert("外层init:"+i); } (function($) { var i=2; funct

EF架构~在Linq to Entity中使用日期函數

回到目录 眾所周知,在linq to entity的查询语句中,不允许出现ef不能识别的关键字,如Trim,Substring,TotalDays等.net里的关键字,在EF查询里都是不被支持的,它的原因可能是为了更好的提高查询的性能吧,毕竟,好的性能取决于你的程序标准,有了一个严格的标准,才能设计出好的程序来. 今天主要说一下,EF为日期方法留的一个后门,<后门>这个词大家在中国社会都应该知道了,顾名思义,就是反着原则走,你的原则对我没有用,哈哈!这东西有时候是有用的,因为在大的原则下,很可

DB2常用函數總結

最近用DB2,数据库之间的差异还是很大的,好多函数都不一样 1.去空格 *DB2中:Ltrim()是去左边空格,rtrim()是去右边空格.*informix中:trim()就是去空格.用法:例:string a="  abc  ";     *DB2中:Ltrim(a)="abc  ";rtrim(a)="  abc",rtrim(ltrim(a))="abc";     *informix中:trim(a)="a

C/C++ 時間相關函數

最近在處理一些時間上面的問題,將這些函數整理一下囉 先從基本時間概念開始,比較要注意的應該是秒之下的時間單位 毫秒(ms):1秒=1000毫秒 之所以會看到這個時間單位是因為在影像處理裡面,如果是做到real-time的話 1秒要有30張frames,那就是一張frames要0.03333秒 C/C++中時間相關函數主要有兩個:clock()跟time() 這兩個函數都是在<time.h>裡面,使用的話要記得引用 clock() 函數定義 The C library function cloc