国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

一種二叉樹非遞歸遍歷算法的C語言實(shí)現(xiàn)

2014-02-25 11:09:43龔佳袁赟劉遠(yuǎn)軍
電腦知識與技術(shù) 2014年1期
關(guān)鍵詞:二叉樹

龔佳 袁赟 劉遠(yuǎn)軍

摘要:針對二叉樹的鏈?zhǔn)酱鎯Y(jié)構(gòu),分析了二叉樹的各種遍歷算法,探討了遞歸算法的遞推消除問題,提出了一種改進(jìn)的非遞歸遍歷算法并用C語言予以實(shí)現(xiàn)。

關(guān)鍵詞:二叉樹;遍歷算法;非遞歸;C語言實(shí)現(xiàn)

中圖分類號:TP301 文獻(xiàn)標(biāo)識碼:A 文章編號:1009-3044(2014)01-0223-03

1 概述

樹形結(jié)構(gòu)是一種非常常見的數(shù)據(jù)結(jié)構(gòu),而二叉樹又是其中最重要的一種樹形結(jié)構(gòu)。二叉樹的遍歷是指按照一定的規(guī)則和次序?qū)⒍鏄渲械拿恳粋€結(jié)點(diǎn)都訪問一次,既不能重復(fù),也不能漏掉。一般而言,對二叉樹的遍歷有前序遍歷、中序遍歷、后序遍歷和按層遍歷等幾種方式。在具體的算法設(shè)計(jì)上,以上遍歷方式一般采取遞歸算法來實(shí)現(xiàn),該文將探討采用非遞歸算法來實(shí)現(xiàn)二叉樹的遍歷。

2 二叉樹的數(shù)據(jù)結(jié)構(gòu)描述

二叉樹作為一種非線性結(jié)構(gòu),每個結(jié)點(diǎn)最多有一個雙親結(jié)點(diǎn)和兩個子結(jié)點(diǎn)。二叉樹可以采用順序存儲結(jié)構(gòu)和鏈?zhǔn)酱鎯Y(jié)構(gòu)。對于完全二叉樹而言,采用順序存儲是非常方便并且節(jié)省空間的,但是對于大部分的非完全二叉樹而言,采用順序存儲將導(dǎo)致空間浪費(fèi)嚴(yán)重且結(jié)構(gòu)混亂、效率低下。因此,更多的時候,大家都更愿意用鏈?zhǔn)酱鎯Y(jié)構(gòu)來表示二叉樹,這樣結(jié)構(gòu)更加清晰,尤其是對于左右子樹的描述和雙親節(jié)點(diǎn)的描述更加方便。該文中擬采用鏈?zhǔn)浇Y(jié)構(gòu)來表示二叉樹。用鏈?zhǔn)酱鎯Y(jié)構(gòu)來表示二叉樹,一個結(jié)點(diǎn)至少由3個域組成,即數(shù)據(jù)域、左子結(jié)點(diǎn)域和右子結(jié)點(diǎn)域(如圖1所示)。

3 二叉樹的遍歷及遞歸算法實(shí)現(xiàn)

3.1 二叉樹的遍歷

二叉樹的遍歷就是一個不漏的訪問樹中的每個結(jié)點(diǎn),同時也不能重復(fù)。所謂“訪問”,就是指對結(jié)點(diǎn)的數(shù)據(jù)域進(jìn)行某種操作,比如說讀取、刪除、更新、求該節(jié)點(diǎn)深度等等。對于二叉樹中的任意一個部分,都可以把它看作三部分,根節(jié)點(diǎn)、左子樹、右子樹,我們用D表示訪問跟結(jié)點(diǎn),用L表示遍歷左子樹,用R表示遍歷右子樹,則共有以下6種遍歷方式[1]。

1) DLR:先訪問根結(jié)點(diǎn),再遍歷左子樹,然后遍歷右子樹;

2) DRL:先訪問根結(jié)點(diǎn),再遍歷右子樹,然后遍歷左子樹;

3) LDR:先遍歷左子樹,再訪問根結(jié)點(diǎn),然后遍歷右子樹;

4) RDL:先遍歷右子樹,再訪問根結(jié)點(diǎn),然后遍歷左子樹;

5) LRD:先遍歷左子樹,再遍歷右子樹,然后訪問根結(jié)點(diǎn);

6) RLD:先遍歷右子樹,再遍歷左子樹,然后訪問根結(jié)點(diǎn)。

為了方便和規(guī)范化,通常都規(guī)定遍歷順序是先左后右的,所以以上6種遍歷算法,經(jīng)常采用的是DLR(前序遍歷)、LDR(中序遍歷)和LRD(后序遍歷)。在有些情況下,特別是對于完全二叉樹的情況,還可以采用按層遍歷的方式。該文將以中序遍歷(LDR)為例,分析并探討LDR的遞歸算法和非遞歸算法。

3.2 LDR的遞歸算法

對于中序遍歷(LDR)而言,在二叉樹的任何一個結(jié)點(diǎn),都執(zhí)行以下步驟:

1) 判斷是否為空,如果為空,遍歷結(jié)束;

2) 按中序遍歷左子樹;

3) 訪問根結(jié)點(diǎn);

4) 按中序遍歷右子樹。

其中,步驟(1)是結(jié)束條件,步驟(2)和步驟(4)則是一個典型的遞歸調(diào)用過程。依據(jù)這個算法思想,寫出C語言代碼如下:

void InOrder(Tnode root)

//中序遍歷二叉樹,root 表示二叉樹或當(dāng)前子樹的根結(jié)點(diǎn)指針

{if(root!=NULL)

{InOrder(root→L_child);

//中序遍歷左子樹

visit(root→Data);

//訪問當(dāng)前根節(jié)點(diǎn)的數(shù)據(jù)域

InOrder(root→R_child);

//中序遍歷右子樹

}}

其中,visit( )為訪問函數(shù),對二叉樹或當(dāng)前子樹的根結(jié)點(diǎn)的數(shù)據(jù)域進(jìn)行訪問,訪問方式可以是讀取數(shù)據(jù)、刪除、修改等等各種操作,這里不再贅述。

4 二叉樹的非遞歸算法

4.1 遞歸算法的缺點(diǎn)與采用非遞歸算法的必要性

遞歸算法是一種化繁為簡,把復(fù)雜問題分解成若干簡單問題的求解方式,他對某些復(fù)雜問題的求解是非常有效的[2]。但是,遞歸算法實(shí)際上是在頂層把要解決的問題往后推,然后等到遞推到最底層,等解決完一個子問題后再往后回溯遞歸,再返回到最頂層,同時,遞歸算法的執(zhí)行需要系統(tǒng)提供隱式棧來支持,這必然會導(dǎo)致遞歸算法的執(zhí)行效率較低。并且在以下兩種情況下,必須要用非遞歸算法來代替遞歸算法。

1) 某些語言環(huán)境不支持遞歸。如Fortran語言中無遞歸機(jī)制。

2) 遞歸算法是一次性執(zhí)行的,中間過程對用戶是不可見的,而有時需要設(shè)置斷點(diǎn),調(diào)試程序,或者有其他的特殊要求時,不能采用遞歸算法[1,2]。

4.2 中序遍歷的非遞歸算法

首先,我們要分析遞歸算法中進(jìn)層和退層時的操作。

遞歸進(jìn)層時系統(tǒng)需要做三件事:

1) 保留本層參數(shù)與返回地址(將所有的實(shí)參、返回地址等信息傳遞給被調(diào)用函數(shù)保存);

2) 給下層參數(shù)賦值(為被調(diào)用函數(shù)的局部變量分配存儲區(qū));

3) 將程序轉(zhuǎn)移到被調(diào)函數(shù)的入口。

遞歸退層時系統(tǒng)需要做三件事:

1) 保存被調(diào)函數(shù)的計(jì)算結(jié)果;

2) 恢復(fù)上層參數(shù)(釋放被調(diào)函數(shù)的數(shù)據(jù)區(qū));

3) 依照被調(diào)函數(shù)保存的返回地址,將控制轉(zhuǎn)移回調(diào)用函數(shù)。

同時考慮到遞歸調(diào)用算法需要系統(tǒng)提供隱式棧來執(zhí)行,所以在將復(fù)雜的遞歸算法改寫成非遞歸算法時,必須引入棧。下面給出基于棧的二叉樹中序遍歷非遞歸算法的C語言實(shí)現(xiàn):

void InOrder(Tnode root)

//中序遍歷二叉樹的非遞歸算法

{ int top=0;

p=root;

L1:if(p!=NULL) //遍歷左子樹

{ top+=2;

if(top>m) return; //棧滿退出

s[top-1]=p; //本層參數(shù)進(jìn)棧

s[top]=L2; //返回地址進(jìn)棧

p=p→L_child; //給下層參數(shù)賦值

goto L1; //轉(zhuǎn)向開始

L2: Visit(p→Data); //訪問根

top+=2;

if(top>m) return; //棧滿溢出

s[top-1]=p; //遍歷右子樹

s[top]=L3;

p=p→R_child;

goto L1;}

L3:if(top!=0)

{ addr=s[top];

p=s[top-1]; //取出返回地址

top=top-2; //退出本層參數(shù)

goto addr;}}

5 結(jié)束語

二叉樹的遍歷是進(jìn)行二叉樹其他操作的基礎(chǔ),如二叉樹的線索化、二叉樹的構(gòu)造、二叉樹的還原等等,都要用到二叉樹的遍歷算法。二叉樹的遍歷算法可以采用遞歸算法,也可以采用非遞歸算法。遞歸算法具有簡潔明了的優(yōu)點(diǎn),程序代碼短,容易理解,但是遞歸算法的執(zhí)行效率往往不高,而非遞歸算法雖然語法上稍顯繁瑣,但是卻有著執(zhí)行效率高、應(yīng)用環(huán)境廣的特點(diǎn)。

參考文獻(xiàn):

[1] 陳衛(wèi)衛(wèi), 王慶瑞. 數(shù)據(jù)結(jié)構(gòu)與算法[M]. 北京:高等教育出版社, 2010.

[2] 耿國華. 數(shù)據(jù)結(jié)構(gòu)——用C語言描述[M]. 北京:高等教育出版社, 2011.

猜你喜歡
二叉樹
CSP真題——二叉樹
電腦報(2022年37期)2022-09-28 05:31:07
基于雙向二叉樹的多級菜單設(shè)計(jì)及實(shí)現(xiàn)
電子制作(2022年16期)2022-09-23 01:39:54
二叉樹創(chuàng)建方法
數(shù)據(jù)結(jié)構(gòu)與虛擬儀器結(jié)合教學(xué)案例
——基于二叉樹的圖像加密
基于隊(duì)列的任意二叉樹層次問題算法設(shè)計(jì)
一種由層次遍歷和其它遍歷構(gòu)造二叉樹的新算法
一種由遍歷序列構(gòu)造二叉樹的改進(jìn)算法
論復(fù)雜二叉樹的初始化算法
河南科技(2014年24期)2014-02-27 14:20:01
基于遍歷序列重構(gòu)二叉結(jié)構(gòu)樹的分析
基于單鏈表的二叉樹非遞歸遍歷算法
通海县| 墨竹工卡县| 扎鲁特旗| 建昌县| 天柱县| 东平县| 永靖县| 嵩明县| 定南县| 五峰| 安远县| 镇远县| 陈巴尔虎旗| 苗栗市| 闸北区| 灵台县| 玉环县| 田东县| 紫阳县| 抚顺县| 大石桥市| 定远县| 翼城县| 塔河县| 海兴县| 简阳市| 五莲县| 高尔夫| 天柱县| 丹阳市| 阿拉尔市| 新丰县| 科技| 宁强县| 宁都县| 镇巴县| 镇江市| 华蓥市| 拉萨市| 平安县| 聂拉木县|