寫給媳婦兒的算法(十五)——二叉樹及其遍歷

二叉樹 是一種特殊的“樹”結(jié)構(gòu)棋傍,它每個節(jié)點(diǎn)最多有兩個子樹救拉。

是一種數(shù)據(jù)結(jié)構(gòu),它是由n(n>=1)個有限結(jié)點(diǎn)組成一個具有層次關(guān)系的集合瘫拣。把它叫做“樹”是因?yàn)樗雌饋硐褚豢玫箳斓臉湟谛酰簿褪钦f它是根朝上,而葉朝下的麸拄。樹跟圖的區(qū)別就在于派昧,樹是有 層次結(jié)構(gòu) 的。

樹與圖.png

樹中只有子節(jié)點(diǎn)拢切,沒有父節(jié)點(diǎn)的節(jié)點(diǎn)是 根節(jié)點(diǎn)蒂萎;既有父節(jié)點(diǎn),又有子節(jié)點(diǎn)的節(jié)點(diǎn)是普通的節(jié)點(diǎn)淮椰;只有父節(jié)點(diǎn)岖是,沒有子節(jié)點(diǎn)的節(jié)點(diǎn)帮毁,是 葉子節(jié)點(diǎn)

二叉樹

二叉樹 就是每個節(jié)點(diǎn)最多有兩個子樹(子節(jié)點(diǎn))的樹:

二叉樹豺撑、滿二叉樹、完全二叉樹.png

滿二叉樹: 葉子節(jié)點(diǎn)全部都在最底層黔牵,除了葉子節(jié)點(diǎn)聪轿,每個節(jié)點(diǎn)都有左右兩個子節(jié)點(diǎn)的二叉樹。
完全二叉樹:葉子節(jié)點(diǎn)只有最下面兩層猾浦,最下層葉子節(jié)點(diǎn)全都靠左排列陆错,除了最后一層的葉子節(jié)點(diǎn)意外其他任何一層的節(jié)點(diǎn)都是滿的,這樣的二叉樹金赦。

二叉樹存儲方式

二叉樹可以使用鏈表來實(shí)現(xiàn)音瓷,也可以使用數(shù)組來實(shí)現(xiàn),這兩種存儲方式各有各的優(yōu)缺點(diǎn)夹抗。

鏈?zhǔn)酱鎯?/h3>
鏈?zhǔn)酱鎯Φ亩鏄?png

二叉樹使用鏈?zhǔn)酱鎯ι鳎恳粋€節(jié)點(diǎn)都需要包含三部分的內(nèi)容:本節(jié)點(diǎn)的值、左子節(jié)點(diǎn)指針漠烧、右子節(jié)點(diǎn)指針杏愤。這種方式只要知道父節(jié)點(diǎn),就能依次找到該節(jié)點(diǎn)的子節(jié)點(diǎn)已脓。這種鏈?zhǔn)酱鎯Φ姆绞矫總€節(jié)點(diǎn)需要包含這三部分珊楼,所以會浪費(fèi)一定的存儲空間,但是實(shí)現(xiàn)起來很容易度液,對于內(nèi)存空間的使用比較靈活厕宗。

順序存儲

使用數(shù)組進(jìn)行順序存儲.png

二叉樹使用順序存儲,需要使用一個數(shù)組堕担。由于數(shù)組是一個連續(xù)的存儲空間已慢,所以,數(shù)組的下標(biāo)是連續(xù)的照宝,且可以計算出來的蛇受。這樣就免去了鏈?zhǔn)酱鎯χ忻總€節(jié)點(diǎn)都需要記錄子節(jié)點(diǎn)指針的空間,每個節(jié)點(diǎn)只需要記錄自己的值就可以了厕鹃。

從圖中的值可以看出來兢仰,假設(shè)父節(jié)點(diǎn)的存儲位置設(shè)為i,那么剂碴,左子節(jié)點(diǎn)位置 = 2 × i把将;右子節(jié)點(diǎn)位置 = 2 × i + 1。這樣我們就可以通過下標(biāo)計算來計算出來各個節(jié)點(diǎn)的位置了忆矛。

另外察蹲,如圖请垛,如果二叉樹不是完全二叉樹的話,那么圖中的G點(diǎn)(怪怪的感覺??)就不存在洽议,那么右邊的存儲數(shù)組的第6個位置就會不存儲任何東西宗收,這樣的話,造成了數(shù)組存儲的離散亚兄,導(dǎo)致空間浪費(fèi)混稽。如果這樣的情況多了,空間就會浪費(fèi)的多的多审胚。所以如果最后一排葉子節(jié)點(diǎn)都靠左排列匈勋,即二叉樹為完全二叉樹的時候,空間才會是最省的膳叨,所以完全二叉樹的概念并不是沒有用的洽洁。

二叉樹遍歷

要想從頭到尾將二叉樹遍歷完全,可以有很多種方式菲嘴。先饿自、中、后序遍歷(深度優(yōu)先)临谱;層次遍歷(廣度優(yōu)先)……層次遍歷的話可以采用一個隊(duì)列來實(shí)現(xiàn)璃俗,這個在廣度優(yōu)先算法一篇寫過了。深度優(yōu)先的話悉默,可以有三種遍歷的方式:先序遍歷城豁、中序遍歷、后序遍歷抄课。


二叉樹三種遍歷方式.png

這三種遍歷方式就是跟節(jié)點(diǎn)的區(qū)別在于對于每個節(jié)點(diǎn)的訪問邏輯順序不同唱星,都是利用遞歸(非遞歸先不考慮)來進(jìn)行訪問:

先序遍歷:①打印父節(jié)點(diǎn) => ②訪問父節(jié)點(diǎn)的左子節(jié)點(diǎn) => ③訪問父節(jié)點(diǎn)的右子節(jié)點(diǎn)
中序遍歷:①訪問父節(jié)點(diǎn)的左子節(jié)點(diǎn) => ②打印父節(jié)點(diǎn) => ③訪問父節(jié)點(diǎn)的右子節(jié)點(diǎn)
后序遍歷:①訪問父節(jié)點(diǎn)的左子節(jié)點(diǎn) => ②訪問父節(jié)點(diǎn)的右子節(jié)點(diǎn) => ③打印父節(jié)點(diǎn)

所謂的前中后,指的是打印父節(jié)點(diǎn)值的時機(jī)跟磨。先序遍歷是先打印父節(jié)點(diǎn)间聊,然后遞歸訪問父節(jié)點(diǎn)的左子節(jié)點(diǎn),然后再遞歸訪問父節(jié)點(diǎn)的右子節(jié)點(diǎn)……

算法實(shí)現(xiàn)

# -*- coding: utf-8 -*-
# @Time    : 2019-03-25 16:41
# @Author  : Jaedong
# @Version : 3.6
# @File    : TraversingBinaryTree.py
# @Software: PyCharm


class Node:
    value = ''
    leftNode = None
    rightNode = None

    def __init__(self, value, leftNode, rightNode):
        self.value = value
        self.leftNode = leftNode
        self.rightNode = rightNode

# 先序遍歷就是:根節(jié)點(diǎn)->左子樹->右子樹
def preorder_traversal(root):
    if root == None:
        return

    print(root.value)
    preorder_traversal(root.leftNode)
    preorder_traversal(root.rightNode)

# 中序遍歷就是:左子樹->根節(jié)點(diǎn)->右子樹
def inorder_traversal(root):
    if root == None:
        return

    inorder_traversal(root.leftNode)
    print(root.value)
    inorder_traversal(root.rightNode)

# 后序遍歷就是:左子樹->右子樹->根節(jié)點(diǎn)
def postorder_traversal(root):
    if root == None:
        return

    postorder_traversal(root.leftNode)
    postorder_traversal(root.rightNode)
    print(root.value)


# 簡單粗暴抵拘,先來一棵二叉樹
node_d = Node('D', None, None)
node_e = Node('E', None, None)
node_b = Node('B', node_d, node_e)
node_f = Node('F', None, None)
node_c = Node('C', None, node_f)
root = Node('A', node_b, node_c)

print('先序遍歷:')
preorder_traversal(root)
print('中序遍歷:')
inorder_traversal(root)
print('后序遍歷:')
postorder_traversal(root)

結(jié)果是:

三種遍歷結(jié)果.png



上一篇:寫給媳婦兒的算法(十四)——動態(tài)規(guī)劃
下一篇:寫給媳婦兒的算法(十六)——二叉查找樹

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末哎榴,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子僵蛛,更是在濱河造成了極大的恐慌尚蝌,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件充尉,死亡現(xiàn)場離奇詭異飘言,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)驼侠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門姿鸿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谆吴,“玉大人,你說我怎么就攤上這事苛预【淅牵” “怎么了?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵碟渺,是天一觀的道長鲜锚。 經(jīng)常有香客問我,道長苫拍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任旺隙,我火速辦了婚禮绒极,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蔬捷。我一直安慰自己垄提,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布周拐。 她就那樣靜靜地躺著铡俐,像睡著了一般。 火紅的嫁衣襯著肌膚如雪妥粟。 梳的紋絲不亂的頭發(fā)上审丘,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天,我揣著相機(jī)與錄音勾给,去河邊找鬼滩报。 笑死,一個胖子當(dāng)著我的面吹牛播急,可吹牛的內(nèi)容都是我干的脓钾。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼桩警,長吁一口氣:“原來是場噩夢啊……” “哼可训!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起捶枢,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤握截,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后柱蟀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體川蒙,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年长已,在試婚紗的時候發(fā)現(xiàn)自己被綠了畜眨。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片昼牛。...
    茶點(diǎn)故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖康聂,靈堂內(nèi)的尸體忽然破棺而出贰健,到底是詐尸還是另有隱情,我是刑警寧澤恬汁,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布伶椿,位于F島的核電站,受9級特大地震影響氓侧,放射性物質(zhì)發(fā)生泄漏脊另。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一约巷、第九天 我趴在偏房一處隱蔽的房頂上張望偎痛。 院中可真熱鬧,春花似錦独郎、人聲如沸踩麦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谓谦。三九已至,卻和暖如春贪婉,著一層夾襖步出監(jiān)牢的瞬間反粥,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工谓松, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留星压,地道東北人。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓鬼譬,卻偏偏與公主長得像娜膘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子优质,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,446評論 2 348