欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java二叉樹的四種遍歷(遞歸和非遞歸)

 更新時間:2020年12月04日 19:15:56   作者:燈塔先生  
這篇文章主要介紹了Java二叉樹的四種遍歷,二叉樹的遍歷可以分為前序、中序、后序、層次遍歷,需要的朋友可以參考下

二叉樹的遍歷可以分為前序、中序、后序、層次遍歷。

前中后是指何時訪問中間節(jié)點,即前序遍歷,遍歷節(jié)點的順序為:中—>左—>右;

中序遍歷,遍歷節(jié)點的順序為:左—>中—>右;

后序遍歷,遍歷節(jié)點的順序為:左—>右—>中。

前序遍歷

遞歸實現(xiàn)

public void preorder_Traversal(TreeNode root)
  {
    if(root==null)return;
    
    //訪問節(jié)點的邏輯代碼塊
    System.out.print(root.val+" ");
    
    preorder_Traversal(root.left);
    preorder_Traversal(root.right);
  }

非遞歸過程如下:

1.每遍歷一個節(jié)點的時候,先節(jié)點入棧,然后尋找當前節(jié)點的左子節(jié)點。(因為是前序遍歷,所以在節(jié)點入棧之前就可以對節(jié)點進行訪問)

2.當某個節(jié)點的左子節(jié)點,當左子節(jié)點不為空的時候,重復過程1.

3.當左子節(jié)點為空的時候?qū)斍肮?jié)點出棧,并且通過其尋找右子節(jié)點,右子節(jié)點不為空的時候,重復過程1-2

4.當右子節(jié)點也為空的時候,則跳回上一個該節(jié)點的父節(jié)點(即因為當前節(jié)點已經(jīng)出棧,所以現(xiàn)在在棧中最上層的節(jié)點是當前節(jié)點的父節(jié)點)

非遞歸實現(xiàn)

public void preorder(TreeNode root)
  {
    Stack<TreeNode>  stack=new Stack<>();
    while(root!=null||!stack.isEmpty())
    {
      //當前節(jié)點不為空,則入棧,確保最后遍歷到的節(jié)點沒有左子節(jié)點
      //因為是前序遍歷,所以再遍歷到每個節(jié)點的時候,都可以先訪問,再尋找其左右子節(jié)點。
      while(root!=null)
      {
        System.out.print(root.val+" ");
        stack.push(root);
        root=root.left;
      }
      if(!stack.empty())
      {
        //把這兩步看成是一步,找到右節(jié)點,并把已處理的中節(jié)點從stack當中去除
        root=stack.pop();
        root=root.right;
      }
    }
  }

中序遍

遞歸實現(xiàn)

public void inorder_Traversal(TreeNode root)
  {
    if(root==null)return;
    inorder_Traversal(root.left);
    
     //訪問節(jié)點的邏輯代碼塊
    System.out.print(root.val+" ");
    
    inorder_Traversal(root.right);
  }

非遞歸

對比前序、中序,發(fā)現(xiàn)代碼幾乎一模一樣,但唯一的不同的是,訪問節(jié)點的位置不一樣,中序遍歷是當左子節(jié)點被訪問過,或者不存在的時候,才可以訪問中間節(jié)點,所以再該處,訪問節(jié)點的位置放在了當左子節(jié)點不存在的時候,即節(jié)點出棧的時候,即是左子節(jié)點不存在的時候進行訪問。

非遞歸實現(xiàn)

public void Inorder(TreeNode root)
  {
    Stack<TreeNode> stack=new Stack<>();
    while(root!=null||!stack.isEmpty())
    {
      //當前節(jié)點不為空,則入棧,確保最后遍歷到的節(jié)點沒有左子節(jié)點
      while(root!=null)
      {
        stack.push(root);
        root=root.left;
      }
      //通過當前節(jié)點,跳到當前節(jié)點的右節(jié)點,因為是中序遍歷,所以當前節(jié)點沒有左節(jié)點的時候,就 
       可以訪問當前節(jié)點
      if(!stack.empty())
      {
        root=stack.pop();
        System.out.print(root.val+" ");
        root=root.right;
      }
    }
  }

后序遍歷

遞歸實現(xiàn)

public void postorder_Traversal(TreeNode root)
  {
    if(root==null)return;
    postorder_Traversal(root.left);
    postorder_Traversal(root.right);
    
     //訪問節(jié)點的邏輯代碼塊
    System.out.print(root.val+" ");
  }

非遞歸版本一

借助兩個棧來存儲我們的節(jié)點以及標示位,過程如下:

1.每遍歷一個節(jié)點的時候,先節(jié)點入棧s,并且s2入棧一個標識位0,然后尋找當前節(jié)點的左子節(jié)點。

2.當某個節(jié)點的左子節(jié)點,當左子節(jié)點不為空的時候,重復過程1.

3.當左子節(jié)點為空的時候?qū)斍肮?jié)點peek出(即將節(jié)點拿出,但棧中還是有該節(jié)點),并且此時將s2對應棧頂?shù)臉俗R位改為1,通過其尋找右子節(jié)點,右子節(jié)點不為空的時候,重復過程1-2

4.當右子節(jié)點也為空的時候,并且s2對應的標識符為1的時候,則彈出s1棧頂?shù)漠斍肮?jié)點,并且將s2的標識符彈出(即因為當前節(jié)點還沒有出棧,所以現(xiàn)在在棧中最上層的節(jié)點是當前節(jié)),注意s1彈出當前節(jié)點并訪問,但是不賦值給root,在這個root此時還是null

5.進入過程3,此時root被peek賦值到當前節(jié)點的父節(jié)點(因為在過程4當中,已經(jīng)pop出了當前節(jié)點,所以s1棧頂是當前節(jié)點的父節(jié)點)的右子節(jié)點。

6.重復過程1-5

public void Postorder(TreeNode root)
  {
    Stack<TreeNode> s =new Stack<>(); 
    Stack<Integer> s2 =new Stack<>();
    Integer i=new Integer(1);
    while(root!=null||!s.isEmpty())
    {
      //只要當前節(jié)點非空,就入棧
      while(root!=null)
      {
        s.push(root);
        s2.push(new Integer(0));
        root=root.left;
      }
      //s2當中如果存1,則意味著當前s1對應的節(jié)點的左右子節(jié)點都已經(jīng)遍歷過了。
      while(!s.empty()&&s2.peek().equals(i))
      {
        s2.pop();
        System.out.print(s.pop().val+" ");
      }
      if(!s.isEmpty())
      {
        s2.pop();
        s2.push(new Integer(1));
        root=s.peek();
        root=root.right;
      }
      
    }
  }

非遞歸版本二

實現(xiàn)思路:

在進行后序遍歷的時候是先要遍歷左子樹,然后在遍歷右子樹,最后才遍歷根節(jié)點。所以在非遞歸的實現(xiàn)中要先把根節(jié)點入棧,然后再把左子樹入棧直到左子樹為空,此時停止入棧。此時棧頂就是需要訪問的元素,所以直接取出訪問p。在訪問結束后,還要判斷被訪問的節(jié)點p是否為棧頂節(jié)點的左子樹,如果是的話那么還需要訪問棧頂節(jié)點的右子樹,所以將棧頂節(jié)點的右子樹取出賦值給p。如果不是的 話則說明棧頂節(jié)點的右子樹已經(jīng)訪問完了,那么現(xiàn)在可以訪問棧頂節(jié)點了,所以此時將p賦值為null。判斷結束的條件是p不為空或者棧不為空,若果兩個條件都不滿足的話,說明所有節(jié)點都已經(jīng)訪問完成。

非遞歸實現(xiàn)

public void postOrder(Node root) {
		
	Stack<Node> s = new Stack<Node>();
	Node p = root;
	while (p != null || !s.empty()) {
		while(p != null) {
			s.push(p);
			p = p.left;
		}
		p = s.pop();
		System.out.print(p.val+" ");
	//這里需要判斷一下,當前p是否為棧頂?shù)淖笞訕?,如果是的話那么還需要先訪問右子樹才能訪問根節(jié)點
	//如果已經(jīng)是不是左子樹的話,那么說明左右子書都已經(jīng)訪問完畢,可以訪問根節(jié)點了,所以講p復制為NULL
	//取根節(jié)點
		if (!s.empty() && p == s.peek().left) {
			p = s.peek().right;
		}
		else p = null;
	}
}
 

層次遍歷

用隊列實現(xiàn),步驟是:

1.對于不為空的結點,先把該結點加入到隊列中;

2.從隊中拿出結點,如果該結點的左右結點不為空,就分別把左右結點加入到隊列中;

3.重復以上操作直到隊列為空;

public void LaywerTraversal(TreeNode root){
  if(root==null) return;
  LinkedList<TreeNode> list = new LinkedList<TreeNode>(); 
  list.add(root);
  TreeNode currentNode;
  while(!list.isEmpty()){
    currentNode=list.poll();
    System.out.println(currentNode.val);
    if(currentNode.left!=null){
      list.add(currentNode.left);
    }
    if(currentNode.right!=null){
      list.add(currentNode.right);
    }
  }
}

到此這篇關于Java二叉樹的四種遍歷(遞歸和非遞歸)的文章就介紹到這了,更多相關Java二叉樹內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • IDEA的常見的設置和優(yōu)化功能圖文詳解

    IDEA的常見的設置和優(yōu)化功能圖文詳解

    這篇文章主要介紹了IDEA的常見的設置和優(yōu)化功能,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-07-07
  • Kafka 安裝與配置詳細過程

    Kafka 安裝與配置詳細過程

    本節(jié)詳細介紹 Kafka 運行環(huán)境的搭建,為了節(jié)省篇幅,本節(jié)的內(nèi)容以 Linux CentOS 作為安裝演示的操作系統(tǒng),其他 Linux 系列的操作系統(tǒng)也可以參考本節(jié)的內(nèi)容,對Kafka 安裝與配置相關知識感興趣的朋友一起看看吧
    2021-11-11
  • idea中創(chuàng)建多module的maven工程的方法

    idea中創(chuàng)建多module的maven工程的方法

    這篇文章主要介紹了idea中創(chuàng)建多module的maven工程的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-10-10
  • java進行error捕獲和處理示例(java異常捕獲)

    java進行error捕獲和處理示例(java異常捕獲)

    通常來說,大家都是對Java中的Exception進行捕獲和進行相應的處理,有些人說,error就無法捕獲了。其實,error也是可以捕獲的。Error和Exception都是Throwable的子類。既然可以catch Throwable,那么error也是可以catch的
    2014-01-01
  • Spring框架web項目實戰(zhàn)全代碼分享

    Spring框架web項目實戰(zhàn)全代碼分享

    這篇文章主要介紹了Spring框架web項目實戰(zhàn)全代碼分享,具有一定參考價值,需要的朋友可以了解下。
    2017-11-11
  • Spring?Boot?Reactor?整合?Resilience4j詳析

    Spring?Boot?Reactor?整合?Resilience4j詳析

    這篇文章主要介紹了Spring?Boot?Reactor整合Resilience4j詳析,文章通過引入pom包展開詳細介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下
    2022-09-09
  • Java RPC框架如何實現(xiàn)客戶端限流配置

    Java RPC框架如何實現(xiàn)客戶端限流配置

    這篇文章主要介紹了Java RPC框架如何實現(xiàn)客戶端限流配置,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-02-02
  • Java中注解@JsonFormat與@DateTimeFormat的使用

    Java中注解@JsonFormat與@DateTimeFormat的使用

    從數(shù)據(jù)庫獲取時間傳到前端進行展示的時候,我們有時候可能無法得到一個滿意的時間格式的時間日期,本文主要介紹了Java中注解@JsonFormat與@DateTimeFormat的使用,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2023-08-08
  • Spring Date jpa 獲取最新一條數(shù)據(jù)的實例代碼

    Spring Date jpa 獲取最新一條數(shù)據(jù)的實例代碼

    這篇文章主要介紹了Spring Date jpa 獲取最新一條數(shù)據(jù)的實例代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-10-10
  • Java:詳解Java中的異常

    Java:詳解Java中的異常

    這篇文章主要介紹了java中的異常,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2021-08-08

最新評論