日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[算法笔记]二叉树基础

發布時間:2024/4/18 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [算法笔记]二叉树基础 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言:部分資料引自極客大學《數據結構與算法之美》,感謝王爭老師!
參考鏈接:

  • https://visualgo.net/en/bst?slide=1
  • https://zh.wikipedia.org/wiki/二叉樹#前(先)序、中序、後序遍歷
  • https://leetcode-cn.com/problems/binary-tree-inorder-traversal/
  • https://time.geekbang.org/column/article/67856
如何表示(或者存儲)一棵二叉樹?

想要存儲一棵二叉樹,我們有兩種方法,一種是基于指針或者引用的二叉鏈式存儲法,一種是基于數組的順序存儲法。
1. 鏈式存儲
每個節點有三個字段,其中一個存儲數據,另外兩個是指向左右子節點的指針。我們只要拎住根節點,就可以通過左右子節點的指針,把整棵樹都串起來。這種存儲方式我們比較常用。大部分二叉樹代碼都是通過這種結構來實現的。

2. 基于數組的順序存儲法
把根節點存儲在下標 i = 1 的位置,那左子節點存儲在下標 2 * i = 2 的位置,右子節點存儲在 2 * i + 1 = 3 的位置。以此類推,B 節點的左子節點存儲在 2 * i = 2 * 2 = 4 的位置,右子節點存儲在 2 * i + 1 = 2 * 2 + 1 = 5 的位置。

思考:根節點存儲在下標為1的位置,而不是0的位置,有可能和二進制位有關。
下表用4位二進制數來表示圖中完全二叉樹的示例:

根節點左節點右節點
000100100011
001001000101
001101100111
010010001001
010110101011

可以發現:
左節點下標 = 根節點下標右移1位
右節點下標 = 根節點下標右移1位 + 1
如果根節點下標從0開始,就不好運算了…

如果是非完全二叉樹,且以數組的形式存儲,在相應空白結點處還是會浪費空間的。所以完全二叉樹使用數組來存儲,空間浪費最少。

二叉樹的屬性

關于“樹”,還有三個比較相似的概念:高度(Height)、深度(Depth)、層(Level)。它們的定義是這樣的:

以下圖為例:

王爭老師對于二叉樹的個人理解:
“高度”這個概念,其實就是從下往上度量,比如我們要度量第 10 層樓的高度、第 13 層樓的高度,起點都是地面。所以,樹這種數據結構的高度也是一樣,從最底層開始計數,并且計數的起點是 0。
“深度”這個概念在生活中是從上往下度量的,比如水中魚的深度,是從水平面開始度量的。所以,樹這種數據結構的深度也是類似的,從根結點開始度量,并且計數起點也是 0。
“層數”跟深度的計算類似,不過,計數起點是 1,也就是說根節點位于第 1 層。

二叉樹的遍歷

經典的方法有三種,前序遍歷、中序遍歷和后序遍歷。其中,前、中、后序,表示的是節點與它的左右子樹節點遍歷打印的先后順序

  • 前序遍歷是指,對于樹中的任意節點來說,先打印這個節點,然后再打印它的左子樹,最后打印它的右子樹。
  • 中序遍歷是指,對于樹中的任意節點來說,先打印它的左子樹,然后再打印它本身,最后打印它的右子樹。
  • 后序遍歷是指,對于樹中的任意節點來說,先打印它的左子樹,然后再打印它的右子樹,最后打印這個節點本身。

這里使用了遞歸的知識,具體代碼實現引自wiki:
前序遍歷

visit(node)print node.valueif node.left != null then visit(node.left)if node.right != null then visit(node.right)

中序遍歷

visit(node)if node.left != null then visit(node.left)print node.valueif node.right != null then visit(node.right)

后序遍歷

visit(node)if node.left != null then visit(node.left)if node.right != null then visit(node.right)print node.value


在這個二叉樹中,
前序遍歷的結果:M,G,D,B,A,C,F,E,J,H,I,K,L,S,P,O,N,Q,R,W,U,T,V,X,Z,Y
中序遍歷的結果:A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
后序遍歷的結果:A,C,B,E,F,D,I,H,L,K,J,G,N,O,R,Q,P,T,V,U,Y,Z,X,W,S,M

對于各個遍歷過程的個人理解:
前序遍歷:

  • 用小明家族繼承傳家寶打比喻或許比較形象:繼承家族傳家寶的原則是傳長子不傳幼子,傳后代不傳兄弟 ---- 從祖父,到父親,到小明本人。假設小明絕后(沒有子孫結點),那么小明的遺產就交給他的弟弟小磊(當前節點的 兄弟節點 )。如果小磊也很不幸絕后(好慘),那么就將財產留給他的叔叔,由叔叔傳承給小磊的堂兄弟。 感覺傳完寶物之后一個家族就完蛋了…

中序遍歷:

  • 每次取走二叉樹中 最左邊的元素,其中最左邊是字面意思(哈哈)。
    就拿這幅圖為例,ABCDEFGHIJKL…是不是一目了然(手動狗頭)
    注意根節點永遠在左節點以及其后代的右部,右節點及其后代的左部。

    后序遍歷:
    假設小明要搭積木城堡,規則是先打好地基,再蓋上樓頂。而且兩個相鄰城堡可以組合成一個大城堡的地基。
    還是以這幅圖為例,先打好地基AC,蓋上屋頂B。此時一個城堡搭建好了,可以搭建下一個城堡:先打好地基E,然后蓋上屋頂F。最后蓋第三層D…

用二叉樹表示下述表達式:a+b*(c-d)-e/f (又是取走最左邊元素…同時)

  • 先序遍歷 的序列是:-+a*b-cd/ef (傳承家產)

  • 中序遍歷 的序列是:a+b*c-d-e/f (摘除最左邊)

  • 后序遍歷 的序列是:abcd-*+ef/- (搭城堡)

小結:遍歷二叉樹:L、D、R分別表示遍歷左子樹、訪問根結點和遍歷右子樹,則先(根)序遍歷二叉樹的順序是DLR,中(根)序遍歷二叉樹的順序是LDR,后(根)序遍歷二叉樹的順序是LRD。還有按層遍歷二叉樹。這些方法的時間復雜度都是O(n),n為結點個數。

最后安利一個很好用的二叉樹在線可視化平臺: https://visualgo.net/en/bst?slide=1

總結

以上是生活随笔為你收集整理的[算法笔记]二叉树基础的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。