最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 不使用第三方變量交換兩個變量值的四種方法詳解

 更新時間:2021年12月09日 15:22:53   作者:阿Q說代碼  
這篇文章主要介紹了四種不使用第三方變量交換兩個變量值的方法。文中對于四種方法進(jìn)行了詳細(xì)的分析,需要的小伙伴們可以跟隨小編一起學(xué)習(xí)一下

哈嘍,大家好,我是阿Q。前幾天有個小伙伴去面試,被面試官的一個問題勸退了:請說出幾種不使用第三方變量交換兩個變量值的方法。

問題有點繞,好不容易縷清了面試官的問題,卻發(fā)現(xiàn)答不上來。一時間尷尬無比,只能硬著頭皮說不會。

遇到交換變量值的問題,通常我們的做法是:定義一個新的變量,借助它完成交換。

代碼如下:

t = a;
a = b; 
b = t;

但問題的重點是“不使用第三方變量”,那就變得“可愛”起來了。思考過后,拋出以下四種方法來解決該問題:

  • 變量本身交換數(shù)值;
  • 算術(shù)運算;
  • 指針地址操作;
  • 位運算;

變量本身交換數(shù)值

b = (a + b) - (a = b);

首先執(zhí)行 a + b 操作,然后將 b 賦值給 a,則 b = a + b - b = a,這就完成了 ab 的互換操作。

算術(shù)運算

如圖所示:

OA = a;

OB = b;

AB = b - a;

首先我們把 AB 之間的距離 b - a 賦值給 a,此時 AB = a, OB = b 。

由于要達(dá)到 ab 交換的目的,所以 OA 要等于 b,而此時 OA 的距離為 b - a ,所以得將 b - a 賦值給 b ,此時 OA = b, AB = a 。

很容易從圖中看出,OB 的距離為 b + a,所以我們只需要將 b + a 賦值給 a 就可以完成兩者的交換了。

綜上所述,我們的步驟為

int a = 10;
int b = 15;
a = b - a; //b=15;a=5;
b = b - a; //b=10;a=5;
a = b + a; //b=10;a=15;

該算法只能用于整型類型。

指針地址操作

我們可以把 a 和 b 想象為內(nèi)存中的地址值,假設(shè) a 為 0x01ff5e70 ,b 為 0x01ff5e90 ,而 b - a 表示兩個變量在內(nèi)存中的儲存位置隔了多少個字節(jié)。所以我們理論上也可以按算術(shù)運算的邏輯來交換兩個變量的值。

代碼如下(此處是 c 語言):

//其中 a 和 b 都是指針變量,里邊存儲著10和20的地址
int *a = new int(10); //a=0x01ff5e70 ,此處代表a中存儲的地址
int *b = new int(20); //b=0x01ff5e90 ,此處代表b中存儲的地址

//指針變量相減得到20和10的地址間隔了多少個字節(jié),然后轉(zhuǎn)為指針變量
a = (int*)(b-a); 	//b=0x01ff5e90;a=0x8
b = (int*)(b-a); 	//b=0x01ff5e70;a=0x8
a=(int*)(b+long(a));//b=0x01ff5e70;a=0x01ff5e90

b - a = 0x01ff5e90 - 0x01ff5e70 = 0x20,0x20 轉(zhuǎn)換為十進(jìn)制為 32 位,因為一個 int 占4位,所以這里是 0x8 。

以上只是理論狀態(tài)下的執(zhí)行過程,如果直接執(zhí)行是不能實現(xiàn)交換的。因為上邊的代碼忽略了一個問題:代碼編譯之后,變量都是存在內(nèi)存中的,而內(nèi)存區(qū)都會存在基地址。

基地址可以理解為某塊內(nèi)存的起點。上邊的數(shù)據(jù)都是在基地址的基礎(chǔ)上做了偏移。

變量的地址 = 變量的基地址 + 變量的偏移地址

當(dāng)我們進(jìn)行 b - a 操作的時候,得到結(jié)果為 8 ,然后轉(zhuǎn)化為指針變量的時候就會給 8 自動添加基地址,此時的結(jié)果就不是 0x8 了,所以會導(dǎo)致結(jié)果錯誤。

另外,地址運算不能出現(xiàn)負(fù)數(shù),即當(dāng) a 的地址大于 b 的地址時,b - a < 0 ,系統(tǒng)自動采用補(bǔ)碼的形式表示負(fù)的位移,也會產(chǎn)生錯誤。

為了解決這個問題,我們只需要保證 b - a 得到的結(jié)果不受基地址的影響即可,所以給出以下解決方案。

int *a = new int(10);
int *b = new int(20); 
cout << a << "`````";
cout << b << "`````";
if(a < b){
	a = (int*)(b-a); 
	cout << a << "`````";

	b=(int*)(b-(long(a)&0x0000ffff));
	cout << b << "`````";
	
	a=(int*)(b+long(a));
	cout << a << "`````";
} else {
	b = (int*)(a-b); 
	cout << b << "`````";

	a=(int*)(a-(long(b)&0x0000ffff));
	cout << a << "`````";
	
	b=(int*)(a+long(b));
	cout << b << "`````";
}

執(zhí)行結(jié)果:

0x8dbe70`````0x8dbe90`````0x8`````0x8dbe70`````0x8dbe90`````

看到這,不知道大家是否真的看懂了。反正我第一次看到這兒時,感覺非常清晰(其實完全沒有理解),第二次看的時候懵逼了,完全不懂,所以還得大家仔細(xì)思考一下才行。

b=(int*)(b-(long(a)&0x0000ffff)); 指令的精妙之處就在于采用了位運算中的與運算,將 a 和 0x0000ffff 進(jìn)行與運算后,b - a 的基地址計算結(jié)果被屏蔽,只保留了偏移地址的計算結(jié)果,也就是我們需要的字節(jié)數(shù)。

在交換很大的數(shù)據(jù)類型時,該方法執(zhí)行速度比算術(shù)算法快。因為它交換的是地址,而變量值在內(nèi)存中是沒有移動過的。

位運算

既然上邊用到了位運算,那我們再說一種直接通過“異或“完成交換的方法。

簡單介紹一下異或的規(guī)則:

  • 如果a、b兩個值不相同,則異或結(jié)果為1;
  • 如果a、b兩個值相同,異或結(jié)果為0。

代碼如下

int a=10, b=12;//二進(jìn)制:a=1010;b=1100;
a = a^b;//a=0110;b=1100
b = a^b;//a=0110;b=1010
a = a^b;//a=1100;b=1010
System.out.println("a="+ a +",b="+ b);

執(zhí)行結(jié)果

a=12,b=10

異或運算能夠使數(shù)據(jù)中的某些位翻轉(zhuǎn),其他位不變。這就意味著任意一個數(shù)與任意一個給定的值連續(xù)異或兩次,值不變。

簡單總結(jié)

以上四種方法均實現(xiàn)了不借助第三方變量來完成兩個變量值的交換:

  • 算術(shù)運算和位運算計算量相當(dāng),只能進(jìn)行整形數(shù)據(jù)的交換;
  • 地址運算中計算較復(fù)雜,可以很輕松的實現(xiàn)大類型(比如自定義的類或結(jié)構(gòu))的交換;
  • 理論上重載 “^” 運算符,也可以實現(xiàn)任意結(jié)構(gòu)的交換;?

到此這篇關(guān)于Java 不使用第三方變量交換兩個變量值的四種方法詳解的文章就介紹到這了,更多相關(guān)Java 變量值交換內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入理解Java8雙冒號::的使用

    深入理解Java8雙冒號::的使用

    這篇文章主要介紹了深入理解Java8雙冒號::的使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • 關(guān)于kafka發(fā)送消息的三種方式總結(jié)

    關(guān)于kafka發(fā)送消息的三種方式總結(jié)

    這篇文章主要介紹了關(guān)于kafka發(fā)送消息的三種方式總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Java世界時區(qū)自動計算及時間生成方法詳解

    Java世界時區(qū)自動計算及時間生成方法詳解

    這篇文章主要為大家詳細(xì)介紹了Java中世界時區(qū)自動計算及時間生成的方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-12-12
  • SpringBoot環(huán)境搭建及第一個程序運行(小白教程)

    SpringBoot環(huán)境搭建及第一個程序運行(小白教程)

    這篇文章主要介紹了SpringBoot環(huán)境搭建及第一個程序運行,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Java實現(xiàn)圖書管理系統(tǒng)的示例代碼

    Java實現(xiàn)圖書管理系統(tǒng)的示例代碼

    這篇文章將通過Java實現(xiàn)一個簡答的圖書管理系統(tǒng),本圖書管理系統(tǒng)用對象數(shù)組的方式來提供操作方法,比較特別,建議新手學(xué)習(xí),這對理解Java面向?qū)ο笥泻艽髱椭?/div> 2022-11-11
  • spring聲明式事務(wù)@Transactional底層工作原理

    spring聲明式事務(wù)@Transactional底層工作原理

    這篇文章主要為大家介紹分析spring聲明式事務(wù)@Transactional底層工作原理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-02-02
  • java基本事件處理機(jī)制解析

    java基本事件處理機(jī)制解析

    這篇文章主要介紹了java基本事件處理機(jī)制解析,?Java事件處理機(jī)制是一種用于處理用戶交互和系統(tǒng)事件的編程模型,它基于事件驅(qū)動的思想,通過監(jiān)聽和響應(yīng)事件來實現(xiàn)程序的交互性和動態(tài)性,需要的朋友可以參考下
    2023-10-10
  • Java rmi遠(yuǎn)程方法調(diào)用基本用法解析

    Java rmi遠(yuǎn)程方法調(diào)用基本用法解析

    這篇文章主要介紹了Java rmi遠(yuǎn)程方法調(diào)用基本用法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-05-05
  • Java8新特性:函數(shù)式編程

    Java8新特性:函數(shù)式編程

    Java8最新引入函數(shù)式編程概念,該項技術(shù)可以大大提升編碼效率,本文會對涉及的對象等進(jìn)行兩種方法的對比,對新技術(shù)更直白的看到變化,更方便學(xué)習(xí)
    2021-06-06
  • Java轉(zhuǎn)義字符詳細(xì)介紹

    Java轉(zhuǎn)義字符詳細(xì)介紹

    這篇文章主要介紹了Java轉(zhuǎn)義字符的相關(guān)資料,包括換行符、回車符、換頁符、退格符、空字符、空格、制表符、單引號、雙引號、反斜杠以及八進(jìn)制和十六進(jìn)制字符,通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-12-12

最新評論

高雄县| 海南省| 龙山县| 定结县| 大埔区| 荔波县| 潮州市| 内丘县| 玛多县| 满城县| 溧水县| 长岛县| 新宁县| 墨竹工卡县| 公安县| 平乐县| 福泉市| 雅江县| 开江县| 云梦县| 竹山县| 庄河市| 怀化市| 饶河县| 高尔夫| 焉耆| 高尔夫| 翼城县| 巨鹿县| 屏东县| 云浮市| 彰武县| 瑞丽市| 防城港市| 雷州市| 买车| 安龙县| 伊春市| 新田县| 长宁县| 彭州市|