<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          二叉樹的四種遍歷 以及代碼實現(xiàn),看這一篇就夠了

          共 5885字,需瀏覽 12分鐘

           ·

          2021-04-07 10:23

          點擊上方藍色字體,選擇“標星公眾號”

          優(yōu)質文章,第一時間送達

          76套java從入門到精通實戰(zhàn)課程分享

          ★ 前言:
          二叉樹的遍歷,是我們數(shù)據(jù)結構?重點中的重點?,90% 的筆試題都是二叉樹遍歷的變形
          但是呢,有很多小伙伴對它的遍歷方式還是有些模糊
          那么,接下來我就為大家詳細介紹各種遍歷方式的區(qū)別:


          何為 遍歷 :?

          就是把二叉樹中的每個結點,一個不落的都走一遍。。

          我們先封裝一個 二叉樹 的對象類:

          public?class?TreeNode?{
          ????int?v;
          ????TreeNode?left;?//?左子樹
          ????TreeNode?right;?//?右子樹

          ????public?TreeNode(int?v)?{
          ????????this.v?=?v;
          ????}

          ????@Override
          ????public?String?toString()?{
          ????????return?String.format("%c",v);
          ????}
          }


          1、DFS(Depth First Search):深度優(yōu)先遍歷 – 棧

          第一種視角看三種遍歷:

          (1)前序遍歷:

          遍歷順序:(遞歸)

          把根結點放前面處理:


          1、首先,處理 根結點

          2、接著,完整地遍歷根的 左子樹(采用先序)

          3、最后,完整地遍歷根的 右子樹(采用先序)

          ce344a7010c273058b7f64c0ade9ecdb.webp

          具體實現(xiàn):根 { 左子樹 } { 右子樹 }


          ① 我們是從 根結點 開始,

          即 :A{ } { }


          ② 由于我們是先遍歷 左子樹

          所以, A { B{}{} } { }


          A { B{ D{}{} }{} } { }


          A { B{ D{}{G} }{} } { }


          ③ 最后遍歷 右子樹:


          A { B{ D{}{G} }{} } { C{}{} }


          A { B{ D{}{G} }{} } { C{E}{} }


          A { B{ D{}{G} }{} } { C{E}{ F{}{} } }


          A { B{ D{}{G} }{} } { C{E}{ F{H}{} } }


          這樣我們就得出了我們先序遍歷出來的結果:

          A B D G C E F H


          ① 代碼實現(xiàn):(遞歸)

          //?前序遍歷
          ????public?static?void?preTraversal(TreeNode?root)?{
          ????????//?前提:這顆樹不是空樹(根結點存在)
          ????????if?(root?!=?null)?{
          ????????????//?1、首先處理根結點
          ????????????System.out.printf("%c",root.v);
          ????????????//?2、按照前序的方式,遞歸處理該結點的左子樹
          ????????????preTraversal(root.left);
          ????????????//?3、按照前序的方式,遞歸處理該結點的右子樹
          ????????????preTraversal(root.right);
          ????????}?
          ????}


          ② 代碼實現(xiàn):(非遞歸)

          ????public?static?void?preOrder(TreeNode?root)?{
          ????????Deque<TreeNode>?stack?=?new?LinkedList<>();
          ????????TreeNode?cur?=?root;
          ????????while?(!stack.isEmpty()?||?cur?!=?null)?{
          ????????????//遍歷左子樹
          ????????????while?(cur?!=?null)?{
          ????????????????System.out.println(cur.v);
          ????????????????stack.push(cur);
          ????????????????cur?=?cur.left;
          ????????????}
          ????????????//取出棧頂元素
          ????????????TreeNode?top?=?stack.pop();
          ????????????//遍歷右子樹
          ????????????cur?=?top.right;
          ????????}
          ????}

          983e9a6540b027fe42a01691e6c69763.webp



          (2)中序遍歷:

          遍歷順序:(遞歸)

          1、先遍歷整顆樹的 左子樹(采用中序)

          2、中間再處理 根結點 (根放到中間處理)

          3、再遍歷整棵樹的 右子樹 (采用中序)

          233dd4a11569ce25d7608217a837efda.webp


          具體實現(xiàn):{ 左子樹 } 根 { 右子樹 }

          即:{ } A { }


          我們先來遍歷 左子樹, 遍歷的方式采用 中序遍歷


          { {}B{} } A { }


          { { {}D{} }B{} } A { }


          { { {}D{G} }B{} } A { }


          我們再來遍歷 右子樹,遍歷的方式仍然采用 中序遍歷


          { { {}D{G} }B{} } A { {}C{} }


          { { {}D{G} }B{} } A { {E}C{} }


          { { {}D{G} }B{} } A { {E}C{ {}F{} } }


          { { {}D{G} }B{} } A { {E}C{ {H}F{} } }


          這樣我們就得出了我們 中序遍歷 出來的結果:

          D G B A E C H F


          ① 代碼實現(xiàn):(遞歸)

          //?中序遍歷
          ????public?static?void?inTraversal(TreeNode?root)?{
          ????????if?(root?!=?null)?{
          ????????????//?1、中序遍歷左子樹
          ????????????inTraversal(root.left);
          ????????????//?2、處理根
          ????????????System.out.printf("%c",root.v);
          ????????????//?3、中序遍歷右子樹
          ????????????inTraversal(root.right);
          ????????}
          ????}


          ② 代碼實現(xiàn):(非遞歸)

          public?static?void?inOrder(TreeNode?root)?{
          ????????Deque<TreeNode>?stack?=?new?LinkedList<>();
          ????????TreeNode?cur?=?root;
          ????????while?(!stack.isEmpty()?||?cur?!=?null)?{
          ????????????//遍歷左子樹
          ????????????while?(cur?!=?null)?{
          ????????????????stack.push(cur);
          ????????????????cur?=?cur.left;
          ????????????}
          ????????????//取出棧頂元素
          ????????????TreeNode?top?=?stack.pop();
          ????????????//回來的時候打印他
          ????????????System.out.println(top.v);
          ????????????//遍歷右子樹
          ????????????cur?=?top.right;
          ????????}
          ????}


          (3)后序遍歷:

          遍歷順序:(遞歸)

          1、先遍歷整顆樹的 左子樹(采用后序)

          2、再遍歷整棵樹的 右子樹 (采用后序)

          3、最后再處理 根結點 (根放到最后處理)

          199a16ae823dd93637782026c58ec50b.webp


          具體實現(xiàn):{ 左子樹 } { 右子樹 } 根

          即:{ } { } A


          我們先來遍歷 左子樹, 遍歷的方式采用 后序遍歷:


          { {}{}B } { }A


          { { {}{}D }{}B } { }A


          { { {}{G}D }{}B } { }A


          我們再來遍歷 右子樹,遍歷的方式仍然采用 后序遍歷


          { { {}{G}D }{}B } { }A


          { { {}{G}D }{}B } { {}{}C }A


          { { {}{G}D }{}B } { {E}{}C }A


          { { {}{G}D }{}B } { {E}{ {}{}F }C }A


          { { {}{G}D }{}B } { {E}{ {H}F}{}C }A


          這樣我們就得出了我們 后序遍歷 出來的結果:

          G D B E H F C A


          ① 代碼實現(xiàn):(遞歸)

          //?后序遍歷
          ????public?static?void?postTraversal(TreeNode?root)?{
          ????????if?(root?!=?null)?{
          ????????????//?1、后續(xù)遍歷左子樹
          ????????????postTraversal(root.left);
          ????????????//?2、后續(xù)遍歷右子樹
          ????????????postTraversal(root.right);
          ????????????//?3、處理根
          ????????????System.out.printf("%c",root.v);

          ????????}
          ????}


          ② 代碼實現(xiàn):(非遞歸)

          ????public?static?void?postOrder(TreeNode?root)?{
          ????????Deque<TreeNode>?stack?=?new?LinkedList<>();
          ????????TreeNode?cur?=?root;
          ????????TreeNode?last?=?null;//記錄上次遍歷的結點
          ????????while?(!stack.isEmpty()?||?cur?!=?null)?{
          ????????????//遍歷左子樹
          ????????????while?(cur?!=?null)?{
          ????????????????//第一次經(jīng)過?cur?這個結點
          ????????????????stack.push(cur);
          ????????????????cur?=?cur.left;
          ????????????}
          ????????????//取出棧頂元素但不刪除
          ????????????TreeNode?top?=?stack.peek();
          ????????????if(top.right?==?null)?{
          ????????????????//第二次經(jīng)過?top?這個結點(因為右邊為空,所以可以看作第三次)
          ????????????????//從左子樹中回來,但是右子樹為空,可以看作從右子樹回來
          ????????????????stack.pop();
          ????????????????last?=?top;
          ????????????????System.out.println(top.v);
          ????????????}?else?if?(top.right?==?last){
          ????????????????//第三次經(jīng)過?top
          ????????????????//說明從右子樹中回來的
          ????????????????stack.pop();
          ????????????????last?=?top;
          ????????????????System.out.println(top.v);
          ????????????}?else?{
          ????????????????//第二次經(jīng)過?top
          ????????????????//說明從左子樹中回來的
          ????????????????cur?=?top.right;
          ????????????}
          ????????}
          ????}


          第二種視角看三種遍歷:


          前序 / 中序 / 后序,都是沿著紅色的虛線前進

          003506b930b2d440950263e15eba922c.webp

          根據(jù)每次結點 經(jīng)過的次數(shù) 來進行判斷是 什么 類型 的遍歷:

          • 前序:A B D C E F

          • 中序:D B A E C F

          • 后序:D B E F C A

          2、BFS(Broadcast First Search):廣度優(yōu)先遍歷

          層次遍歷:- - (隊列)

          按照從上到下,從左到右依次將二叉樹遍歷一遍

          716192c5466853ead5f64b9a0391c4bc.webp



          步驟:準備一個隊列

          1、啟動階段 : 把根節(jié)點放入隊列

          deb3c8d4602b596e6904cfad3b4b6b49.webp


          2、開啟循環(huán),直到隊列為空(isEmpty)

          (1)從隊列中取出隊首結點

          (2)層序遍歷經(jīng)過該結點(打印)

          (3)把該結點的 左 / 右 孩子放入隊列中(如果存在)

          78c63dc7ca3abcd856cd3992664d7396.webp


          重復上述循環(huán),即可層序遍歷完二叉樹


          最終打印的結果是:A B C D E F G H I


          代碼實現(xiàn):

          //層序遍歷
          public?class?TreeLevelOrder?{
          ????public?static?void?levelOrderTraversal(TreeNode?root)?{
          ????????if?(root?==?null)?{
          ????????????return;
          ????????}
          ????????//隊列的元素的類型是樹的結點
          ????????Queue<TreeNode>?queue?=?new?LinkedList<>();
          ????????//1、把根節(jié)點放入隊列
          ????????queue.add(root);
          ????????//2、開啟循環(huán)
          ????????while?(!queue.isEmpty())?{
          ????????????//(1)從隊列中取出隊首元素
          ????????????//node?就是層序遍歷時經(jīng)過的結點
          ????????????TreeNode?node?=?queue.remove();
          ????????????//(2)打印遍歷結點的值
          ????????????System.out.println(node.v);
          ????????????//(3)把該結點的左右子樹放入隊列中
          ????????????if?(node.left?!=?null)?{
          ????????????????queue.add(node.left);
          ????????????}
          ????????????if?(node.right?!=?null)?{
          ????????????????queue.add(node.right);
          ????????????}
          ????????}
          ????}
          }

          用途:(判斷完全二叉樹)

          ————————————————

          版權聲明:本文為CSDN博主「小喬不掉發(fā)」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權協(xié)議,轉載請附上原文出處鏈接及本聲明。

          原文鏈接:

          https://blog.csdn.net/qq_45658339/article/details/109608414





          鋒哥最新SpringCloud分布式電商秒殺課程發(fā)布

          ??????

          ??長按上方微信二維碼?2 秒





          感謝點贊支持下哈?f5a908479e59eca0c88caafb9b294170.webp

          瀏覽 53
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲欧美中文日韩在线 | 无码 高潮 在线白丝护士 | 最新中文字幕在线 | 国产成人无码在线高清播放 | 大鸡吧插入视频 |