資料結構 二叉樹遍歷 求深度C語言的簡單實現

2021-08-11 13:44:23 字數 3429 閱讀 8508

github:(

當年在學資料結構的時候,要求自己把**給實現一遍。在實現完線性表,棧和佇列之後,到了樹這章實現**確實有點難以入手,原因大家都懂,有遞迴。

樹的這章,比較重要的**是遞迴遍歷以及求深度,先弄明白這兩段**再去看關於樹的相關**就會容易很多。 這裡提個小小意見,遞迴很抽象,最好能畫個樹的圖,然後按照程式**在樹的圖中給畫出來,最好能debug一遍。

所以我給出這相關**。希望可以幫助大家。

#include typedef struct bitnode*bitree, bitnode;

void preorder(bitree t); //前序遍歷

void inorder(bitree t); //中序遍歷

void postorder(bitree t); //後序遍歷

void createbitree(bitree* t); //建立樹

int depth(bitree t);

int main()

void createbitree(bitree* t)

if (ch == '#')

else

}void preorder(bitree t)

}void inorder(bitree t)

}void postorder(bitree t)

}int depth(bitree t) else

else }}

這裡我建議你開啟兩個視窗來講下面的解釋和**一一對應來看。

line 1 匯入標頭檔案

line 3~6 二叉樹的資料結構,乙個資料域,兩個孩子結點的指標域

line 8~12 二叉樹的建立(根據先序遍歷序列),先序遍歷,中序遍歷,後序遍歷,求深度

line 14~29 在main函式對這些函式測試

line 31~48 根據先序遍歷序列進行建立樹,這個可以先不用看具體的實現。不過如果你像看的化,我還是簡單說下他是怎麼實現的。這個函式每次接收乙個字元,然後按照先序遍歷呼叫函式,根據字元(是資料還是空指標,空指標用』#'表示),如果是空指標就將傳進來的指標置為空,如果不是空指標,則建立乙個新的結點。

line 50~56 以先序遍歷的方式遍歷樹,先訪問根結點printf("%c ", t->data);,再訪問左子樹preorder(t->lchild);,右子樹preorder(t->lchild);,這裡為什麼是左子樹右子樹,我想這就是遞迴的魅力了。 接下來我根據下面這張圖,對先序遍歷的過程(只對a結點及左子樹的,不然要寫太多了,你先看,記得對照圖看)做個說明。(圖中的灰色結點『#』平常不會畫出來,這裡我為了方便,才畫出來的)

其實遞迴呼叫會形成乙個遞迴圖,而這個遞迴圖就是一棵樹。所以你會發現先序遍歷是有且只會一次訪問結點(跟圖的不一樣,圖還要設乙個訪問陣列,來判斷當前結點是否被訪問過)。

上面這張圖,我把流向都給畫出來了,其中的數字代表第幾次被訪問。

首先我們會傳入根結點的指標到先序遍歷中(在main函式中呼叫的,line 18那裡),也是圖中的a結點,所以你看到圖中的1,那個代表是a結點是第乙個訪問。然後我們用printf("%c ", t->data);把a結點的值給列印出來(算是a結點的訪問,你也可以用a結點做別的事,但是這裡為了舉例,用了列印來表示訪問)。

訪問完a結點後,preorder(t->lchild);我們會執行這個語句,a函式因為沒執行完又去執行別的函式了,所以入函式棧裡,等它執行完的這個函式執行完畢後,a函式才會繼續執行剩下的preorder(t->rchild);

那我們可以看到a結點的左孩子是b,所以我們會訪問b,所以b是第2次訪問的結點(圖中標2)。

繼續,b結點訪問完,又呼叫了preorder(t->lchild);,同樣的,b函式因為沒執行完又去執行別的函式了,所以入函式棧裡,我們現在棧裡有兩個函式,乙個是訪問a結點時的那個函式,乙個是b結點時的那個函式。

繼續,b結點的左孩子是空,我在圖中標記為#,t為空時,不滿足if (t != null)所以,函式執行完畢,所以我們會出函式棧,把b給彈出來,然後把b繼續執行剛才未執行的語句。注意:這裡我在圖中把b的左孩子那個也寫了個數字3,說明我們是第三次訪問這個結點的,不過我們不做任何訪問的操作(把它列印出來)。

我們回到訪問b結點的那個函式,我們已經執行完preorder(t->lchild);(就是上面那個步驟),程式會繼續執行preorder(t->rchild);,這時b還沒有執行完畢,b壓入棧。這時棧有訪問a和b兩個結點的函式。

同樣的,跟b結點的左孩子一樣,不滿足if (t != null)所以,函式執行完畢,所以我們會出函式棧,把訪問b的那個函式給彈出來,然後繼續執行剛才未執行完的**。這時函式棧就a了。

這時訪問的b結點的函式沒有其它語句了,b結點的函式執行完畢,出棧,這時出來的是訪問a的結點的函式,a結點剛才執行完preorder(t->lchild);了,接下來會繼續訪問preorder(t->rchild);,這是訪問a結點的函式入棧,訪問a的右結點c孩子…

不知道你看明白沒,我希望你自己能把**結合圖走一遍,你就能理解這個遞迴遍歷了。

line 58~64 以中序遍歷的方式遍歷樹,你會發現將上面先序遍歷訪問結點的那句**跟遞迴呼叫左孩子結點的那句**交換下順序就是中序遍歷**了

line 66~72 以後序遍歷的方式遍歷樹,同理,將上面先序遍歷訪問結點的那句**放在遞迴呼叫右孩子結點的那句**的後面即可

line 74~88 求樹的深度

求樹的深度,我建議你先看完遞迴遍歷,好好吸收一下遞迴的操作,然後根據**在圖里執行一遍。

求深度的思想主要在於返回。

line 75~76 在遇到空指標時,會直接返回0。看下圖的綠色部分。

line 78~79 在遇到非空指標時,會得到兩個子樹的深度,比如現在b結點的那個位置,他會得到左子樹的深度0(line 75~76遇到的空指標返回0),右子樹的深度0。

line 80~85 判斷兩者的哪個最大(因為depth=max,左右子樹的最大深度加上當前結點的深度(1))

以a結點來講,你看圖,a的左子樹深度為1,右子樹為2,那我們整棵樹是3=右子樹深度+1,返回給了main函式。

資料結構C語言二叉樹的遍歷

資料結構c語言二叉樹的遍歷 樹形結構是一類重要的非線性資料結構,其中以樹和二叉樹最為常用。二叉樹是每個結點最多有兩個子樹的有序樹。通常子樹的根被稱作 左子樹 left subtree 和 右子樹 right subtree 二叉樹常被用作二叉查詢樹和二叉堆或是二叉排序樹。二叉樹的每個結點至多只有二棵...

mysql 遍歷二叉樹 資料結構 二叉樹遍歷

這篇博文主要是研究二叉樹遍歷的遞迴與非遞迴演算法,有興趣的小夥伴可以了解下!二叉樹的遞迴遍歷 深度優先遍歷 先來張圖,看看各結點遍歷時的情況 二叉樹深度優先遍歷總結 分別為第一次,第二次,第三次進入某個結點 先序遍歷 先訪問根結點,然後先序遍歷左子樹,最後先序遍歷右子樹 根 左 右 中序遍歷 先中序...

資料結構 遍歷二叉樹

資料結構實驗之二叉樹二 遍歷二叉樹 time limit 1000ms memory limit 65536kb submit statistic problem description 已知二叉樹的乙個按先序遍歷輸入的字串行,如abc,de,g,f,其中,表示空結點 請建立二叉樹並按中序和後序的方...