通俗易懂多圖透徹講解二叉樹的遍歷--前序, 中序和后序

二叉樹的遍歷是一個數據結構中經常會遇到的知識點, 具體又分為前序, 中序和后序三種.

什么是樹?

先來理解一下什么是樹, 從一個我們相對熟悉的家譜樹(Family Tree)說起吧.

數據結構-樹-家譜樹

家族的根是爺爺, 然后生了兩個娃, 大伯和你爸爸. 繼續往下, 有堂哥堂姐, 還有你以及你妹, 等等.

一個家族繁衍下來, 很像一棵樹開枝散葉, 當然跟真的樹相比, 畫出來時通常是倒過來的, 根在上面.

二叉樹 VS 多叉樹

明白了什么是樹, 那什么又是二叉樹呢?

首先這里每個人稱為樹的一個節點. 而每個節點下面呢? 可以看到最多只有兩個節點.

可能養三個娃太費勁了, 或者計劃生育, 頂多兩個葫蘆娃, 超生了就罰款, 當然現在應該不會了.

一個節點, 在它之下的節點, 多則兩個,少則一個甚至沒有, 這就是二叉樹.

而如果像下邊這樣, 大伯之后還有個二伯, 你爸是老三, 那這就不算了.

多叉樹

所以前面的圖是二叉樹, 后面的的則不是.

二叉樹的節點(Node)

再來看二叉樹的幾種節點.

二叉樹的節點-根節點-左節點-右節點

首先爺爺這里叫做 根節點, 老祖宗.

給他一個綠色, 不是帽子啊. 只是為了區分.

然后一個節點下面不是頂多兩個節點嘛, 那左邊這個呢就叫 左節點, 標成紅色.

這里像大伯, 堂哥, 你還有外甥, 不管處在哪個層級或者說輩分也好, 只要在左邊的就是左節點.

那其余的自然就是 右節點 了. 用藍色表示.

二叉樹的子樹(subtree)

了解了左右節點后, 再來看一個子樹的概念.

二叉樹的子樹-左子樹-右子樹

根節點左邊這一支呢, 也就是你大伯一家子, 與節點類似, 就叫 左子樹, 還是用紅色表示.

右邊的自然就是 右子樹 了, 也就是你爸爸這一家子.

二叉樹的遍歷(traversal)

有了以上概念后, 再來看遍歷. 那什么是遍歷呢?

假設來說吧, 有一天你變得很出名, 然后有個好事的記者呢, 就想對你這整個家族的人, 都采訪一下, 挖點奇聞軼事或者你小時候的糗事出來.

這種把一個樹上全部節點都訪問一次的行為, 就是遍歷, 都歷經一遍.

既然都要訪問, 那現在的問題就是, 這里這么多人, 到底按什么順序去訪問.

對于二叉樹, 深度優先的遍歷有這么三種:

  • 前序遍歷(preorder)
  • 中序遍歷(inorder)
  • 后序遍歷(postorder)

二叉樹的前序遍歷

先來看什么是前序遍歷.

它的大規則或者說大的方向是先訪問根節點, 然后是左子樹, 最后是右子樹. 簡稱 “根-左-右”.

先采訪爺爺. 然后是大伯一家子, 最后到你家.

二叉樹前序遍歷的大方向

當然這兩家子下面又還有很多人, 到底又先采訪誰的小規則我們晚點再說.

先說另一個問題, 不知道你想過沒有, 為什么大規則要這樣安排呢?

二叉樹遍歷的就近原則

這里介紹二叉樹遍歷的一個可以叫做就近的原則吧.

假設來說, 這是個地圖, 爺爺在江西, 然后子女通常圍繞父母就近開枝散葉, 比如大伯就去了臨近的廣東, 而你爸爸則到了旁邊的福建, 這是很自然的.

二叉樹遍歷的就近原則

再往下呢, 也是類似的, 堂哥堂姐們就隨著大伯在廣東混了, 而你和你妹自然就在福建, 也是很合理的.

那回到記者采訪的問題上, 假如這個記者剛采訪完廣東的大伯, 又大老遠跑到福建去采訪你爸爸,
左右橫跳, 飛來飛去, 好不容易掙點稿費, 都交給鐵道部或者民航局了, 不劃算.

另外, 我們可能注意到一點, 大伯和你爸和爺爺之間都有一條線連接.

想象這是一棵樹, 而記者則是一只螞蟻, 他現在在大伯這個節點上, 他要去你爸那邊, 其實他要先沿著左邊的路爬回到爺爺這個根節點, 再順著右邊的樹枝才能爬到你爸的節點上.

大伯和你爸之間其實是沒有連線的. 如果有的話, 這就不是樹形結構而是圖形結構了.

左子樹的前序遍歷

明白了這個就近原則后, 我們繼續看這個左子樹里面的節點要按什么順序去訪問.

前面說了大規則是 根-左-右, 然后說子樹里面要確定一個小規則. 其實呢, 并不存在所謂的小規則.

當把左子樹單拎出來, 其實它還是一顆樹. 因此依然可以按照 “根-左-右” 的規則.

先訪問根節點, 大伯;

之后是左子樹, 堂哥一家子;

最后是右子樹, 堂姐, 或者說右節點, 目前就她一個, 可能還沒出嫁或者還沒生娃.

二叉樹左子樹的前序遍歷

這里利用了子樹和整棵樹之間的一種自相似特性. 想象一下, 把一棵樹的一個樹枝掰斷了, 插在地上, 它看上去是不是就像一顆小樹?

兒子跟老子長得一樣, 這就是自相似. 因為存在這種相似性, 就可以重復使用同一個規則, 而不需要針對各個子部分又發明新的規則, 這就是遞歸處理.

左子樹的展開

那么將左子樹展開, 爺爺之后是大伯, 然后是堂哥一家, 這個需要繼續展開;

二叉樹前序遍歷-左子樹的展開

然后是堂姐, 最后到你家, 也是需要進一步展開.

左子樹的繼續展開

繼續展開堂哥一家, 依然是按照 “根-左-右” 的順序.

先是堂哥, 然后左子樹, 這個大侄子這里沒有, 可能因為他太調皮搗蛋了, 堂哥不要他, 讓別人抱養走了;

二叉樹前序遍歷-左子樹的繼續展開

左子樹或者左節點沒有就跳過;

最后是右子樹, 你侄女, 或者說右節點, 小學剛畢業呢, 還沒到合法生娃的年紀, 下面沒人了, 所以展開到她這里也結束了.

左子樹的完全展開

這樣就完全確定了大伯一家子的采訪順序.

二叉樹前序遍歷-左子樹的完全展開

大伯之后是堂哥, 再之后是侄女, 最后是堂姐.

右子樹的展開

左子樹展開完了, 再看右子樹, 那就簡單了, 依然是按照 “根-左-右” 的順序,

二叉樹前序遍歷-右子樹的展開

先是爸爸這個根節點; 然后是左子樹, 或者說左節點, 也就是你, 光桿司令一個, 就不用繼續展開了; 最后是右子樹, 妹妹一家, 需要繼續展開.

右子樹的繼續展開

展開后就是這樣.

二叉樹前序遍歷-右子樹的繼續展開

先是根節點爸爸, 其次是左節點你, 最后是右子樹, 妹妹一家.

右子樹的完全展開

最后妹妹一家再展開. 還是 “根-左-右” 的順序:

二叉樹前序遍歷-右子樹的完全展開

先是根節點, 妹妹; 再到左節點, 你外甥;

然后是右節點, 暫時沒有, 還沒懷上呢, 或者還沒生出來, 還在媽媽肚子里喝羊水呢, 那就也不用管它, 跳過就完了.

至此, 這一大家子人的采訪順序就全部確定了.

二叉樹前序遍歷-右子樹的完全展開

顯然, 無論這棵樹有多深, 哪怕向天再借500年, 家族不斷繁衍, 子又生孫孫又生子, 子又有子子又有孫, 子子孫孫祖宗十八代, 照樣可以按照這同一條規則去確定遍歷的順序.

前序遍歷的總結

最后, 對前序遍歷做個總結.

記住 “根-左-右” 這個順序. 先是爺爺這個根節點, 然后左子樹, 右子樹.

二叉樹前序遍歷-根級別展開

左子樹里面, 又繼續按照 “根-左-右” 的順序:

二叉樹前序遍歷-左子樹級別展開

先是大伯這個根節點, 然后左子樹, 之后右節點堂姐.

再之后, 堂哥這里, 還是按照 “根-左-右” 的順序:

二叉樹前序遍歷-左子樹的子樹級別展開

當然這時沒有左子樹, 那跳過就行了, 先是根節點, 然后右節點.

而右子樹呢, 也是按照 “根-左-右, 根-左-右” 的順序不斷遞歸展開, 最終得到了前序遍歷下, 所有節點的訪問順序.

二叉樹前序遍歷-左右子樹的全部展開

二叉樹的中序遍歷

明白了前序遍歷后, 再來看中序遍歷, 就很容易理解了, 唯一的區別是訪問順序.

中序遍歷按照 “左-根-右” 的順序, 根節點在中間.

二叉樹的中序遍歷

先是左子樹, 堂哥一家子這次排在了最前;

然后才到根節點, 爺爺這里, 處于中間;

最后才是右子樹, 也是你爸爸一家.

而每一個子部分呢, 遞歸地按照 “左-根-右” 的順序展開, 直到完全展開成我們看到的這個順序.

在這里, 像爺爺, 大伯, 爸爸這些根節點呢, 大概是處在中間, 或者是每個子部分的中間

那么這就是中序遍歷, 也叫中根遍歷, 根在中間.

二叉樹的后序遍歷

最后, 來看下后序遍歷, 同樣的道理, 只是順序變成了 “左-右-根”, 根在最后.

讀者可自己依葫蘆畫瓢, 嘗試一下展開.

最終結果就是這樣, 每一子部分都是按照"左-右-根"的順序不斷展開, 最終許多根節點是相對處在后面的.

二叉樹的后序遍歷

讀者可以核對一下自己展開的結果是否正確. 如果有什么疑問, 可以對照著前面的前序和中序遍歷好好理解一下, 舉一反三, 因為道理都是類似的, 這里就不再展開那些細節了.

如果你得到了正確的訪問順序, 那可以說你已經正確地掌握了這三種遍歷形式.

二叉樹的遍歷總結

最后是對二叉樹這三種遍歷的一個總結.

  • 前序, 又叫 前根遍歷, 按照 “根-左-右” 的順序遞歸展開;
  • 中序, 又叫 中根遍歷, 按照 “左-根-右” 的順序遞歸展開;
  • 后序, 又叫 后根遍歷, 按照 “左-右-根” 的順序遞歸展開;

所以, 主要區別就在根的位置上.

二叉樹的前根, 中根和后根遍歷順序總結

  1. 首先, 前中后指的就是根的位置.
  2. 其次, 左右子樹則始終是先左后右.
  3. 最后, 遞歸應用以上規則直到子樹全部展開.

關于二叉樹的前序, 中序和后序這三種遍歷方式就講到這里, 謝謝大家.

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/45642.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/45642.shtml
英文地址,請注明出處:http://en.pswp.cn/web/45642.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

簡化流程,強化協作——揭秘可道云TeamOS文檔審批的實用魅力

在團隊協作的過程中,文檔審批是確保信息安全和流程規范的重要環節。然而,傳統的文檔審批流程往往繁瑣且僵化,難以滿足團隊快速響應和靈活協作的需求。 可道云teamOS的文檔審批功能,以其獨特的靈活性和便捷性,為團隊帶…

吸血鬼之戀

吸血鬼之戀 AI制作,吸血鬼之戀,BGM選自《暮光之城》,希望大家喜歡。 歡迎你分享你的作品到我們的平臺上:http://www.shxcj.com 或者 www.2img.ai 讓更多的人看到你的才華。 創作不易,覺得不錯的話,點個贊吧…

c++字符串實現join方法,使用模板

c字符串實現join方法&#xff0c;使用模板 主要記錄下類成員函數&#xff0c;申明為模板函數的寫法 注意定義迭代器時&#xff0c;前面需要加上typename關鍵字 typename std::vector<T>::iterator it;#pragma once #include <vector> #include <string>clas…

java——Junit單元測試

測試分類 黑盒測試&#xff1a;不輸入代碼&#xff0c;給輸入值&#xff0c;看程序能夠給出期望的值。 白盒測試&#xff1a;寫代碼&#xff0c;關注程序具體執行流程。 JUnit單元測試 一個測試框架&#xff0c;供java開發人員編寫單元測試。 是程序員測試&#xff0c;即白…

PBT激光穿透率測量儀

在現代材料科學與工業制造領域&#xff0c;激光技術以其高精度、高效率和非接觸性等特點&#xff0c;成為了不可或缺的測量與加工手段。其中&#xff0c;PBT&#xff08;聚對苯二甲酸丁二醇酯&#xff09;作為一種重要的熱塑性工程塑料&#xff0c;因其優異的機械性能、耐熱性和…

嵌入式全棧設計思路:STM32G4+ChibiOS+FreeRTOS+PID控制+PFC算法構建高效智能電源管理系統(附代碼示例)

智能電源管理系統是一個基于STM32G4微控制器的高性能數字電源控制解決方案。本項目旨在設計一個功能全面、高效穩定的電源管理系統,可廣泛應用于工業控制、新能源、通信設備等領域。 1.1 系統主要特點 高精度數字電源控制&#xff1a;利用STM32G4的高性能ADC和定時器,實現精確…

HTML5+CSS3小實例:純CSS實現奧運五環

實例:純CSS實現奧運五環 技術棧:HTML+CSS 效果: 源碼: 【HTML】 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-sca…

Spring MVC中Restful風格引入

一&#xff0c;RESTful概述 在現代Web應用開發中&#xff0c;RESTful架構風格已成為一種標準實踐&#xff0c;特別是在構建可擴展的Web服務時。Spring MVC提供了全面的支持來構建遵循REST原則的Web服務。我在此介紹如何在Spring MVC中實現RESTful風格的Web服務&#xff0c;并通…

【八大排序】java版(上)(冒泡、快排、堆排、選擇排序)

文章目錄 一、冒泡排序(重點)思路代碼 二、快排(面試重點)思路代碼 三、堆排序(面試重點)思路代碼 四、選擇排序思路代碼 一、冒泡排序(重點) 思路 前后兩兩數據進行比較&#xff0c;小的數據往前走&#xff0c;大的數據往后走&#xff0c;每一輪結束之后&#xff0c;最大的數…

網頁數據抓取:融合BeautifulSoup和Scrapy的高級爬蟲技術

網頁數據抓取&#xff1a;融合BeautifulSoup和Scrapy的高級爬蟲技術 在當今的大數據時代&#xff0c;網絡爬蟲技術已經成為獲取信息的重要手段之一。Python憑借其強大的庫支持&#xff0c;成為了進行網頁數據抓取的首選語言。在眾多的爬蟲庫中&#xff0c;BeautifulSoup和Scrap…

在Android Jetpack Compose中實現夜間模式

在Android Jetpack Compose中實現夜間模式 隨著用戶對夜間模式需求的增加,Android開發者需要掌握如何在應用中實現這一功能。Jetpack Compose作為現代Android UI工具包,提供了簡便且靈活的方式來實現夜間模式。本文將詳細介紹如何在Jetpack Compose中實現夜間模式,包括配置…

Linux系統之玩轉fortune命令

Linux系統之好玩的fortune命令 一、fortune命令介紹1.1 fortune簡介1.2 fortune中英文 二、本地環境介紹2.1 本地環境規劃2.2 本次實踐介紹 三、檢查本地環境3.1 檢查本地操作系統版本3.2 檢查系統內核版本 四、fortune英文版的使用4.1 安裝fortune英文版4.2 命令幫助4.3 fortu…

69、Flink 的 DataStream Connector 之 Kafka 連接器詳解

1.概述 Flink 提供了 Kafka 連接器使用精確一次&#xff08;Exactly-once&#xff09;的語義在 Kafka topic 中讀取和寫入數據。 目前還沒有 Flink 1.19 可用的連接器。 2.Kafka Source a&#xff09;使用方法 Kafka Source 提供了構建類來創建 KafkaSource 的實例。以下代…

安卓手機刷入Magisk面具教程

手機如果想獲取 Root 權限&#xff0c;刷入面具是必要的做法。本期文章將會教你如何刷入 Magisk 面具。 準備工作 Magisk: 關注微信公眾號 heStudio Community回復 magisk 獲取下載鏈接。第三方 Recovery&#xff08;官方 Recovery 能玩出什么花樣&#xff1f;&#xff1f;&a…

PDM系統:企業產品數據管理、PDM系統哪個好

PDM系統&#xff1a;企業產品數據管理、PDM系統哪個好 在當今這個數據驅動的時代&#xff0c;企業產品數據管理&#xff08;PDM&#xff09;系統已成為企業提升競爭力、加速產品創新、優化生產流程的關鍵工具。PDM系統不僅是一個技術平臺&#xff0c;更是企業實現數字化轉型的重…

防火墻負載分擔,帶寬策略

一、實驗拓撲圖 二、實驗要求 12&#xff0c;對現有網絡進行改造升級&#xff0c;將當個防火墻組網改成雙機熱備的組網形式&#xff0c;做負載分擔模式&#xff0c;游客區和DMZ區走FW3&#xff0c;生產區和辦公區的流量走FW1 13&#xff0c;辦公區上網用戶限制流量不超過100M&a…

昇思25天學習打卡營第23天|基于MobileNetv2的垃圾分類

基于MobileNetv2的垃圾分類 1、實驗目的 了解熟悉垃圾分類應用代碼的編寫&#xff08;Python語言&#xff09;&#xff1b;了解Linux操作系統的基本使用&#xff1b;掌握atc命令進行模型轉換的基本操作。 2、MobileNetv2模型原理介紹 MobileNet網絡是由Google團隊于2017年提…

在 Debian 12 上安裝 budgie-extras-common 包

在 Debian 12 上安裝 budgie-extras-common 包&#xff1a; 安裝前的準備 更新 apt 數據庫&#xff1a; 使用 apt-get:sudo apt-get update或者使用 apt:sudo apt update如果使用 aptitude&#xff08;通常不在 Debian 默認安裝中&#xff09;&#xff0c;首先需要安裝它&…

效能工具:執行 npm start 可直接切換proxy代理UR后直接啟動項目

1) 背景: 我們項目是2個前端3個后端的配置。前端和每個后端都有需要調試的接口。 因此經常切換vite.congig.js中的proxy后端代理鏈接&#xff0c;是挺麻煩的。 于是我研究如何能快速切換后端URL&#xff0c;所幸懶人有懶福&#xff0c;我找到了Inquirer 和 fs&#xff0c; 實…