小菜毛毛技術分享
與大家共同成長
BlogJava
::
首頁
::
聯系
::
聚合
::
管理
164 Posts :: 141 Stories :: 94 Comments :: 0 Trackbacks
常用鏈接
我的隨筆
我的評論
我的參與
最新評論
留言簿
(15)
給我留言
查看公開留言
查看私人留言
我參與的團隊
隨筆分類
andriod(23)
appfuse 集成J2EE框架(2)
eclipse 插件相關(3)
English(5)
FckEditor(2)
FLEX(9)
google app engine(2)
googleAnalytics(1)
htmlunit(1)
httpclient(1)
IDE(8)
java基礎運用(11)
java定時器(5)
jQuery(1)
JSON-LIB快速入門(1)
JSTL(3)
LOG4J(1)
maven(1)
mysql(1)
servlet(3)
SMC(stateMachine)(1)
spring 框架(1)
struts2(1)
SVN(1)
tiles 框架(1)
velocity(1)
webservice(6)
XML(3)
協議相關(3)
應用服務器(5)
性能優化(3)
技術族譜:軟件開發相關知識體系的整理心得(圖)(1)
搜索引擎(5)
操作系統(4)
數據建模(8)
電信綜合施工調度系統-剖析(2)
規則引擎(1)
計算機基礎(1)
設計模式(2)
資源(2)
集群與負載均衡(2)
面試(37)
隨筆檔案
2011年5月 (1)
2011年2月 (1)
2011年1月 (2)
2010年12月 (7)
2010年11月 (18)
2010年10月 (7)
2010年9月 (8)
2010年8月 (4)
2010年7月 (5)
2010年6月 (4)
2010年5月 (7)
2010年4月 (8)
2010年3月 (24)
2010年2月 (12)
2010年1月 (7)
2009年12月 (2)
2009年11月 (3)
2009年10月 (2)
2009年9月 (8)
2009年8月 (15)
2009年7月 (13)
2009年6月 (2)
2009年5月 (4)
文章分類
AJAX(9)
ANT(4)
EXTJS(15)
HTML+div+css實踐(16)
J2EE相關技術與框架(26)
java基礎及其原理(9)
JBPM(9)
JSTL(2)
rbac 權限管理模型(1)
webservice(1)
XML(3)
個人日志(4)
技術類英文文檔翻譯學習(1)
數據庫(33)
數據結構
權限管理(2)
電信行業(2)
文章檔案
2010年9月 (1)
2010年5月 (1)
2010年3月 (3)
2010年2月 (12)
2010年1月 (17)
2009年12月 (9)
2009年11月 (2)
2009年10月 (1)
2009年9月 (2)
2009年8月 (17)
2009年7月 (9)
2009年6月 (25)
2009年5月 (42)
新聞檔案
2010年2月 (1)
收藏夾
TEST(2)
搜索
最新評論
1.?re: Apache Commons fileUpload實現文件上傳
good
--未來不是夢
2.?re: js操作html的table,包括添加行,添加列,刪除行,刪除列
共和國分隔符
--菊花菊花姐
3.?re: WAP網站可以用Google Analytics統計分析流量
請問ga中對wap站的跟蹤在哪里可以查看,我操作的方式和pc站一樣,都是把網址輸入,就出來一段網址,這樣似乎不對,是嗎,前輩
--ga菜鳥
4.?re: Velocity模板(VM)語言介紹
博主寫的很詳細,學習啦
--winclpt
5.?re: 利用Java編寫簡單的WebService實例[未登錄]
11
--111
閱讀排行榜
1.?Velocity模板(VM)語言介紹(30220)
2.?JSTL對Map集合的操作(21137)
3.?htmlunit 示例(16683)
4.?利用Java編寫簡單的WebService實例(13403)
5.?webservice和soap原理(12103)
評論排行榜
1.?Flex Builder 3 Help 中文版 (CHM/PDF)下載(19)
2.?aptana漢化(3)
3.?WAP網站可以用Google Analytics統計分析流量(2)
4.?Android中添加Admob廣告(轉(2)
5.?axis2 java.lang.reflect.InvocationTargetException (2)
交換兩個變量的值,不使用第三個變量
字體大小:
大
中
小
正文
交換兩個變量的值,不使用第三個變量
(2009-09-16 18:19:18)
標簽:
雜談
分類:
計算機
通常我們的做法是(尤其是在學習階段):定義一個新的變量,借助它完成交換。代碼如下:
int a,b;
a=10; b=15;
int t;
t=a; a=b; b=t;
這種算法易于理解,特別適合幫助初學者了解計算機程序的特點,是賦值語句的經典應用。在實際軟件開發當中,此算法簡單明了,不會產生歧義,便于程序員之間的交流,一般情況下碰到交換變量值的問題,都應采用此算法(以下稱為標準算法)。
上面的算法最大的缺點就是需要借助一個臨時變量。那么不借助臨時變量可以實現交換嗎?答案是肯定的!這里我們可以用三種算法來實現:1)算術運算;2)指針地址操作;3)位運算。
1) 算術運算
簡單來說,就是通過普通的+和-運算來實現。代碼如下:
int a,b;
a=10;b=12;
a=b-a; //a=2;b=12
b=b-a; //a=2;b=10
a=b+a; //a=10;b=10
通過以上運算,a和b中的值就進行了交換。表面上看起來很簡單,但是不容易想到,尤其是在習慣標準算法之后。
它的原理是:把a、b看做數軸上的點,圍繞兩點間的距離來進行計算。
具體過程:第一句“a=b-a”求出ab兩點的距離,并且將其保存在a中;第二句“b=b-a”求出a到原點的距離(b到原點的距離與ab兩點距離之差),并且將其保存在b中;第三句“a=b+a”求出b到原點的距離(a到原點距離與ab兩點距離之和),并且將其保存在a中。完成交換。
此算法與標準算法相比,多了三個計算的過程,但是沒有借助臨時變量。(以下稱為算術算法)
2) 指針地址操作
因為對地址的操作實際上進行的是整數運算,比如:兩個地址相減得到一個整數,表示兩個變量在內存中的儲存位置隔了多少個字節;地址和一個整數相加即“a+10”表示以a為基地址的在a后10個a類數據單元的地址。所以理論上可以通過和算術算法類似的運算來完成地址的交換,從而達到交換變量的目的。即:
int *a,*b; //假設
*a=new int(10);
*b=new int(20); //&a=0x00001000h,&b=0x00001200h
a=(int*)(b-a); //&a=0x00000200h,&b=0x00001200h
b=(int*)(b-a); //&a=0x00000200h,&b=0x00001000h
a=(int*)(b+int(a)); //&a=0x00001200h,&b=0x00001000h
通過以上運算a、b的地址真的已經完成了交換,且a指向了原先b指向的值,b指向原先a指向的值了嗎?上面的代碼可以通過編譯,但是執行結果卻令人匪夷所思!原因何在?
首先必須了解,操作系統把內存分為幾個區域:系統代碼/數據區、應用程序代碼/數據區、堆棧區、全局數據區等等。在編譯源程序時,常量、全局變量等都放入全局數據區,局部變量、動態變量則放入堆棧區。這樣當算法執行到“a=(int*)(b-a)”時,a的值并不是0x00000200h,而是要加上變量a所在內存區的基地址,實際的結果是:0x008f0200h,其中0x008f即為基地址,0200即為a在該內存區的位移。它是由編譯器自動添加的。因此導致以后的地址計算均不正確,使得a,b指向所在區的其他內存單元。再次,地址運算不能出現負數,即當a的地址大于b的地址時,b-a<0,系統自動采用補碼的形式表示負的位移,由此會產生錯誤,導致與前面同樣的結果。
有辦法解決嗎?當然!以下是改進的算法:
if(a<b)
{
a=(int*)(b-a);
b=(int*)(b-(int(a)&0x0000ffff));
a=(int*)(b+(int(a)&0x0000ffff));
}
else
{
b=(int*)(a-b);
a=(int*)(a-(int(b)&0x0000ffff));
b=(int*)(a+(int(b)&0x0000ffff));
}
算法做的最大改進就是采用位運算中的與運算“int(a)&0x0000ffff”,因為地址中高16位為段地址,后16位為位移地址,將它和0x0000ffff進行與運算后,段地址被屏蔽,只保留位移地址。這樣就原始算法吻合,從而得到正確的結果。
此算法同樣沒有使用第三變量就完成了值的交換,與算術算法比較它顯得不好理解,但是它有它的優點即在交換很大的數據類型時,它的執行速度比算術算法快。因為它交換的時地址,而變量值在內存中是沒有移動過的。(以下稱為地址算法)
3) 位運算
通過異或運算也能實現變量的交換,這也許是最為神奇的,請看以下代碼:
int a=10,b=12; //a=1010^b=1100;
a=a^b; //a=0110^b=1100;
b=a^b; //a=0110^b=1010;
a=a^b; //a=1100=12;b=1010;
此算法能夠實現是由異或運算的特點決定的,通過異或運算能夠使數據中的某些位翻轉,其他位不變。這就意味著任意一個數與任意一個給定的值連續異或兩次,值不變。
即:a^b^b=a。將a=a^b代入b=a^b則得b=a^b^b=a;同理可以得到a=b^a^a=b;輕松完成交換。
以上三個算法均實現了不借助其他變量來完成兩個變量值的交換,相比較而言算術算法和位算法計算量相當,地址算法中計算較復雜,卻可以很輕松的實現大類型(比如自定義的類或結構)的交換,而前兩種只能進行整形數據的交換(理論上重載“^”運算符,也可以實現任意結構的交換)。
介紹這三種算法并不是要應用到實踐當中,而是為了探討技術,展示程序設計的魅力。從中可以看出,數學中的小技巧對程序設計而言具有相當的影響力,運用得當會有意想不到的神奇效果。而從實際的軟件開發看,標準算法無疑是最好的,能夠解決任意類型的交換問題
posted on 2009-12-02 14:55
小菜毛毛
閱讀(7547)
評論(0)
編輯
收藏
所屬分類:
java基礎運用
、
面試
新用戶注冊
刷新評論列表
只有注冊用戶
登錄
后才能發表評論。
網站導航:
博客園
IT新聞
Chat2DB
C++博客
博問
管理
相關文章:
java sax 解析 實例
java反射詳解
java中文漢字排序
javac -classpath的使用
JAVAC 命令詳解(http://www.cnblogs.com/jeffchen/archive/2008/01/16/1041783.html)
Java虛擬機參數詳解
用java實現comet,基于 HTTP長連接的實現,用于從服務端實時發送信息到客戶端
字符,字節和編碼
交換兩個變量的值,不使用第三個變量
JAVA 書籍比較全的網站 http://ajava.org/book/
Copyright @ 小菜毛毛
Powered by:
.Text
and
ASP.NET
Theme by:
.NET Monster
主站蜘蛛池模板:
成年人在线免费观看
|
四虎永久免费地址在线观看
|
无码天堂亚洲国产AV
|
亚洲综合亚洲国产尤物
|
久久国产成人亚洲精品影院
|
青青视频观看免费99
|
亚洲国产精品免费视频
|
国产一二三四区乱码免费
|
亚洲AV日韩AV无码污污网站
|
亚洲三级中文字幕
|
亚洲三级在线免费观看
|
亚洲嫩草影院在线观看
|
亚洲综合男人的天堂色婷婷
|
国产亚洲精品观看91在线
|
久久精品国产亚洲麻豆
|
亚洲国产精品VA在线观看麻豆
|
亚洲黄色免费电影
|
亚洲男人天堂av
|
亚洲va成无码人在线观看
|
亚洲午夜精品一区二区公牛电影院
|
久久精品国产亚洲精品2020
|
亚洲国产日韩一区高清在线
|
亚洲春黄在线观看
|
亚洲日韩一区精品射精
|
野花视频在线官网免费1
|
一区二区免费电影
|
免费视频成人片在线观看
|
亚洲美女视频免费
|
免费无遮挡无码永久在线观看视频
|
最新国产乱人伦偷精品免费网站
|
在线免费观看h片
|
国内免费高清在线观看
|
精品亚洲一区二区三区在线观看
|
精品亚洲永久免费精品
|
亚洲香蕉久久一区二区
|
美女视频黄a视频全免费网站一区
|
好紧我太爽了视频免费国产
|
最新中文字幕免费视频
|
亚洲AV第一页国产精品
|
欧美亚洲精品一区二区
|
久久精品人成免费
|