最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java 二叉樹遍歷的常用方法

 更新時間:2021年05月28日 09:15:41   作者:vcjmhg  
二叉樹的遍歷可以說是解決二叉樹問題的基礎。我們常用的遍歷方式無外乎就四種 前序遍歷、中序遍歷、后續(xù)遍歷、層次遍歷 這四種。

采用前序遍歷、中序遍歷、后續(xù)遍歷實現時,即便采用不同的實現方式(遞歸方式、非遞歸),它們的算法結構是有很大的相似性。因而針對前三種的遍歷我們會總結出對應通用的解決框架,便于在解決二叉樹問題時進行使用。

遞歸方式

遞歸方式遍歷二叉樹時,無論是 前序遍歷、中序遍歷 還是 后續(xù)遍歷 的方式,它們最大的區(qū)別就是對節(jié)點數據的訪問位置不同。除此之外其結構完全一致,因而我們總結出如下的框架結構:

void traverse(TreeNode root) {
    //終止條件
    if(root == null) return;
    // 前序遍歷
    traverse(root.left);
    // 中序遍歷
    traverse(root.right);
    // 后序遍歷
}

對應注釋的位置訪問數據就可以實現不同的遍歷方式。

例如,前序遍歷:

void traverse(TreeNode root) {
    if(root == null) return;
    visit(root);
    traverse(root.left);
    traverse(root.right);
}

同樣的中序遍歷:

void traverse(TreeNode root) {
    if(root ==null) return;
    traverse(root.left);
    visit(root);
    traverse(root.right);
}

后續(xù)遍歷:

void traverse(TreeNode root) {
    if(root ==null) return;
    traverse(root.left);
    traverse(root.right)
}

是否非常 easy!!

非遞歸方式

二叉樹非遞歸遍歷說實話有很多種實現方式,但本質上都是模擬整個遍歷的過程來實現的。

為了便于理解,其中前序遍歷、中序遍歷、后序遍歷我們采用一套類似的算法框架。

整個算法框架如下:

 public void traverse(TreeNode root) {
    // 邊界判斷
    if (root == null) {
      return;
    }
    Stack<TreeNode> stack = new Stack<>();
    TreeNode current = root;
    while (current != null || !stack.isEmpty()) {
       //節(jié)點非空時,證明父節(jié)點的左側節(jié)點非空,直接入棧
      if (current != null) {
        //前序遍歷 visit(current)
        stack.push(current);
        current = current.left;
      } else {
        //節(jié)點為空,證明左側節(jié)點為空,出棧,更換游標節(jié)點方向
        current = stack.pop();
		//中續(xù)遍歷 visit(current);
        current = current.right;
      }
    }
  }

后序遍歷它的遍歷順序為**"左--> 右--> 根",較之與前序遍歷的"根--> 左--> 右",好像是有很大的相似性,我們能否針對上邊的框架進行修改,使由前序遍歷轉換成后序遍歷??
答案是肯定的,我們可以觀察到,可以先求出遍歷順序是"根--> 右--> 左"**"的節(jié)點序列,再倒序,便剛好是后序遍歷的順序:左右根。而遍歷順序是根右左的話,很好辦,從前序遍歷的代碼中改兩行就是了。

故而,可以選擇使用兩個棧,其中一個用于遍歷,另一個用于結果的倒序。

實現代碼如下:

//使用雙棧來實現后序遍歷
  public void postOrderTraverse(TreeNode root){
    Stack<TreeNode> stack = new Stack<>();
    Stack<Integer> res = new Stack<>();
    TreeNode cur = root;
    while (cur!=null || !stack.isEmpty()) {
      if (cur!=null){
        stack.push(cur);
        res.push(cur.val);
        cur = cur.right; //修改處
      }else{
        cur = stack.pop();
        cur = cur.left;  // 修改處
      }
    }
    while (!res.isEmpty()){
      visit(res.pop());
    }
  }

至此,非遞歸遍歷完成,是不是也很 easy??!

下邊我們可以看一下最后一種層次遍歷

層次遍歷

層次遍歷本質上就是閹割版廣度優(yōu)先遍歷,我們此處就直接給出 BFS 算法的框架:

/**
* 給定起始節(jié)點start和目標節(jié)點target,返回其最短路徑長度
**/
int BFS(Node start,Node target){
    Queue<Node> q; //核心數據結構
    Set<Node> visited: //某些情況下可以通過byte數組來進行代替
    int step = 0; //記錄擴散步數
    //起始節(jié)點入隊列
    q.add(start);
    visited.offer(start);
    while(q not empty) {
        //必須要用sz來保存q.size(),然后擴散sz不能直接使用q.size()
        int sz = q.size();
        //將隊列中的節(jié)點進行擴散
        for(int i =0 ; i < sz; i++) {
            Node cur = q.poll();
            // 目標節(jié)點判斷
            if(cur is target) {
                return step;
            }
            // 鄰接結點入隊列
            for(Node n:cur.adjs) {
                //未訪問節(jié)點入隊列
                if(n is not int visited) {
                    visitd.add(n);
                    q.offer(n);
                }
            }
        }
        // 更新步數
        step++;
    }
}

此處我們借助 BFS 的框架,直接給出其實現方法:

void LevelOrder(TreeNode root){
    //初始化棧,并放入
    Queue<TreeNode> queue;
    queue.add(root);
    while( !queue.isEmpty()) {
        //出棧
        TreeNode cur = queue.poll();
        //訪問節(jié)點
        visit(cur);
        //向下一層級擴散
        if(cur.left !=null) queue.add(cur.left);
        if(cur.right !=null) queue.add(cur.right);
    }
}

較之于 BFS,我們會發(fā)現,層次遍歷,少了好多東西,比如不需要 visited 來標記已訪問的節(jié)點(二叉樹本身結構的特點,不可能出現重復遍歷),也不需要將隊列中的節(jié)點進行擴散等。

總結

至此,二叉樹的四種遍歷方式總結完成。我們發(fā)現其實二叉樹所有的遍歷方式都有一種通用的算法框架,只要掌握算法本身的框架還是比較容易能夠寫出實現代碼的。

以上就是Java 二叉樹遍歷的常用方法的詳細內容,更多關于Java 二叉樹遍歷的資料請關注腳本之家其它相關文章!

相關文章

  • Java Map集合用法詳解

    Java Map集合用法詳解

    Map用于保存具有映射關系的數據,Map集合里保存著兩組值,一組用于保存Map的ley,另一組保存著Map的value;Map集合和查字典類似,通過key找到對應的value,通過頁數找到對應的信息。用學生類來說,key相當于學號,value對應name,age,sex等信息。用這種對應關系方便查找
    2021-10-10
  • 對Java字符串與整形、浮點類型之間的相互轉換方法總結

    對Java字符串與整形、浮點類型之間的相互轉換方法總結

    今天小編就為大家分享一篇對Java字符串與整形、浮點類型之間的相互轉換方法總結,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • springboot集成mybatis實例代碼

    springboot集成mybatis實例代碼

    本篇文章主要介紹了springboot集成mybatis實例代碼,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • Spring Security之LogoutSuccessHandler注銷成功操作方式

    Spring Security之LogoutSuccessHandler注銷成功操作方式

    這篇文章主要介紹了Spring Security之LogoutSuccessHandler注銷成功操作方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • SpringBoot 監(jiān)控管理模塊actuator沒有權限的問題解決方法

    SpringBoot 監(jiān)控管理模塊actuator沒有權限的問題解決方法

    這篇文章主要介紹了SpringBoot 監(jiān)控管理模塊actuator沒有權限的問題解決方法,需要的朋友可以參考下
    2017-12-12
  • 使用javassist動態(tài)生成類的配置代碼

    使用javassist動態(tài)生成類的配置代碼

    Javassist它是一個用 Java 編輯字節(jié)碼的類庫,它使 Java 程序能夠在運行時定義新類,并在 JVM 加載時修改類文件,本文給大家介紹使用javassist動態(tài)生成類的實例代碼,感興趣的朋友一起看看吧
    2022-09-09
  • 在Java編程中使用正則表達式

    在Java編程中使用正則表達式

    這篇文章主要介紹了在Java編程中使用正則表達式,注意使用matches()方法檢測一下Java對正則表達式的支持情況,需要的朋友可以參考下
    2015-08-08
  • Java中反射詳解

    Java中反射詳解

    本文主要介紹了Java中反射的相關知識。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • 深入理解Spring Boot的日志管理

    深入理解Spring Boot的日志管理

    這篇文章主要給大家深入的介紹了Spring Boot日志管理的相關資料,文中介紹的很詳細,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-02-02
  • 如何完成spring的最小化XML配置

    如何完成spring的最小化XML配置

    這篇文章主要介紹了如何完成spring的最小化XML配置,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,,需要的朋友可以參考下
    2019-06-06

最新評論

温州市| 巴中市| 石景山区| 潮安县| 星子县| 镇安县| 黄骅市| 综艺| 株洲市| 抚州市| 黄冈市| 芜湖市| 枣强县| 辉南县| 甘南县| 枣强县| 巴塘县| 万安县| 黎川县| 巴里| 盐城市| 兴宁市| 星子县| 碌曲县| 新乡市| 思茅市| 辛集市| 施秉县| 文安县| 黄山市| 沙坪坝区| 井陉县| 和林格尔县| 威宁| 封丘县| 阳山县| 武城县| 舒城县| 赞皇县| 吉木乃县| 五大连池市|