我們前面講了陣列、鍊錶等線性資料結構,今天我們來看乙個非線性的資料結構--樹。之前我們說所謂的線性資料結構是指資料就像一條線一樣只有前和後兩個方向。而樹作為一種非線性的資料結構,肯定是不止這兩個方向。
說起來其實樹也只有乙個前的方向,但是後就不一定是乙個了。雖然部分樹在極端情況下會退化成煉表,但是大多數情況下,他都不只有乙個「後」。
維基百科中對樹的解釋是這樣的:
在電腦科學中,樹(英語:tree)是一種抽象資料型別(adt)或是實現這種抽象資料型別的資料結構,用來模擬具有樹狀結構性質的資料集合。它是由n(n>0)個有限節點組成乙個具有層次關係的集合。把它叫做「樹」是因為它看起來像一棵倒掛的樹,也就是說它是根朝上,而葉朝下的。它具有以下的特點:(該**極客時間)
上圖中,其中前面三個都是樹,最後乙個不是樹。
我們再結合一張圖來簡單解釋一下樹的幾個名詞,方便我們後續理解:
在這幅圖中,通過觀察我們可以得知這麼幾個屬性:
父節點:a節點就是b節點的父節點,b節點是a節點的子節點
兄弟節點:b、c這兩個節點的父節點是同乙個節點,所以他們互稱為兄弟節點
根節點:a節點沒有父節點,我們把沒有父節點的節點叫做根節點
葉子節點:圖中的h、i、j、k、l節點沒有子節點,我們把沒有子節點的節點叫做葉子節點
節點的高度:節點到葉子結點的最長路徑,比如c節點的高度是2(l->f是1,f->c是2)
節點的深度:節點到根節點的所經歷的邊的個數比如c節點的高度是1(a->c,只有一條邊,所以深度=1)
節點的層:節點的深度+1
樹的高度:根節點的高度
樹結構多種多樣,但是我們在實際開發過程中直接用到或者間接用到的最常見的樹就是二叉樹。二叉樹顧名思義,每個節點最多有兩個子節點,我們分別將其稱為左子節點、右子節點。不過我們並不要求二叉樹上的每個節點都必須要有這兩個節點,可以只有左子節點也可以只有右子節點。
如果乙個二叉樹中,葉子節點全都在最後兩層,最後一層的葉子節點全部都是靠左排列的,而且除了最後一層中,其他節點個數都要達到最大,這種二叉樹叫做完全二叉樹。這種理論調調可能看起來比較複雜,我們可以通過畫圖的方式快速理解,如圖所示,這就是乙個完全二叉樹:
如果乙個二叉樹中,葉子節點全都在最底層,除了葉子節點之外,每個節點都有左右兩個子節點,這種二叉樹就是滿二叉樹。
如圖所示,這就是乙個滿二叉樹:
除了剛才說的這兩種特殊的二叉樹之外的其他二叉樹都是普通二叉樹
剛才我們簡單梳理了一下二叉樹的基本定義,那我們現在來看二叉樹中非常重要的乙個操作,二叉樹的遍歷。經典的方法有三種,前序遍歷、中序遍歷和後序遍歷。其中,前、中、後序,表示的是節點與它的左右子樹節點遍歷列印的先後順序。為了方便大家理解,我這裡拿一張圖,結合我們的遍歷順序要求,說一下輸出結果應該是什麼。大家可以借助結果來理解這個遍歷順序。
前序遍歷是指,對於樹中的任意節點來說,先列印這個節點,然後再列印它的左子樹,最後列印它的右子樹。
結合上圖來說,前序遍歷的輸出結果是:
中序遍歷是指,對於樹中的任意節點來說,先列印它的左子樹,然後再列印它本身,最後列印它的右子樹。結合上圖來說,中序遍歷的輸出結果是:a -> b -> d -> h -> i -> e -> j -> k -> c -> f -> l -> g
後序遍歷是指,對於樹中的任意節點來說,先列印它的左子樹,然後再列印它的右子樹,最後列印這個節點本身。結合上圖來說,後續遍歷的輸出結果是:h -> d -> i -> b -> j -> e -> k -> a -> l -> f -> c -> g
在最後,我把我建立的樹的結構以及前中後序遍歷的**貼出來,大家看看和大家想象的是否一致h -> i -> d -> j -> k -> e -> b -> l -> f -> g -> c -> a
使用樹+佇列的方式來實現。這裡是利用佇列的fifo的特性來做的,我們依次按層將節點放入佇列中去,然後輸出出來,並且在輸出的時候,將輸出節點的左右子節點寫入佇列中// 二叉樹類
private static class treenode
/*** 前序遍歷
* @param treenode 二叉樹
*/private static void preorderbytree(treenode treenode)
system.out.print(treenode.data + " -> ");
preorderbytree(treenode.left);
preorderbytree(treenode.right);
}/**
* 中序遍歷
* @param node treenode 二叉樹
*/private static void inordertree(treenode node)
inordertree(node.left);
system.out.print(node.data + " -> ");
inordertree(node.right);
}/**
* 後序遍歷
* @param node 二叉樹
*/private static void behindordertree(treenode node)
behindordertree(node.left);
behindordertree(node.right);
system.out.print(node.data + " -> ");
}
/**
* 二叉樹的按層遍歷
* @param node
*/private static void levelorder(node node)
if (pollnode.right != null) }}
資料結構學習筆記 二叉樹
樹,非線性表結構 樹有三個概念 高度從下向上數,起點是0 深度從上向下數,起點是0 層數從上向下數,起點是1 每個節點最多兩個叉 有兩種特殊二叉樹 滿二叉樹,除了葉子節點,每個節點都有左右兩個子節點 完全二叉樹,葉子節點都在最底下兩層,最後一層葉子節點都靠左排列,且除了最後一層,其它層節點個數都達到...
資料結構學習(1) 二叉樹
二叉樹結構 public class treenode 前序遍歷 根結點,左子樹,右子樹 public static void prenode treenode node,listtreelist 中序遍歷 左子樹,根結點,右子樹 public static void midnode treenod...
資料結構學習之二叉樹
一 為什麼用二叉樹,而不是三個指標域或是根據實際情況指定指標域?比如3,那麼有n個節點就是有3n個指標域,其中邊只有n條,那麼只有n 1個域非空,有2n 1個域為空,浪費空間。而對於2,那麼就只有n 1個域為空。而比如說根據實際來確定指標域,對於實現上是非常困難的。度為2的樹就是二叉樹。斜二叉樹 完...