複習整理 (一)二叉樹遍歷

2022-08-24 10:39:07 字數 3463 閱讀 1648

介紹常規的三種遞迴遍歷方法(先中後)以及非遞迴的先序、中序、後序、層序遍歷
對二叉樹這種資料結構有一定了解

遍歷二叉樹的目的是為了訪問到每個結點且按照某一特定的順序

一定要記住子樹的->->

遞迴的特點就是**可讀性高,容易理解

/*先序遍歷,以rt為根的樹*/ //根->左->右

template void binarytree::preorder(const node* rt, void(*visit)(const t&)) const

}

先分析先序遍歷效果:如上圖先序遍歷的順序為abcdefghk

根總是先被訪問,之後被訪問的就是他的左孩子,左孩子又稱為新的根,於是繼續訪問他的左孩子,直到這個根沒有左孩子,之後訪問他的右兒子,如果他沒有右兒子,如圖中的d,追溯到他的父節點去訪問右兒子,一直追溯,直到有了右兒子,如ea的右兒子,e又作為新的根節點先被訪問 ,繼續一開始的遍歷。

可能要被我繞暈了,簡言之,得到根節點之後先對其訪問,然後要訪問全部的左兒子,最後再是右兒子。所以,一顆子樹的右兒子要放在最後訪問,就好比壓在最下面,等上面的根和左兒子訪問過了在出來,於是,這裡我們用到了

上**!

/*非遞迴先序遍歷*/

template void binarytree::norecurringpreorder(const node* rt, void(*visit)(const t&)) const

stacks;

node* temp = nullptr;

s.push(rt);

while (s.empty() == false)

if (temp->left_child != nullptr)

}}

子樹的->->**:

/*中序遍歷*/   //左->根->右

template void binarytree::inorder(const node* rt, void(*visit)(const t&)) const

}

遍歷效果:上圖遍歷順序為bdcaehgkf遍歷思路:一路向左!直到這個左孩子作為根的時候沒有它自己的左孩子,那就先訪問他,因為此時按照遍歷順序->->,他被當成根了(沒有左孩子),訪問他完之後就取訪問他的右兒子,繼續一路向左,重複過程...

偽**:當前根不為空的時候=>壓入=>他成為他的左兒子=>迴圈,如果當前是空=>取棧頂(當前根)訪問他,並且pop()=>他成為他的右兒子=>迴圈,棧空或者最初根為nullptr的時候退出。

上**:

/*非遞迴中序遍歷*/

template void binarytree::norecurringinorder(node* rt, void(*visit)(const t&)) const

else

}}

子樹的->->**:

/*後序遍歷*/ //左->右->根

template void binarytree::postorder(const node* rt, void(*visit)(const t&)) const

}

遍歷效果:dcbhkgfea關於思路

後序遍歷的非遞迴就比前兩種的要複雜一點了,也比較難理解,因為根是最後被訪問的,而在棧頂的元素當做根的話並不知道他的兒子們有沒有被訪問過,所以開乙個棧不夠,起碼還要乙個棧來儲存乙個標記,這個標記用來記錄他的兒子們有沒有被訪問過。

關於方法

方法有很多種,可以開乙個布林棧放入對應根節點的標記,判斷當前根已經被訪問過兒子們了即可出棧,否則就壓入他的兩個兒子(按順序是先左後右,又因為棧的關係,所以先壓入右兒子)。

這裡呢我就介紹一種方法:開乙個棧,每次節點壓入都壓兩次,出棧的時候判斷棧頂元素是否和他相同,如果兩個相同,就說明他的兒子沒有被訪問(壓入棧),就先壓入他的右孩子,再左孩子,注意每次壓入都是壓兩個,空節點不入棧。

**:

/*非遞迴後序遍歷*/

void binarytree::norecurringpostorder(node* rt, void(*visit)(const t&)) const

stacks;

node* temp = rt;

s.push(temp);

s.push(temp);

while (s.empty() == false)

if (temp->left_child)

} else

}}

目前我看到的方法不管是開兩個棧還是乙個棧,需要的空間都是總節點數的兩倍。

按照層數從左往右依次遍歷

上圖遍歷效果:abecfdghk

思路:訪問的順序像排隊一樣逐層遍歷,每層的下面一層,按照從左到右的順序在當前層的最後排好隊,當前層也是按照從左往右的順序被排好了,那在訪問當前層的節點時將兒子們(下一層)排入尾,這樣就可以實現了。可以看成是一種遞推,把根看成最初的乙個人在排隊

上**:

/*層序遍歷,利用佇列,也可以利用陣列,然後用兩個指標去控制入和出*/

template void binarytree::levelorder(node* rt, void(*visit)(const t&)) const

while (!q.empty())

if (temp->right_child)

}}

還有一種利用陣列來實現的方法,網上找到的,大致思路其實就是用陣列實現了佇列的功能:通過兩個指標 in out(都是下標)控制,個人認為會浪費資源空間,不過思路很好。

void floorprint(ptreenode tree)  //層序遍歷

out++; }}

原文:

二叉樹的遍歷很重要(我們老師是這麼說的。。可能只是為了應付考試吧)我還是比較推薦在理解的基礎上掌握知識,要不斷的在腦海中模擬遍歷的過程,遞迴的和非遞迴的。

二叉樹相關演算法(一) 二叉樹的遍歷

遞迴方式會導致每個節點會經過三次,先序是在第一次經過節點時訪問,中序是第二次經過節點時訪問,後序是第三次經過節點時訪問。其中較為特殊的是葉子節點,左孩子和右孩子都為空,訪問空樹時什麼都不做就返回。public static void p node h 1 利用棧來進行實現,三種演算法在理解的基礎上進...

設計性實驗一 二叉樹的遍歷

一 實驗任務 二叉樹的遍歷 分別以順序儲存結構和二叉鍊錶作儲存結構,試編寫前序 中序 後序及層次順序遍歷二叉樹的演算法。二 實驗任務的子任務 本人設計以二叉鍊錶作儲存結構,編寫前序 中序 後序及層次順序遍歷二叉樹的演算法。三 演算法分析 如圖 文字或流程圖或畫圖說明都可 1.假設輸入的資料即為乙個二...

二叉樹學習(一)二叉樹基礎

最近準備學習一下資料結構,二叉樹當然是必須要了解的了。網上看了一些貼子,順便把重要的內容就記下來了,有需要的同學可以看看,入門看很有幫助。1.1 定義 1.2 結點的度 1.3 結點關係 1.4 結點層次 2.1 定義 2.2 二叉樹特點 每個結點最多有兩顆子樹,所以二叉樹中不存在度大於2的結點。左...