算法力扣刷題 三十六【二叉樹迭代遍歷】

前言

記錄三十五 介紹了二叉樹基礎,和遞歸法模版及遍歷方式;
遞歸:代碼簡單,但要想清楚三步:

  • 確定參數和返回值;
  • 確定終止條件,并return什么?;
  • 終止條件外的邏輯,在哪里做到自己調用自己?——應該是出現嵌套時候,要重復操作的時候。

遞歸的問題:遞歸次數多,開的新棧多,內存空間占用大。

如果二叉樹前中后序遍歷使用非遞歸方法,怎么操作?


一、“輸入”學習階段

學習參考鏈接

解釋迭代

重復執行一段代碼,直到滿足某個條件后停止。用循環可以實現重復;(遞歸也是重復)。

前序遍歷

過程

模擬遞歸過程,用結構棧。

  • 先把根節點放到棧中,再取出根節點加入遍歷數組;
  • 先放入右孩子,再放入左孩子。(左孩子先出來,說明先處理左子樹)。
  • 直到棧為空。
  • 總結:取出根節點,拿右孩子和左孩子入棧交換。先訪問到中節點,可以直接處理中節點;再訪問到左孩子(后入棧),處理左子樹;再訪問到右孩子(先入棧),處理右子樹。訪問節點順序=處理節點順序

代碼實現

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*> st;st.push(root);while(!st.empty()){TreeNode* cur = st.top();st.pop();if(cur != nullptr){result.push_back(cur->val);st.push(cur->right);	//如果cur是葉子節點,把空也入棧,但是取到空的時候不操作。st.push(cur->left);}}return result;}
};

上面的實現:把葉子結點的左右孩子是空,也入棧,但是不操作。

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*> st;if(root == nullptr) return result;st.push(root);while(!st.empty()){TreeNode* cur = st.top();st.pop();result.push_back(cur->val);if(cur->right) st.push(cur->right);if(cur->left) st.push(cur->left);}return result;}
};

這是參考代碼,空就不入棧,所以可以在pop之后直接push_back。

后序遍歷

過程

  • 前序實現得到:中左右;
  • 如果先放左孩子,再放右孩子;得到中右左;
  • 把result最后整體reverse,得到左右中。
  • 總結:先訪問到中節點,可以直接處理中節點;再訪問到右孩子(后入棧),處理右子樹;再訪問到左孩子(先入棧),處理左子樹。訪問節點順序=處理節點順序。最后reverse結果。

代碼實現

參考代碼:

/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode* > st;if(root == nullptr) return result;st.push(root);while(!st.empty()){TreeNode* cur = st.top();st.pop();result.push_back(cur->val);if(cur->left) st.push(cur->left);if(cur->right) st.push(cur->right);}reverse(result.begin(),result.end());return result;}
};

中序遍歷

過程

有所區別原因:訪問節點順序不等于處理節點順序。每一次先接觸中間節點,但不能處理它,要找它的左子樹;找到左子樹,再處理它;再找右子樹。

  • 用棧來記錄遍歷過的元素,雖然訪問到但是還沒到要處理的時候。
  • cur != 空,作為中節點,放入棧中;cur = cur->left;把left給到下一棒。
  • 如果遇到空,說明左子樹結束;需要從棧中取元素,放入result,st.pop();cur = cur->right;再把right給到下一棒。
  • 當cur == 空且st棧為空,終止。cur==空,說明訪問結束;st等于空,說明沒有中節點可以取。

代碼實現

  • 根據思路,先自我實現:
    /*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
    class Solution {
    public:vector<int> inorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*> st;if(root == nullptr) return result;st.push(root);TreeNode* cur = root->left;while(1){if(cur != nullptr){st.push(cur);cur = cur->left;}else{if(st.empty()) break;cur = st.top();st.pop();result.push_back(cur->val);cur = cur->right;}}return result;}
    };
    
  • 對照參考代碼:
    去掉 if(st.empty()) break; while條件改為(cur != nullptr || !st.empty())

二、統一迭代遍歷實現

學習參考鏈接

思路學習

標記法

  • 訪問的節點放入棧中,把要處理的節點也放入棧中但是標記要處理的節點。
  • 如何標記?要處理的節點放入棧之后,緊接著放入一個空指針作為標記

代碼實現

  • 前序遍歷:中左右。所以cur不為空時,入棧順序:右左中。
/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*> st;if(root != nullptr) {st.push(root);}while(!st.empty()){TreeNode* cur = st.top();if(cur != nullptr){st.pop();if(cur->right) st.push(cur->right);//先放入右孩子if(cur->left) st.push(cur->left); //再放入左孩子st.push(cur);   //放入中節點,緊跟著NULL,代表處理過,它下一輪該進resultst.push(nullptr);}else{st.pop();   //把空指針先彈出TreeNode* temp = st.top();//獲取入數組的元素st.pop();   //彈出該元素result.push_back(temp->val); }}return result;}
};
  • 中序遍歷:左中右。所以cur不為空時,入棧順序:右中左。
/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:vector<int> preorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*> st;if(root != nullptr) {st.push(root);}while(!st.empty()){TreeNode* cur = st.top();if(cur != nullptr){st.pop();if(cur->right) st.push(cur->right);//先放入右孩子st.push(cur);   //放入中節點,緊跟著NULL,代表處理過,它下一輪該進resultst.push(nullptr);if(cur->left) st.push(cur->left); //再放入左孩子}else{st.pop();   //把空指針先彈出TreeNode* temp = st.top();//獲取入數組的元素st.pop();   //彈出該元素result.push_back(temp->val); }}return result;}
};
  • 后序遍歷:左右中。所以cur不為空時,入棧順序:中右左。
/*** Definition for a binary tree node.* struct TreeNode {*     int val;*     TreeNode *left;*     TreeNode *right;*     TreeNode() : val(0), left(nullptr), right(nullptr) {}*     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}*     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}* };*/
class Solution {
public:vector<int> postorderTraversal(TreeNode* root) {vector<int> result;stack<TreeNode*> st;if(root != nullptr) st.push(root);while(!st.empty()){TreeNode* cur = st.top();if(cur != nullptr){st.push(nullptr);	//先放中節點,直接放null,標記下if(cur->right) st.push(cur->right);//再放右孩子if(cur->left) st.push(cur->left);//再放左孩子}else{st.pop();TreeNode* temp = st.top();st.pop();result.push_back(temp->val);}}return result;}
};

總結

本文學習迭代遍歷二叉樹。用循環+棧處理。

  • 非統一的方法:
    • 前序遍歷:根節點先入棧,每出棧一個根節點,就把右左孩子放入。相當于交換。
    • 后序遍歷:中左右——中右左——左右中;
    • 中序遍歷:棧放遍歷的元素,不為空,把left交到下一棒;為空,取出中節點;把right交到下一棒。
  • 統一方法:標記法。要處理的節點后面緊跟著是null,取到棧頂是空,代表要入棧。直到整個棧空。
    • 前序遍歷:不為空,放入順序:右左中;
    • 中序遍歷:不為空,放入順序:右中左;
    • 后序遍歷:不為空,放入順序:中右左;

(歡迎指正,轉載標明出處)

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

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

相關文章

【AI大模型】賦能兒童安全:樓層與室內定位實踐與未來發展

文章目錄 引言第一章&#xff1a;AI與室內定位技術1.1 AI技術概述1.2 室內定位技術概述1.3 樓層定位的挑戰與解決方案 第二章&#xff1a;兒童定位與安全監控的需求2.1 兒童安全問題的現狀2.2 智能穿戴設備的興起 第三章&#xff1a;技術實現細節3.1 硬件設計與選擇傳感器選擇與…

SpringSecurity中文文檔(Servlet Authorization Architecture )

Authorization 在確定了用戶將如何進行身份驗證之后&#xff0c;還需要配置應用程序的授權規則。 Spring Security 中的高級授權功能是其受歡迎的最有說服力的原因之一。無論您選擇如何進行身份驗證(無論是使用 Spring Security 提供的機制和提供者&#xff0c;還是與容器或其…

兩張圖片合并(右上角添加水印,兼容矢量圖)保留原來的顏色

無縫合并兩張圖片&#xff08;封面右上角添加logo&#xff09;-- opencv &#xff1a; 進行添加logo(水印)由于使用了cv2.seamlessClone&#xff0c;cv2.seamlessClone使用了泊松克隆&#xff08;Poisson Cloning&#xff09;&#xff0c;會根據周圍的顏色信息進行顏色調整&…

tcp并發設計

4注意&#xff1a;原始代碼&#xff0c;如果先關閉服務器端&#xff0c;再次開啟服務器的時候會報"connect: Connection refused "錯誤&#xff0c;這是因為先關服務器端&#xff0c;導致系統認為客戶端仍然在與服務器端連接造成。 可以使用setsockopt setsockopt函…

three-tile 一個開源的輕量級三維瓦片庫

three-tile 介紹 three-tile 是一個開源的輕量級三維瓦片庫&#xff0c;它基于threejs使用typescript開發&#xff0c;提供一個三維地形模型&#xff0c;能輕松給你的應用增加三維瓦片地圖。 源碼&#xff1a;https://github.com/sxguojf/three-tile 示例&#xff1a;https:/…

【TB作品】51單片機 Proteus仿真 00013紅外proteus仿真循跡避障小車

實驗報告&#xff1a;智能小車系統設計與實現 一、背景介紹 本實驗旨在設計并實現一個基于STC89C52單片機控制的智能小車系統。該系統通過超聲波傳感器進行避障&#xff0c;通過紅外接收器實現遠程控制&#xff0c;同時具備循跡功能。整個系統的核心是單片機&#xff0c;它通…

YOLOv10改進 | 損失函數篇 | InnerIoU、InnerSIoU、InnerWIoU、FocusIoU等損失函數

一、本文介紹 本文給大家帶來的是YOLOv10最新改進&#xff0c;為大家帶來最近新提出的InnerIoU的內容同時用Inner的思想結合SIoU、WIoU、GIoU、DIoU、EIOU、CIoU等損失函數&#xff0c;形成 InnerIoU、InnerSIoU、InnerWIoU、等新版本損失函數&#xff0c;同時還結合了Focus和…

LeetCode42(接雨水)[三種解法:理解動態規劃,雙指針,單調棧]

接雨水 給定 n 個非負整數表示每個寬度為 1 的柱子的高度圖&#xff0c;計算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 這是一道困難題,難度確實有點層次.我們先來樸素思想走一波. 要求能接多少雨水,我們可以具化到每個硅谷,每個硅谷能存多少雨水,那么答案就是每個…

PDA:Prompt-based Distribution Alignment for Unsupervised Domain Adaptation

文章匯總 式中&#xff0c; y s y^s ys表示源域數據的one-hot ground-truth&#xff0c; K K K為類數&#xff0c; w i w_i wi?和 z ~ s \tilde{z}_s z~s?分別表示源域經過提示調優的最終文本表示和最終圖像表示的第 i i i類。 同理&#xff0c;為了進一步利用目標領域的數據…

防火墻詳解(USG6000V)

0、防火墻組網模式 防火墻能夠工作在三種模式下分別是路由模式、透明模式、旁路檢測模式、混合模式 0.1、路由模式 路由模式&#xff1a;防火墻全部以第三層對外連接&#xff0c;即接口具有IP 地址。一般都用在防火墻是邊界的場景下 防火墻需要的部署/配置&#xff1a; 接…

【入門篇】STM32尋址范圍(更新中)

寫在前面 STM32的尋址范圍涉及存儲器映射和32位地址線的使用。并且STM32的內存地址訪問是按字節編址的,即每個存儲單元是1字節(8位)。 一、尋址大小與范圍 地址線根數 地址編號(二進制) 地址編號數(即內存大小) <

實現基于Elasticsearch的搜索服務

實現基于Elasticsearch的搜索服務 大家好&#xff0c;我是微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 1. Elasticsearch簡介 Elasticsearch是一個開源的分布式搜索引擎&#xff0c;提供強大的全文搜索和分析功能。本文…

10、DDD分層架構

微服務架構模型有很多種&#xff0c;例如洋蔥架構、CQRS和六邊形架構等。雖然這些架構模式提出的時代和背景不同&#xff0c;但其核心理念都是為了設計出“高內聚&#xff0c;低耦合”的微服務&#xff0c;輕松實現微服務的架構演進。DDD分層架構的出現&#xff0c;使微服務的架…

什么是ThreadLocal以及內存泄漏問題、hash沖突問題

ThreadLocal是什么 ThreadLocal類用來提供線程內部的局部變量 它主要有三大特性&#xff1a; 線程安全: 在多線程并發的場景下保證線程安全傳遞數據&#xff1a;通過ThreadLocal在同一線程傳遞公共變量線程隔離&#xff1a;每個線程的變量都是獨立的&#xff0c;不會互相影響…

這次讓我們從幾個點認識一下Mysql的Innodb

MySQL 的 InnoDB 存儲引擎是 MySQL 默認和最常用的存儲引擎之一。它主要關注的是高可靠性、性能以及完整的事務支持。以下是對 InnoDB 存儲引擎的詳細介紹&#xff1a; 1. 數據庫特性 1.1 事務支持 InnoDB 是完全支持事務的存儲引擎&#xff0c;支持四種主要的事務隔離級別&…

【uniapp-ios】App端與webview端相互通信的方法以及注意事項

前言 在開發中&#xff0c;使用uniapp開發的項目開發效率是極高的&#xff0c;使用一套代碼就能夠同時在多端上線&#xff0c;像筆者之前寫過的使用Flutter端和webview端之間的相互通信方法和問題&#xff0c;這種方式本質上實際上是h5和h5之間的通信&#xff0c;網上有非常多…

ios身份證實名認證接口開發示例助力電商物流實名認證

為了更好的利用貨車資源&#xff0c;也方便企業正常的運送貨物&#xff0c;“互聯網電商”平臺可謂風起云涌。貨車司機和有發貨需求的人們可以在物流平臺注冊&#xff0c;貨車司機接單為有運送需求的用戶提供有償貨運服務。那么&#xff0c;如何讓企業放心的將貨物安心的交予貨…

物聯網實訓室建設可行性報告

一、建設物聯網實訓室的目的和意義 隨著信息技術的快速發展&#xff0c;物聯網&#xff08;IoT&#xff09;已成為推動社會進步和經濟發展的關鍵技術之一。物聯網技術的集成應用&#xff0c;不僅能夠提高生產效率&#xff0c;還能促進智慧城市、智能家居、智能農業等多個領域的…

python04——類(基礎new)

類其實也是一種封裝的思想&#xff0c;類就是把變量、方法等封裝在一起&#xff0c;然后可以通過不同的實例化對其進行調用操作。 1.類的定義 class 類名&#xff1a; 變量a def __init__ (self,參數2&#xff0c;參數2...)&#xff1a;初始化函數&#xff01;&#xff01;&…

vivado DELAY_VALUE_XPHY、DIFF_TERM

延遲_值_XPHY PORT對象上的DELAY_VALUE_XPHY屬性指定要添加的延遲量 Versal XPHY邏輯接口的輸入或輸出路徑。在的早期階段 opt_design在重新生成高級I/O向導IP時 DELAY_VALUE_XPHY值將從PORT復制到的XPHY實例上 輸入或輸出路徑。Vivado設計套件中存在DRCs&#xff0c;以確保 DE…