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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

二叉树先中后序递归遍历与非递归遍历、层次遍历

發(fā)布時間:2024/7/5 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二叉树先中后序递归遍历与非递归遍历、层次遍历 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

      • 1 先序遍歷
        • 1.1 先序遍歷遞歸
        • 1.2 先序遍歷非遞歸
      • 2 中序遍歷
        • 2.1 中序遍歷遞歸
        • 2.2 中序遍歷非遞歸
      • 3 后序遍歷
        • 3.1 后序遍歷遞歸
        • 3.2 后序遍歷非遞歸
      • 4 層序遍歷

1 先序遍歷

若二叉樹為空,則操作返回,否則先訪問根結點,然后前序遍歷左子樹,再前序遍歷右子樹

1.1 先序遍歷遞歸

void PreviousOrderTraverse(BTNode T) {if (T == NULL) {return;}/* 對節(jié)點的操作 */PreviousOrderTraverse(T->lchild); // 先序遍歷左子樹PreviousOrderTraverse(T->rchild); // 再先序遍歷右子樹 }

1.2 先序遍歷非遞歸

遞歸的實現(xiàn)依賴于棧,那么就將二叉樹的遞歸遍歷轉換為非遞歸遍歷,也就是利用棧來實現(xiàn)

void PreviousOrderTraverse(BTNode *bt) {if(bt !=NULL{BTNode *Stack[maxSize]; int top=-1;BTNode *p=NULL; //p為遍歷指針Stack[++top]=bt;while(top!=-1{p=Stack[top--]; //根結點出棧并訪問visit(p);if(p->rchild!=NULL//檢測左右孩子是否存在Stack[++top]=p->rchild; //先入if(p->rchild!=NULL)Stack[++top]=p->lchild;}} }

2 中序遍歷

若二叉樹為空,則操作返回,否則從根節(jié)點開始(注意不是先訪問根結點),中序遍歷根結點的左子樹,然后是訪問根結點,最后中序遍歷右子樹

2.1 中序遍歷遞歸

void InOrderTraverse(BTNode T) {if (T == NULL) {return;}InOrderTraverse(T->lchild); // 先中序遍歷左子樹/* 對結點的操作 */InOrderTraverse(T->rchild); // 再中序遍歷右子樹 }

2.2 中序遍歷非遞歸

void InOrderTraverse(BTNode *bt) {BTNode p = T; // p 是遍歷指針Stack S = CreateStack(MAXSIZE); // 初始化棧while (p != NULL || !IsEmpty(S)) { // 棧不為空或 p 不為空時遍歷if (p != NULL) {Push(S, p); // 一直向左并將沿途節(jié)點壓入堆棧p= p->leftChild;} else { // p 為空時,棧不為空,彈出節(jié)點訪問右孩子p= Pop(S); // 彈出堆棧visit();//訪問節(jié)點p = p->rightChild;}} }

3 后序遍歷

若二叉樹為空,則操作返回,否則從左到右,先葉子后結點的方式遍歷訪問左右子樹,最后是訪問根結點

3.1 后序遍歷遞歸

void PostOrderTraverse(BTNode T) {if (T == NULL) {return;}PostOrderTraverse(T->lchild); // 先后序遍歷左子樹PostOrderTraverse(T->rchild); // 再后序遍歷右子樹/* 對結點的操作 */ }

3.2 后序遍歷非遞歸

  • 后序非遞歸遍歷二叉樹的順序是先訪問左子樹,再訪問右子樹,最后訪問根結點。當用堆棧存儲結點時,必須分清返回根結點時是從左子樹返回還是從右子樹返回的;因此,必須使用輔助指針指向最近訪問過的結點。
  • void PostOrderTraverse(BTNode T) {BTNode p = T; // p 為遍歷指針BTNode pTop = NULL; // pTop 為臨時指針BTNode pLast = NULL; // pLast 為保存已訪問節(jié)點指針Stack S = CreateStack(MAXSIZE); // 初始化棧while (p != NULL || !IsEmpty(S)) { // 棧不為空或 p 不為空時遍歷 while (p != NULL) {Push(s, p); // 一直向左并將沿途節(jié)點壓入堆棧 p = p->lchild;}pTop = GetStackTop(s); // 取棧頂元素,不是出棧//當棧頂元素的右孩子為空,或者為已經遍歷過的節(jié)點if (pTop->rchild == NULL || pTop->rchild == pLast) {StackPop(s); // 出棧,打印,并令遍歷過的節(jié)點為此時的棧頂元素visit();//訪問節(jié)點pLast = pTop; // 將 pTop 設為已經遍歷過的節(jié)點 continue; // 繼續(xù)循環(huán)}p = pTop->rchild; //遍歷它的右孩子} }
  • 在先序遍歷非遞歸上進行修改,先進左孩子,再進右孩子得逆后序序列,再借助一個棧將逆后序序列轉化為后序序列
  • void PostorderTraverse(BTNode *bt) {if(bt!=NULL){/*定義兩個棧*/BTNode *Stack1[maxSize]; int top1=-1; //遍歷棧 BTNode *Stack2[maxSize]; int top2=-1; //結果序列逆序的棧BTNode *p=NULL;Stack1[++top1]=bt;while(top1!=NULL){p=Stack1[top1--];Stack2[++top2]=p; //每次1出棧,便進2棧 /* 以下與先序遍歷區(qū)別:左右孩子入棧順序相反*/if(p->lchild!=NULL)Stack1[++top1]=p->lchild;if(p->rchild!=NULL)Stack1[++top1]=p->rchild; }while(top2!=-1){/*出棧序列即為后序遍歷序列*/p=Stack2[top2--];visit(p); //visit是訪問p的函數,此處執(zhí)行打印結點值操作 }} }

    4 層序遍歷

    若二叉樹為空,則操作返回,否則從樹的第一層,也就是根結點開始訪問,從上而下逐層遍歷,在同一層中,按從左到右的順序對結點逐個訪問

  • 根結點入隊
  • 從隊列中取出一個元素
  • 訪問該元素所指的結點
  • 若該元素所指結點的左右孩子為非空,則將其左、右孩子的指針順序入隊
  • void LevelTraverse(BTNode *bt) {if(bt!=NULL) //根結點不空即樹不空 {int front,rear;BTNode *que[maxSize];front=rear=0;BTNode *p; //p是遍歷指針 rear=(rear+1)%maxSize;que[rear]=bt; //根結點入隊 while(front!=rear) //隊列為空則遍歷結束 {front=(front+1)%maxSize;p=que[front];visit(p);if(p->lchild!=NULL){rear=(rear+1)%maxSize;que[rear]=p->lchild; //如果左子樹不空,則入隊 } if(p->rchild!=NULL){rear=(rear+1)%maxSize;que[rear]=p->rchild; //如果右子樹不空,則入隊 } }} }

    總結

    以上是生活随笔為你收集整理的二叉树先中后序递归遍历与非递归遍历、层次遍历的全部內容,希望文章能夠幫你解決所遇到的問題。

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