1. 程式人生 > >看了齊姐這篇文章,再也不怕面試問樹了

看了齊姐這篇文章,再也不怕面試問樹了

在寫完了所有線性資料結構之後,今天開啟非線性資料結構系列。 我們今天先來看,什麼是“樹”。 樹是由頂點和邊組成的且不存在環的資料結構。**作為一個應用非常廣的資料結構,不僅在工作中常用,在面試中也非常常考。** 一是因為樹的結構天然決定了它和遞迴聯絡緊密,很多樹相關的演算法題都非常適合用遞迴來解; 二是因為它的難度介於連結串列和圖之間,非常適合在 45 分鐘的面試裡進行考察,所以一場面試中遇到兩三輪問樹都是再正常不過的了。 本文先來講樹的基礎內容,分為以下小節,每個小節開頭都會有思維導圖和對應的 `Leetcode` 演算法題喲~ 1. 簡介 2. 金融裡的二叉樹 3. 樹的所有概念 a. 樹的**三大特點** b. 樹的**五大品種** c. 高度和深度 4. 看樹的角度 a. 三種 `DFS` 遍歷方式 b. 兩種 `BFS` 遍歷方式 c. 四種檢視 鑑於樹相關的內容太多,而且又是面試重點內容,之後會有文章再專門來講**樹有關的解題思路**以及最常用的**二叉搜尋樹**,大家敬請期待~ ## 簡介 其實資料結構裡的“樹”和我們現實世界裡的樹挺像的,只不過倒過來了嘛,根朝上。 比如: ![](https://img2020.cnblogs.com/blog/2000306/202008/2000306-20200811094629462-1606942676.png) 在這片森林裡,最常用的還是「二叉樹」。 二叉樹,是由很多個 `TreeNode` 構成的這種樹形的資料結構, ```java class TreeNode { int value; TreeNode left; TreeNode right; } ``` 就像連結串列中的 `ListNode`。 二叉樹並不一定非得是“二叉”的,而是說每個節點**最多**有兩個孩子,叫 `left` 和 `right`,但也可以沒有。 當每個節點都只有一個孩子的時候,就退化成了連結串列。 所以**連結串列就是一棵特殊的樹,而樹是一個特殊的圖。** ## 金融裡的二叉樹 大家知道我是金融背景的,所以我最開始瞭解二叉樹是在金融工程課程中給衍生品定價,這裡也簡單梳理下,不感興趣的小夥伴可以跳過這一段。 在金融工程裡,二叉樹是用來在風險中性世界裡給期權定價使用的模型。 比如這是一個股價二叉樹,其實就是我們把二叉樹放倒了看嘛。 ![](https://img2020.cnblogs.com/blog/2000306/202008/2000306-20200811094918850-537833304.png) 有些小夥伴會發現,這裡的節點好像少了很多,沒錯,因為我們讓股價每次上漲和下跌的幅度保持不變,所以到第 n 層最多有 n 個節點,而不會像普通的二叉樹一樣按照等比序列增長。 上圖是兩期的二叉樹,那麼最簡單的一期的二叉樹定價模型表示為: ![](https://img2020.cnblogs.com/blog/2000306/202008/2000306-20200811094940963-97397574.png) 我們假設當前股票的價格為 `S`,那我們想知道未來某個時刻比如 `t 時刻`的價格,股價有可能上漲也有可能下跌,還可能不變呢。 在該模型裡我們就抽象成兩種可能性,一種是上漲,一種是下跌,所以可以用二叉樹來表示。 假設股票價格會有 `p` 的概率上漲至 `uS`, 有 `1-p` 的概率下跌至 `dS`. 這裡的 `p` 並不是在真實世界裡股票上漲的概率,而是一個在風險中性世界裡的上漲概率,所以 **股票現在的價格就是未來某時刻的無風險收益的折現**, 即: $$S = e^{-rt}[pS_u + (1-p) S_d] $$ 這就是最簡單的二叉樹定價模型。 那我們言歸正傳。 ## 樹的所有概念 ![](https://img2020.cnblogs.com/blog/2000306/202008/2000306-20200811095037183-980834264.png) ### 1. 三大特點 樹的三大特點是: 1. 如果把樹看成一個無向圖,那麼它是一個**連通圖** `connected graph`. 2. 樹是一個**無環圖**。 3. 樹的節點個數和邊的個數之間的關係是固定的。如果樹上有 `n` 個 `node`,那麼它有 `n-1` 條邊。因為除了根節點,其他的節點都會有一條邊指向它。 ### 2. 樹的品種 **2.1 平衡二叉樹** `Balanced Binary Tree`: - 定義:對於這棵樹裡的**每個節點**,它的左子樹和右子樹的高度差不大於 1。 這裡要注意,是對於**每個節點**,而不只是對於根結點。 比如左邊這棵樹就不是平衡二叉樹,右邊的才是。 ![](https://img2020.cnblogs.com/blog/2000306/202008/2000306-20200811095132202-516003319.png) 那麼大名鼎鼎的 `AVL-Tree` 就是平衡二叉樹,準確說是自平衡二叉查詢樹。 那什麼是二叉查詢樹呢? **2.2 二叉查詢樹** `Binary Search Tree` - 定義:對於這棵樹裡的每個節點, - 它左子樹裡的每個節點的值都小於它的值; - 它右子樹裡的每個節點的值都大於它的值。 ![](https://img2020.cnblogs.com/blog/2000306/202008/2000306-20200811095156621-1658484242.png) 對二叉查詢樹,最重要的性質就是: **在做中序遍歷時,這個序列是一個升序序列。** 當你在做二叉查詢樹的演算法題沒有思路時,可以想想這個性質,很多題目都會迎刃而解。 **2.3 完全二叉樹** `Complete Binary Tree`: - 定義:除了最後一層,其他層都是滿的,那麼最後一層的節點要靠左排列且中間不允許有氣泡。 比如左邊不是完全二叉樹,右邊的是。 ![](https://img2020.cnblogs.com/blog/2000306/202008/2000306-20200811095314788-427933433.png) 比如堆就是一個完全二叉樹,還不瞭解堆的基本操作的,公眾號內回覆「堆」獲取文章複習喲~ 那麼完全二叉樹的最大的好處就是因為它排列緊密沒有氣泡,所以可以用陣列來儲存,這樣就大大節省了記憶體空間。 **2.4 完美二叉樹** `Perfect Binary Tree` - 定義:所有層的所有節點都必須是滿的。 完美二叉樹比完全二叉樹的定義更加嚴格,包括最後一層,每一層的節點都要是滿的,畢竟是追求完美的嘛。 所以我們如果知道了層數,就知道了它有多少個節點,也就是一個等比數列求和。 ![](https://img2020.cnblogs.com/blog/2000306/202008/2000306-20200811095358828-1913182819.png) **2.5 完滿二叉樹** `Full Tree` - 定義:對於這棵樹的每個節點而言,要麼有 0 個孩子,要麼有 2 個孩子。 ![](https://img2020.cnblogs.com/blog/2000306/202008/2000306-20200811095430733-1936180033.png) 大家不要輕視這些概念哦,很多演算法題都會直接考察,在本節的思維導圖裡也附帶了 Leetcode 對應的題目,電面時很喜歡考哦~ ### 3. 高度和深度 樹的高度 `height` 和深度 `depth` 是兩個非常重要的概念,比如 Leetcode 104 和 111 就是專門求樹的高度的。 而這兩個概念是相反方向的,大體上呢, - **高度是從當前節點到葉子