二叉樹的遍歷之迭代遍歷

前言:在學習二叉樹的時候我們基本上已經了解過二叉樹的三種遍歷,對于這三種遍歷,我們采用遞歸的思路,很簡單的就能實現,那么如何用迭代的方法去解決問題?

我們首先來看第一個:

前序遍歷

144. 二叉樹的前序遍歷 - 力扣(LeetCode)

前序遍歷就是以 根 左子樹 右子樹的順序遍歷二叉樹。呢么如何用得帶去解決問題呢?

首先我們知道函數遞歸就是函數一層層的調用自己,本質上是以一種先進后退的思路,而這與棧的特性一致,因此函數遞歸,我們可以用調用堆棧來看,就是棧的思路。

現在我們解決問題,既然不用遞歸,但還是可以用到解決問題的本質思路,就是用棧去解決問題:

例圖:

?我們就用這個圖做演示:

大致解題思路:由于二叉樹遍歷一直往下走,無法回頭,我們需要提供一個棧,假設我們每次先遍歷左子樹,每次遍歷的時候,將我們需要往回遍歷的節點放入棧中(往回遍歷的節點就是擁有右子樹的系點),在遍歷完左節點后,此時回退上一個節點,看他的右子樹是否為空。

且我們的整個循環的條件中 棧是否為空 就決定是否繼續遍歷這一個二叉樹。

首先前序遍歷的順序 是根? 左子樹 右子樹 。其次,對于二叉樹,解決了整個左子樹的遍歷。那么整個右子樹的遍歷,也是與之相同的,也就是我們再解決問題時就只針對一個子樹,這里我們就以遍歷整個左子樹為主,實現對整個樹的遍歷。且題目要求返回數組,因此我們是遍歷插入數據。

由于我們無法知道某個左節點的右節點是否為空,所以開始我們先將所有左節點入棧:

第一步操作:

首先要遍歷根,也就是從1開始,不為空,放入數組,并入棧,在看它的左,2不為空,放入數組,并入棧,再看它的左,3,不為空,放入數組并入棧。我們就完成了第一步,但是對于最后一個最左節點(它可能是一個子樹的根,他也有可能是子樹的左節點)。

第二步操作:

從這里開始,我們就要開始判斷是否出棧,此時獲取當前棧頂元素,3節點,再出棧。(此時棧不為空)

? ?若3節點無右節點,此時根已經遍歷完了,現在輪到左子樹了,而3此時是作為一個子樹的左節點,并且是遍歷順序左子樹中的第一個節點,之后出棧,看節點2的右子樹是否存在。

? ?若3節點有右節點(右子樹),比如我們這里就是節點4,3節點就往右子樹走,按照前序遍歷順序,我們該將此節點數據放入數組中,因此以該節點為開始,繼續第一步操作,將該右節點(也有可能是右子樹),按照先把左節點入棧,入數組,在判斷右子樹情況來出棧。

第三步操作:

其實我們的前序遍歷已經實現,可能有人還覺得還沒完成,因為右子樹還沒處理,實際上當我們回退二叉樹,也就是出棧的時候,出到最后一個元素,也就是真正的根節點時,棧不為空,循環還沒結束,會繼續判斷當前節點的右子樹。

代碼實現:

vector<int> preorderTraversal(TreeNode* root) {//用來返回遍歷結果的數組vector<int> v;//用棧來回退我們二叉樹stack<TreeNode*> t;TreeNode*node=root;//當節點為空或者棧不為空的時候循環繼續while(node||!t.empty()){//第一步將左邊的節點一次放入數組并入棧 while(node){v.push_back(node->val);t.push(node);node=node->left;}//從該位置開始判斷是否要出棧node=t.top();t.pop();if(node->right==nullptr){node=nullptr;//直接為空,繼續循環進入到出棧操作}else{node=node->right;}      }return v;}

中序遍歷

中序遍歷 的順序是?左節點 根 右子樹 。與前序的插入思想不太一樣,不過還是利用棧來回到上一個節點。前序遍歷時,其實是有點巧合,因為根節點與左節點連續,我們是直接將左節點一個個入棧后,直接放入數組,因為順序是從根節點開始,且根節點下來就是左節點,因此插入順序與我們的直接將左節點插入的順序一致。

但對于中序和后序遍歷,都是先從左節點開始的,因此,從根開始,我們是先將之后的左節點一個個入棧,這里就不能再放數組了,直到最左節點時,根據我們的的遍歷順序,下來時根節點,再來判斷。具體分析如下:

還是以這張圖為例:

第一步:

剛開始我們還是直接以根為開始,將它的一個個左節點入棧,此時棧中為3,2,1。

第二步:

從這里開始,就需要判斷是否出棧,是否插入數組,因此從這里開始,還是先獲取棧頂元素,在出棧,當前位置就是節點3,之后就是判斷3節點是否具有右子樹。

若沒有右子樹,那么3就是第一個左節點,放入數組,之后回退到上一個節點2,繼續判斷。

若有右子樹,此時節點3是一個根,不能放入數組,我們繼續走到節點4,以4節點為開始,與前序遍歷一樣,執行第一步的操作進行入棧,之后在判斷。

直到回退到根節點,此時進行右子樹的遍歷。

代碼如下:

  vector<int> inorderTraversal(TreeNode* root) {vector<int> v;stack<TreeNode*> t;TreeNode* prev=nullptr;while(root||!t.empty()){while(root){if(root){t.push(root);}root=root->left;}root=t.top();t.pop();      //為空先插左節點v.push_back(root->val);if(root->right==nullptr){root=nullptr;}else{root=root->right;}}return v;}

?后序遍歷

后序遍歷的思路與中序遍歷有些許一樣,但對于情況的判斷更加復雜。

因為后序的遍歷順序為 左子樹? 右子樹 根,育賢婿一樣,我們還是從根節點開始,入棧左子樹的所有左節點,直到最左節點,還是要進行判斷。具體分析如下:

?還是一這張圖為例:

第一步:

依然是將左子樹的所有的左節點依次入棧, 1入,2入,3入,此時到了節點3。

第二步:

從節點3開始判斷是否要回退,因此獲取棧頂節點為3,出棧,當前節點為3。

若3沒有右節點,此時我們就是左節點,我們就可以將3放入數組,之后回退到節點2。

若3的右節點存在,此時的操作是將該節點再次重新入棧(因為下一個右節點(右子樹)插入完才輪到我),之后當前節點走到這個右節點,循環回到第一步,繼續入棧。

在這里有重要的一點:

第一點:與之前兩種遍歷一樣,我們需要從當前節點回退到上個節點的方法是將指針置空,之后重新賦值為棧頂元素的節點。

其次除了葉子節點容易判斷插入,如果上一次插入的節點,是當前節點的右節點,則就需要放入數組里,即 先插的左, 之后插的右,根節點需要判斷,當前節點的右節點是上一次插入的節點就說明是根,插入數組。

源碼:

vector<int> postorderTraversal(TreeNode* root) {stack<TreeNode*>s;vector<int> ret;TreeNode*prev=nullptr;while(root||!s.empty()){//先找所有的左節點while(root){ s.push(root);root=root->left;}//倒退判斷這些節點的右節點,直到最后根節點,在判斷右子樹root=s.top(); s.pop();if(root->right==nullptr ||root->right==prev) {ret.push_back(root->val);prev=root;root=nullptr;}else{//若右子樹不為空,繼續入棧s.push(root);root=root->right;}}return ret;}

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

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

相關文章

【計算機網絡學習之路】HTTP請求

目錄 前言 HTTP請求報文格式 一. 請求行 HTTP請求方法 GET和POST的區別 URL 二. 請求頭 常見的Header 常見的額請求體數據類型 三. 請求體 結束語 前言 HTTP是應用層的一個協議。實際我們訪問一個網頁&#xff0c;都會像該網頁的服務器發送HTTP請求&#xff0c;服務…

chrome 調試之 - 給微軟小冰看病(無論給小冰發送什么內容都只回復“我已經開始升級啦,期待一下吧!”)

微軟 Bing 搜索推出了小冰AI智能聊天模塊&#xff0c;具體啟用方式是用edge或chrome瀏覽器打開鏈接 cn.bing.com 后在輸入框搜索任意內容&#xff0c;待搜索結果頁面加載完并稍等片刻&#xff0c;頁面右側就會出現一個躲在滾動條后面的小蘿莉&#xff0c;撫摸...不&#xff0c;…

Java-網絡通信總結

文章目錄 網絡程序設計基礎局域網與互聯網 網絡協議IP協議TCP/IP 協議端口域套接字 TCP 程序InterAddress 類ServerSocket 類 UDP 程序DatagramPacket 類DatagramSocket 類 網絡程序設計基礎 網絡程序設計編寫的是與其他計算機進行通信的程序。Java 已經將網絡程序所需要的元素…

RK3588平臺開發系列講解(hardware)reference-ril源碼分析

平臺內核版本安卓版本RK3588Linux 5.10Android 12文章目錄 一、reference-ril目錄介紹二、支持的功能三、Android RIL 框架沉淀、分享、成長,讓自己和他人都能有所收獲!?? 一、reference-ril目錄介紹 目錄:3588-android12/hardware/ril/reference-ril

ElementUI 時間選擇器如何限定選擇時間

DatePicker 日期選擇器 | Element Plus 我們如何限定我們的選擇時間呢&#xff0c;比如限定選擇時間為今天之前&#xff0c;或者今天之后的時間&#xff1f; 我們可以使用官方提供的disabled-date來實現 我們通過這個屬性 做一個回調函數&#xff0c;在里面比較我們想要限定的時…

MongoDB數據建模與文檔設計

目錄 1. 文檔數據庫的概念 2. 數據建模的最佳實踐 3. 復雜文檔結構的設計 4. Java代碼實踐 1. 文檔數據庫的概念 MongoDB文檔模型&#xff1a; MongoDB是一種文檔數據庫&#xff0c;它以BSON&#xff08;Binary JSON&#xff09;格式存儲數據。文檔是MongoDB中基本的數據單…

#HarmonyOS:基礎語法

基礎語法 定義了聲明式UI描述&#xff1b; 自定義組件&#xff1b; 動態擴展UI元素的能力&#xff1b; 狀態管理 多維度裝填管理機制&#xff1b;父子組件間爺孫組件間全局范圍內傳遞跨設備傳遞只讀的單向傳遞可變的雙向傳遞 渲染控制 UI描述&#xff1a;以聲明式的方式來…

鴻蒙方舟開發框架ArkUI簡介

語雀知識庫地址&#xff1a;語雀HarmonyOS知識庫 飛書知識庫地址&#xff1a;飛書HarmonyOS知識庫 嗨&#xff0c;各位別來無恙吶&#xff0c;我是小白 眾所周知&#xff0c;華為在今年推出了 HarmonyOS 4.0 版本&#xff0c;而在此之前的版本中&#xff0c;HarmonyOS 應用的 …

2024年AI視頻識別技術的6大發展趨勢預測

隨著人工智能技術的快速發展&#xff0c;AI視頻識別技術也將會得到進一步的發展和應用。2023年已經進入尾聲&#xff0c;2024年即將來臨&#xff0c;那么AI視頻識別技術又將迎來怎樣的發展趨勢&#xff1f;本文將對2023年的AI視頻技術做一個簡單的盤點并對2024年的發展趨勢進行…

Advanced Renamer

Advanced Renamer 安裝鏈接 1.前后添加字符 2.字符轉數字&#xff0c;編號整體加減

oracle實驗2023-12-8--觸發器

第十四周實驗 【例】功能要求&#xff1a;增加一新表XS_1&#xff0c;表結構和表XS相同&#xff0c;用來存放從XS表中刪除的記錄。 分析: 1、創建表 xs_1 SQL> create table xs_1 as select * from xs; Table created SQL> truncate table xs_1; Table truncated題目&a…

StoneDB-8.0-V2.2.0 企業版正式發布!性能優化,穩定性提升,持續公測中!

? 11月&#xff0c;StoneDB 新版本如期而至&#xff0c;這一個月來我們的研發同學加班加點&#xff0c;持續迭代&#xff1a;在 2.2.0 版本中&#xff0c;我們針對用戶提出的需求和做出了重量級更新&#xff0c;修復了一些已知和用戶反饋的 Bug&#xff0c;同時對部分代碼進行…

PairLIE論文閱讀筆記

PairLIE論文閱讀筆記 論文為2023CVPR的Learning a Simple Low-light Image Enhancer from Paired Low-light Instances.論文鏈接如下&#xff1a; openaccess.thecvf.com/content/CVPR2023/papers/Fu_Learning_a_Simple_Low-Light_Image_Enhancer_From_Paired_Low-Light_Instan…

Kafka安全性探究:構建可信賴的分布式消息系統

在本文中&#xff0c;將研究Kafka的安全性&#xff0c;探討如何確保數據在傳輸和存儲過程中的完整性、機密性以及授權訪問。通過詳實的示例代碼&#xff0c;全面討論Kafka安全性的各個方面&#xff0c;從加密通信到訪問控制&#xff0c;幫助大家構建一個可信賴的分布式消息系統…

vue3 setup router的使用教程

vue3 setup router的使用教程 文章目錄 vue3 setup router的使用教程1. 安裝2. 使用&#xff08;創建路由實例&#xff09;3. 路由跳轉3.1 通過router-link標簽跳轉3.2 通過js代碼跳轉 4. 接收參數4.1 通過query接收參數4.2 通過params接收參數 5. 路由守衛5.1 全局守衛5.2 路由…

阿里云docker加速

文章目錄 一、 阿里云鏡像倉庫配置二、配置加速1. CentOS2. Mac3. Windows注意 一、 阿里云鏡像倉庫配置 1.注冊阿里云賬號&#xff0c;并登陸到阿里云后臺&#xff0c;進入控制臺面板 2.進入控制臺以后&#xff0c;找到左上方的三橫的功能列表按鈕&#xff0c;在彈出來的功能…

智能手機IC

智能手機IC 電子元器件百科 文章目錄 智能手機IC前言一、智能手機IC是什么二、智能手機IC的類別三、智能手機IC應用實例四、智能手機IC作用總結前言 智能手機IC通過相互配合和協同工作,支持智能手機的各種功能和特性,如高速計算、多媒體處理、無線通信、圖形渲染、傳感器數據…

G1 GC基本邏輯

1 MixedGC基本過程 在G1GC中&#xff0c;有兩種主要的垃圾回收過程&#xff1a;Young GC和Mixed GC。這兩者都是為了回收堆內存中的垃圾對象&#xff0c;但是他們關注的區域和工作方式有所不同。 Young GC&#xff1a; Young GC主要負責回收Young Generation&#xff08;包括…

跟著GPT學設計模式之建造者模式

Builder 模式&#xff0c;中文翻譯為建造者模式或者構建者模式&#xff0c;也有人叫它生成器模式。允許你創建不同口味的對象同時避免構造器污染。當一個對象可能有幾種口味&#xff0c;或者一個對象的創建涉及到很多步驟時會很有用。 現實世界例子&#xff1a;想象一個角色扮…

Vue:用IDEA開發Vue,標簽語法爆紅問題處理

一、場景描述 我在IDEA中&#xff0c;學習Vue課程。 入門學習時&#xff0c;是在html文件中&#xff0c;script引入vue.js文件方式。 此時&#xff0c;在html文件中用v-標簽&#xff0c;爆紅。 二、解決辦法 打開 菜單欄 File - Settings 選擇 Editor - Files Type&#xf…