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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

二叉树的遍历总结

發布時間:2025/3/21 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二叉树的遍历总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

二叉樹的遍歷總結

文章目錄

  • 二叉樹的遍歷總結
    • 二叉樹結構
    • 建立二叉樹
    • 層次遍歷
    • 遞歸的三種遍歷
    • 非遞歸的三種遍歷
    • 完整代碼

二叉樹結構

用二叉鏈表來存儲二叉樹

typedef struct BiTNode //二叉樹 {int data; //結點數值struct BiTNode *lchild;struct BiTNode *rchild; }BiTNode, *BiTree;

建立二叉樹

輸入一個數組,以層次遍歷的順序進行建樹,規定數組元素都大于0。當數組元素為-1時,表示該結點為空

舉個例子,比如數組大小為 12,數組元素為

3 5 6 8 -1 2 7 8 1 34 -1 65

則建立的二叉樹為

建立二叉樹的代碼:

queue<BiTree> q;//輔助隊列void createBiTree() {int n;int a[1010];//讀取輸入scanf("%d", &n);for (int i = 1; i <= n; i++){scanf("%d", &a[i]);}//建立二叉樹int counts = 1;for (int i = 1; i <= n; i++){BiTree tmp = (BiTree)malloc(sizeof(BiTNode));tmp = q.front();q.pop();tmp->data = a[i];//賦值tmp->lchild = (BiTree)malloc(sizeof(BiTNode));tmp->rchild = (BiTree)malloc(sizeof(BiTNode));if(a[i] != -1){tmp->num = counts;//給非空結點編號counts++;q.push(tmp->lchild);//后面的元素必須掛在非空結點下面q.push(tmp->rchild);}else //空結點標記{tmp->lchild->data = -1;tmp->rchild->data = -1;}}while(!q.empty())//清除隊列中的空結點{q.front()->data = -1;q.pop();} }

層次遍歷

訪問結點

  • 如果該結點不為空,輸出該結點的值
void visit(BiTree T) {if(T->data != -1)printf("%d ", T->data); }

層次遍歷

  • 先把二叉樹的根結點入隊。然后隊首元素出隊,訪問出隊結點。若它有左子樹,則將左子樹根結點入隊;若它有右子樹,右子樹根結點入隊。然后繼續出隊,訪問出隊結點······重復這個過程,直到隊列為空
void LevelOrder(BiTree T) {while(!q.empty())//初始化隊列{q.pop();}q.push(T);//根結點入隊while(!q.empty()){BiTree tmp = q.front();q.pop();//隊頭結點出隊visit(tmp);//訪問出隊結點if(tmp->lchild->data != -1)q.push(tmp->lchild);if(tmp->rchild->data != -1)q.push(tmp->rchild);} }

遞歸的三種遍歷

先序遍歷,也叫前序遍歷

  • 訪問根結點
  • 先序遍歷左子樹
  • 先序遍歷右子樹
void PreOrder(BiTree T) {if(T->data != -1)//結點非空{visit(T);PreOrder(T->lchild);PreOrder(T->rchild);} }

中序遍歷

  • 中序遍歷左子樹
  • 訪問根結點
  • 中序遍歷右子樹
void InOrder(BiTree T) {if(T->data != -1)//結點非空{InOrder(T->lchild);visit(T);InOrder(T->rchild);} }

后序遍歷

  • 后序遍歷左子樹
  • 后序遍歷右子樹
  • 訪問根結點
void PostOrder(BiTree T) {if(T->data != -1)//結點非空{PostOrder(T->lchild);PostOrder(T->rchild);visit(T);} }

非遞歸的三種遍歷

中序遍歷

  • 沿著根的左孩子,依次入棧,直到左孩子為空
  • 棧頂元素出棧并訪問,若其右孩子為空,繼續執行 2
  • 若其右孩子不空,將右子樹轉向執行 1
  • void InOrder2(BiTree T) {stack<BiTree> s;BiTree p = T;while((p->data != -1) || (!s.empty()))//p不空或棧不空{if(p->data != -1) //非空結點{s.push(p); //入棧,一路向左p = p->lchild; }else //出棧,轉向出棧結點的右子樹{p = s.top();s.pop();visit(p);p = p->rchild;}} }

    先序遍歷和中序遍歷很相似,區別在于掃描結點時先訪問結點,再將其入棧

    void PreOrder2(BiTree T) {stack<BiTree> s;BiTree p = T;while((p->data != -1) || (!s.empty()))//p不空或者棧不空{if(p->data != -1) //結點非空{visit(p); //先訪問結點,再入棧s.push(p);p = p->lchild;}else{p = s.top(); //出棧,轉向出棧結點的右子樹s.pop();p = p->rchild;}} }

    后序遍歷

  • 初始時依次掃描根結點的所有左側結點并將它們全部依次進棧

  • 讀棧頂元素,若其右孩子不為空且未被訪問過,將右子樹轉向 1

  • 否則,棧頂元素出棧并訪問

  • 注意:

    在第二步中,需要分清返回時是從左子樹返回的還是右子樹返回的,設置一個輔助指針 r,指向最近訪問過的結點

    每次出棧訪問完一個結點就相當于遍歷完以該結點為根的子樹,需要將 p 置空

    void PostOrder2(BiTree T) {stack<BiTree> s;BiTree p = T;BiTree r = NULL; //r指針記錄最后一個訪問的結點BiTree kong = (BiTree)malloc(sizeof(BiTNode));//空指針,方便p置空kong->data = -1;while((p->data != -1) || (!s.empty()))//p不空或棧不空{if(p->data != -1) //非空結點{s.push(p); //入棧,一路向左p = p->lchild;}else{p = s.top(); //訪問棧頂元素(不出棧)if((p->rchild->data != -1) && (p->rchild != r))//右子樹存在且未被訪問過{p = p->rchild; //轉向右子樹s.push(p);p = p->lchild; //仍然一路向左}else //否則,彈出棧頂元素并訪問{s.pop(); visit(p);r = p; //記錄最近訪問過的結點p = kong; //結點訪問完后,p置空}}} }

    完整代碼

    #include <cstdio> #include <cstdlib> #include <queue> #include <stack> using namespace std;typedef struct BiTNode //二叉樹 {int data; //結點數值struct BiTNode *lchild;struct BiTNode *rchild; }BiTNode, *BiTree; queue<BiTree> q;//輔助隊列void createBiTree(); //層次序列建立二叉樹 void visit(BiTree R); //訪問結點void LevelOrder(BiTree R); //層次遍歷/* 遞歸的先序、中序、后序遍歷 */ void PreOrder(BiTree R); void InOrder(BiTree R); void PostOrder(BiTree R); /* 非遞歸的先序、中序、后序遍歷 */ void PreOrder2(BiTree R); void InOrder2(BiTree R); void PostOrder2(BiTree R); int main() {BiTree bit;bit = (BiTree)malloc(sizeof(BiTNode));q.push(bit);createBiTree();//層次遍歷printf("\n層次遍歷: ");LevelOrder(bit);printf("\n\n");/* 遞歸 */printf("遞歸\n");printf("先序遍歷: ");PreOrder(bit);printf("\n");printf("中序遍歷: ");InOrder(bit);printf("\n");printf("后序遍歷: ");PostOrder(bit);printf("\n\n");/* 非遞歸 */printf("非遞歸\n");printf("先序遍歷: ");PreOrder2(bit);printf("\n");printf("中序遍歷: ");InOrder2(bit);printf("\n");printf("后序遍歷: ");PostOrder2(bit);printf("\n");return 0; }void createBiTree() {int n;int a[1010];//讀取輸入scanf("%d", &n);for (int i = 1; i <= n; i++){scanf("%d", &a[i]);}//建立二叉樹for (int i = 1; i <= n; i++){BiTree tmp = (BiTree)malloc(sizeof(BiTNode));tmp = q.front();q.pop();tmp->data = a[i];//賦值tmp->lchild = (BiTree)malloc(sizeof(BiTNode));tmp->rchild = (BiTree)malloc(sizeof(BiTNode));if(a[i] != -1){q.push(tmp->lchild);//后面的元素必須掛在非空結點下面q.push(tmp->rchild);}else //空結點標記{tmp->lchild->data = -1;tmp->rchild->data = -1;}}while(!q.empty())//清除隊列中的空結點{q.front()->data = -1;q.pop();} } void visit(BiTree T) {if(T->data != -1)printf("%d ", T->data); } void LevelOrder(BiTree T) {while(!q.empty())//初始化隊列{q.pop();}q.push(T);//根結點入隊while(!q.empty()){BiTree tmp = q.front();q.pop();//隊頭結點出隊visit(tmp);//訪問出隊結點if(tmp->lchild->data != -1)q.push(tmp->lchild);if(tmp->rchild->data != -1)q.push(tmp->rchild);} } void PreOrder(BiTree T) {if(T->data != -1)//結點非空{visit(T);PreOrder(T->lchild);PreOrder(T->rchild);} } void InOrder(BiTree T) {if(T->data != -1)//結點非空{InOrder(T->lchild);visit(T);InOrder(T->rchild);} } void PostOrder(BiTree T) {if(T->data != -1)//結點非空{PostOrder(T->lchild);PostOrder(T->rchild);visit(T);} } void PreOrder2(BiTree T) {stack<BiTree> s;BiTree p = T;while((p->data != -1) || (!s.empty()))//p不空或者棧不空{if(p->data != -1) //結點非空{visit(p); //先訪問結點,再入棧s.push(p);p = p->lchild;}else{p = s.top(); //出棧,轉向出棧結點的右子樹s.pop();p = p->rchild;}} } void InOrder2(BiTree T) {stack<BiTree> s;BiTree p = T;while((p->data != -1) || (!s.empty()))//p不空或棧不空{if(p->data != -1) //非空結點{s.push(p); //入棧,一路向左p = p->lchild; }else //出棧,轉向出棧結點的右子樹{p = s.top();s.pop();visit(p);p = p->rchild;}} } void PostOrder2(BiTree T) {stack<BiTree> s;BiTree p = T;BiTree r = NULL; //r指針記錄最后一個訪問的結點BiTree kong = (BiTree)malloc(sizeof(BiTNode));//空指針,方便p置空kong->data = -1;while((p->data != -1) || (!s.empty()))//p不空或棧不空{if(p->data != -1) //非空結點{s.push(p); //入棧,一路向左p = p->lchild;}else{p = s.top(); //訪問棧頂元素(不出棧)if((p->rchild->data != -1) && (p->rchild != r))//右子樹存在且未被訪問過{p = p->rchild; //轉向右子樹s.push(p);p = p->lchild; //仍然一路向左}else //否則,彈出棧頂元素并訪問{s.pop(); visit(p);r = p; //記錄最近訪問過的結點p = kong; //結點訪問完后,p置空}}} }

    程序運行結果如下:

    總結

    以上是生活随笔為你收集整理的二叉树的遍历总结的全部內容,希望文章能夠幫你解決所遇到的問題。

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