00.二叉樹基本

基本概念

  • 結點:表示樹中的元素。
  • 結點的度:擁有子結點的個數
  • 葉子:度爲0的結點,也叫終端結點
  • 樹的度:樹中結點的最大的度
  • 結點的層次:根結點是第一層,它的孩子結點是第二層,依次類推。
  • 樹的高度:最大層次數。

  • 二叉樹:所有結點的度數不超過2的樹。
  • 滿二叉樹:高度爲h的二叉樹恰好有2^h-1個結點時。
  • 完全二叉樹:葉子結點只可能出現在最後一層或倒數第二層,每個非葉子結點要麼有兩個孩子結點,要麼只有左孩子結點。

滿二叉樹

葉子節點全都在最底層,除了葉子節點之外,每個節點都有左右兩個子節點

完全二叉樹

葉子節點都在最底下兩層,最後一層的葉子節點都靠左排列,並且除了最後一層,其他層的節點個數都要達到最大

2是滿二叉樹,3是完全二叉樹

二叉樹的存儲

要理解完全二叉樹定義的由來,需要先了解一棵二叉樹的存儲

想要存儲一棵二叉樹,有兩種方法,一種是基於指針或者引用的二叉鏈式存儲法,一種是基於數組的順序存儲法

鏈式存儲法

圖中應該可以很清楚地看到,每個節點有三個字段,其中一個存儲數據,另外兩個是指向左右子節點的指針。我們只要拎住根節點,就可以通過左右子節點的指針,把整棵樹都串起來。

這種存儲方式比較常用。大部分二叉樹代碼都是通過這種結構來實現的

基於數組的順序存儲法

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

如果節點X存儲在數組中下標爲i的位置,下標爲2 * i 的位置存儲的就是左子節點,下標爲2 * i + 1的位置存儲的就是右子節點。
反過來,下標爲i/2的位置存儲就是它的父節點。通過這種方式,我們只要知道根節點存儲的位置(一般情況下,爲了方便計算子節點,根節點會存儲在下標爲1的位置),這樣就可以通過下標計算,把整棵樹都串起來

不過,剛剛舉的例子是一棵完全二叉樹,所以僅僅“浪費”了一個下標爲0的存儲位置。
如果是非完全二叉樹,其實會浪費比較多的數組存儲空間。你可以看我舉的下面這個例子

所以,如果某棵二叉樹是一棵完全二叉樹,那用數組存儲無疑是最節省內存的一種方式。因爲數組的存儲方式並不需要像鏈式存儲法那樣,要存儲額外的左右子節點的指針。這也是爲什麼完全二叉樹會單獨拎出來的原因,也是爲什麼完全二叉樹要求最後一層的子節點都靠左的原因。

二叉樹的遍歷

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

前序遍歷

對於樹中的任意節點來說,先打印這個節點,然後再打印它的左子樹,最後打印它的右子樹。(本左右)

中序遍歷

對於樹中的任意節點來說,先打印它的左子樹,然後再打印它本身,最後打印它的右子樹。(左本右 有序輸出)

後序遍歷

對於樹中的任意節點來說,先打印它的左子樹,然後再打印它的右子樹,最後打印這個節點本身(左右本 左右都遍歷完了在操作本身,釋放二叉樹時使用 )

前序遍歷的遞推公式:
preOrder(r) = print r->preOrder(r->left)->preOrder(r->right)

中序遍歷的遞推公式:
inOrder(r) = inOrder(r->left)->print r->inOrder(r->right)

後序遍歷的遞推公式:
postOrder(r) = postOrder(r->left)->postOrder(r->right)->print r

1個節點有左右子樹,被分爲3個點
遞歸的訪問整棵樹的時候都要訪問這三個點

二叉樹的前中後序遍歷(遞歸方式)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章