日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

二叉树的非递归遍历(统一的模板)

發布時間:2025/3/19 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二叉树的非递归遍历(统一的模板) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

二叉樹的非遞歸遍歷

  • 前言
  • 樹的存儲結構
    • 先序遍歷
      • 先序的遞歸遍歷
      • 先序的非遞歸遍歷
    • 中序遍歷
      • 中序的遞歸遍歷
      • 中序遍歷的非遞歸算法
    • 后序遍歷
      • 后序的遞歸遍歷
      • 后序的非遞歸遍歷
    • 層次遍歷
    • 層次遍歷獲得每一層的節點個數

前言

以下是本博主用c語言創建棧和隊列的博文

  • 隊列

  • 二叉樹的基本操作

在二叉樹遍歷的時候,默認是先左子樹后右子樹。先,中,后是針對什么時候讀取根節點而言的。

先序,中序與后序都需要借助棧來實現。對于c沒有棧,所以本博主在代碼中的棧是自己用c語言寫的棧(鏈式棧),你們也可以依照自己的來改。在c++中就可以直接用STL中的了。

先序與中序的非遞歸過程可以通過這個圖片來理解。

后序的非遞歸過程可以通過這個圖片來理解。

樹的存儲結構

//樹的節點 typedef struct BiTNode {char data;struct BiTNode* left, * right; }BiTNode,*BiTree;

先序遍歷

先序的遞歸遍歷

/* 先序遍歷*/ //遞歸算法 void PreOrder(BiTree T) {if (T) {printf("%c ", T->data);PreOrder(T->left);PreOrder(T->right);} }

先序的非遞歸遍歷

算法思路

  • 先將根節點壓入棧中,用一個工作指針node(初始值為根節點)
  • 步驟1 遍歷當前節點node的左子樹,直到左子樹為空。(在這里輸出)
  • 步驟2 彈出棧頂的空指針
  • 步驟3 如果棧沒有空,將棧頂元素彈出賦值給node,將node->right壓入棧

代碼:

void PreOrder_S(BiTree T) {if (!T) return;LinkStack S = (SNode*)malloc(sizeof(SNode));init(S);//初始化鏈式棧,使其置為空Push_L(S, T); //將根節點壓入BiTNode* node = Top_L(S); while (!empty(S)) {// 一直往左子樹方向走,直到遇到空的節點while (node) {printf("%c ", node->data);node = node->left; //置當前節點為其左子樹Push_L(S, node); //壓入}//上面循環結束的時候,在最后壓入了一個空節點Pop_L(S); //彈出空節點if (!empty(S)) {//從棧頂彈出元素賦值給nodenode = Top_L(S); Pop_L(S);node = node->right;//置為其右子樹Push_L(S, node);//壓入}} }

中序遍歷

中序的遞歸遍歷

/* 中序遍歷*/ //遞歸算法 void InOrder(BiTree T) {if (T) {InOrder(T->left);printf("%c ", T->data);InOrder(T->right);} }

中序遍歷的非遞歸算法

算法的基本思路:

  • 先將根節點壓入棧中,用一個工作指針node(初始值為根節點)
  • 步驟1 遍歷當前節點node的左子樹,直到左子樹為空。
  • 步驟2 彈出棧頂的空指針
  • 步驟3 如果棧沒有空,將棧頂元素彈出賦值給node(在這里輸出),將node->right壓入棧

代碼:

void InOrder_S(BiTree T) {if (!T) return;LinkStack S = (SNode*)malloc(sizeof(SNode));init(S);Push_L(S, T);BiTNode* node = Top_L(S);while (!empty(S)) {while (node) {node = node->left;Push_L(S, node);}Pop_L(S);//空指針退棧if (!empty(S)) {//從棧頂彈出元素賦值給nodenode = Top_L(S);Pop_L(S);printf("%c ", node->data);node = node->right;//置為其右子樹Push_L(S, node);//壓入}}}

后序遍歷

后序的遞歸遍歷

/* 后序遍歷*/ //遞歸算法 void PostOrder(BiTree T) {if (T) {PostOrder(T->left);PostOrder(T->right);printf("%c ", T->data);} }

后序的非遞歸遍歷

算法的基本思路:

  • 因為后序遍歷的時候一個二叉樹的根節點會訪問兩次
  • 設置一個標記,在第一次訪問的時候不用出棧,只用讀取即可
  • 在第二次訪問時就出棧
  • 步驟一 遍歷當前節點node的左子樹,直到左子樹為空。
  • 步驟二 彈出棧頂的空指針,設置flag = 1,T = NULL
  • 步驟三 遍歷該節點的右子樹,如果右子樹為空,或者已經訪問兩次了就出棧
  • 否則 就node = node->right,然后將node壓入棧中

代碼:

void PostOrder_S(BiTree T) {if (!T) return;LinkStack S = (SNode*)malloc(sizeof(SNode));int flag;init(S);Push_L(S, T);BiTNode* node = Top_L(S);while (!empty(S)) {//向左移動到盡頭while (node) {node = node->left;Push_L(S, node);}//空指針退棧Pop_L(S);//T指向 棧頂節點前一個已經訪問過的節點//初始值為NULL,是棧頂節點右子樹為空也可以直接輸出了T = NULL;flag = 1;while (!empty(S) && flag) { //變循環了//取出當前棧頂元素node = Top_L(S);//右節點為空,或者右節點已經訪問過了if (node->right == T) {printf("%c ", node->data);Pop_L(S);//T指向被訪問的節點T = node;}else {//否則將右節點插入node = node->right;Push_L(S, node);//設置未被訪問的標記flag = 0; }}} }

層次遍歷

/*層次遍歷*/ void LevelOrder(BiTree T) {if (!T)return;LinkQueue Q;init(Q); //初始化隊列push(Q, T);//將根節點壓入隊列while (!empty(Q)) {BiTNode* node = font(Q);pop(Q);printf("%c ", node->data);if (node->left)push(Q,node->left);if (node->right)push(Q, node->right);}}

層次遍歷獲得每一層的節點個數

思路:想比于普通的層次遍歷只循環一次且只用到一個隊列,這個算法需要用到兩個隊列,并且在一個循環中,還要嵌套一個循環。之前在每一次都將不為空的節點插入一個隊列中,因此除非節點全部遍歷在停止而不能得到具體的層的節點。因此我們將左右孩子的節點先放在一個輔助隊列里邊。直到將原隊列的節點遍歷完,那么該次遍歷的就是該層節點,輔助隊列里邊的則是下一層的節點,在內層循環結束后,將輔助隊列的元素賦值給原隊列,同時層數+1。

void traverseByLevel(node* root) {if (root) {queue<node*>que;que.push(root);int level = 1; //記錄當前層數while (que.size()) {queue<node*>assist;if (que.front() != root) { //第一行后都需要輸出換行cout << endl;}bool flag = true;cout << "第" << level << "有" << que.size() << "個結點" << endl;while (que.size()) {node* p = que.front();que.pop();if (p->lchild) {assist.push(p->lchild);}if (p->rchild) {assist.push(p->rchild);}if (false == flag) { //每行第2個元素開始 輸出元素時前面加空格cout << " ";}cout << p->data ;flag = false;}level++;que = assist;}} }

總結

以上是生活随笔為你收集整理的二叉树的非递归遍历(统一的模板)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。