1. 程式人生 > >二叉樹先中後序遍歷(遞迴、非遞迴方法)、層序遍歷 Java實現

二叉樹先中後序遍歷(遞迴、非遞迴方法)、層序遍歷 Java實現

第一部分:二叉樹結點的定義

二叉樹結點有三個屬性:資料域、左結點、右結點。構造方法寫三個引數,這樣建立結點的時候程式碼更簡潔,且要從葉子結點開始建立(從底往上建立)。注:如果只寫一個賦值引數的構造器,那麼建立節點的順序就無所謂了,但是建立二叉樹時要多寫幾行程式碼。

package binaryTree.bean;
/*
 * 二叉樹的結點
 */
public class Node {
private int data;
private Node left;
private Node right;

public Node(int data,Node left,Node right){
this.data = data;
this.left = left;
this.right = right;
}

public int getData(){
return data;
}
public void setData(int data){
this.data = data;
}
public Node getLeft(){
return left;
}
public void setLeft(Node left){
this.left = left;
}
public Node getRight(){
return right;
}
public void setRight(Node right){
this.right = right;
}
}

第二部分:全部程式碼

該二叉樹(你可以任意畫一個)有五個結點,為了方便描述,賦值分別為1、2、3、4、5。前中後序遍歷遞迴與非遞迴完整程式碼如下:

package binaryTree;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;


/*         二叉樹
 *    @1
 *   /  \
 *                @2  @3
 *               / \ 
 *              @4 @5
 */
/* 
 * 遞迴與非遞迴
 * 先序遍歷 preOrderTraverse   1 2 4 5 3
 * 中序遍歷 inOrderTraverse    4 2 5 1 3
 * 後序遍歷 postOrderTraverse  4 5 2 3 1
 * 層序遍歷 levelOrderTraverse 1 2 3 4 5
 */
/*
 * 棧 stack類  入棧push(),出棧pop()
 * 佇列 Queue介面 LinkedList為實現類   入隊offer(),出隊poll()
 */
import binaryTree.bean.Node;
public class BinaryTree {
public static void main(String[] args) {
//結點一的左右結點為結點二、結點三
//結點二的左右結點為結點四、五
//結點三、四、五的左右結點均為空
//由於Node的構造方法為三個引數,故要從葉子結點開始設定
Node node4 = new Node(4, null, null);
Node node5 = new Node(5, null, null);
Node node2 = new Node(2, node4, node5);
Node node3 = new Node(3, null, null);
Node node1 = new Node(1, node2, node3);

//preOrderTraverse1(node1);
//inOrderTraverse1(node1);
//postOrderTraverse1(node1);
//preOrderTraverse2(node1);
//inOrderTraverse2(node1);
//postOrderTraverse2(node1);
levelOrderTraverse(node1);

}

//先序遍歷(遞迴法)
private static void preOrderTraverse1(Node head){
if(head == null)
return;
//根左右
System.out.print(head.getData()+" ");
preOrderTraverse1(head.getLeft());
preOrderTraverse1(head.getRight());
}
//後序遍歷(遞迴法)
private static void postOrderTraverse1(Node head){
if(head == null)
return;
//左右根
postOrderTraverse1(head.getLeft());
postOrderTraverse1(head.getRight());
System.out.print(head.getData()+" ");
}
//中序遍歷(遞迴法)
private static void inOrderTraverse1(Node head){
if(head == null)
return;
//左根右
inOrderTraverse1(head.getLeft());
System.out.print(head.getData()+" ");
inOrderTraverse1(head.getRight());
}
/*
* 先序遍歷(非遞迴法)
* 1.申請一個棧記為stack.
* 2.然後將頭結點head壓入stack中
* 3.每次從stack中彈出棧頂結點,記為cur,然後列印cur結點的值.如果cur右孩子不為空的話,
* 先將cur的右孩子先壓入stack中再將cur的左孩子壓入stack。
* 然後從stack中彈出棧頂結點並記為cur,列印cur結點的值,如果cur右孩子不為空的話,先將
* cur的右孩子先壓入stack中,再將cur的左孩子壓入stack.然後重複以上步驟(若某個結點沒有
* 孩子,則棧繼續彈出),直到stack為空,全部過程結束。
*/
private static void preOrderTraverse2(Node head){
Stack<Node> stack = new Stack<>();
stack.push(head);
while(!stack.isEmpty()){
Node current = stack.pop();
System.out.print(current.getData()+" ");
if(current.getRight()!=null){
stack.push(current.getRight());
}
if(current.getLeft()!=null){
stack.push(current.getLeft());
}
}
}
/*
* 中序遍歷(非遞迴法)
* 1.申請一個新的棧記為stack,申請變數cur,初始時令cur等於頭結點。
* 2.進入while(current!=null||!stack.isEmpty())迴圈,
* 然後判斷當current!=null時, 把cur結點壓入棧中,然後令cur=cur.getLeft,然後重複while迴圈
* 如果cur為空,則從stack中彈出一個結點記為node,
* 列印node的值,並讓cur=node.right,然後繼續重複while迴圈
*/
private static void inOrderTraverse2(Node head){
Stack<Node> stack = new Stack<>();
Node current = head;
while(current!=null||!stack.isEmpty()){
if(current!=null){
stack.push(current);
current = current.getLeft();
}else{
Node node = stack.pop();
System.out.print(node.getData()+" ");
current = node.getRight();
}
}
}
/*
* 後序遍歷(非遞迴方法一:使用兩個棧)
* 1.申請兩個棧記為s1、s2.將頭結點壓入s1中,然後彈出並放入s2中
* 2.將 從s1彈出並放入s2中的結點 記為cur,然後先把cur的左孩子壓入s1中,再把cur的
* 右孩子壓入s1中.(若彈出的結點cur沒有左右孩子,則繼續從s1彈出結點並放入s2中)
* 3.迴圈步驟2,直到s1為空,過程停止。
* 4.從s2中依次彈出節點並列印,列印的順序就是後序遍歷的順序。
*/
private static void postOrderTraverse2(Node head){
Stack<Node> stack1 = new Stack<>();
Stack<Node> stack2 = new Stack<>();
stack1.push(head);
while(!stack1.isEmpty()){
Node current = stack1.pop();
stack2.push(current);
if(current.getLeft()!=null){
stack1.push(current.getLeft());
}
if(current.getRight()!=null){
stack1.push(current.getRight());
}
}
while(!stack2.isEmpty()){
Node node = stack2.pop();
System.out.print(node.getData()+" ");
}
}
/*
* 層序遍歷
* 每一層都是從左到右的遍歷輸出,藉助於佇列實現。offer()為入隊,poll()為出隊
* 1.先將根節點入隊
* 2.將隊首節點賦為cur,然後出隊並列印,
* 如果當前結點cur的左結點不為空則將左結點入隊,然後若右結點不為空則將右結點入隊。
* 3.重複步驟2直到隊空
*/
private static void levelOrderTraverse(Node head){
Queue<Node> queue = new LinkedList<>();
queue.offer(head);
while(!queue.isEmpty()){
Node current = queue.poll();
System.out.print(current.getData()+" ");
if(current.getLeft()!=null){
queue.offer(current.getLeft());
}
if(current.getRight()!=null){
queue.offer(current.getRight());
}
}
}

}

注:前中後序遍歷,不管是遞迴方法還是非遞迴方法,遍歷整棵樹的時間複雜度都是O(N),N為二叉樹的結點數。

每一種方法我都執行成功,都有詳細的註釋,有問題的話歡迎在評論區提問,一起學習進步!

相關推薦

的C++程式碼

馬上就要資料結構考試了,會考到二叉樹的遍歷演算法設計題,然後就自己總結了一個關於二叉樹的簡單演算法程式碼。 #include <iostream> #include <stdio.h> #include <stdlib.h> #inclu

方法 Java實現

第一部分:二叉樹結點的定義 二叉樹結點有三個屬性:資料域、左結點、右結點。構造方法寫三個引數,這樣建立結點的時候程式碼更簡潔,且要從葉子結點開始建立(從底往上建立)。注:如果只寫一個賦值引數的構造器,那麼建立節點的順序就無所謂了,但是建立二叉樹時要多寫幾行程式碼。 pack

二叉樹 com size 基本 html 後序 href col spa 轉自:https://www.cnblogs.com/polly333/p/4740355.html 基本思想>>   先序遍歷:根——>左——>右   先序遍歷:左——>

數據結構 歸和歸方式實現

nor post 後序遍歷 order else 對象 二叉樹先序 bre print   二叉樹的先序遍歷順序是根、左、右;中序遍歷順序是左、根、右;後序遍歷順序是左、右、根。   遞歸方式實現如下: 1 public class TreeNode { 2

鏈式

參考部落格:click here! 鏈式二叉樹儲存結構: typedef int DataType; typedef struct BiNode { DataType data; struct BiNode *lc, *rc; // 左右子節點指標 int depth; } B

演算法與演算法

首先是二叉樹資料結構的定義: typedef struct TNode *Position; typedef Position BinTree; /* 二叉樹型別 */ struct TNode{ /* 樹結點定義 */ int Data; /* 結點資料 */ BinTre

實現

一、遞迴實現 import java.util.*; /* public class TreeNode { int val = 0; TreeNode left = null; TreeNode right = null; public TreeNode(int

已知結果和結果,還原建立

主函式 int main(int argc, char** argv){ int n, m; cin>>n; for(int i=0;i<n;i++){ cin>>m; v.push_back(m); } for(

建立

思想:用”棧”來消除遞迴。 主要是建立的過程,剛開始卡到了如果遇到’#’,那麼在else中間出棧之後還需要讀一個元素,這樣在遇到連續的”#”之後,退棧並不能達到合適的位置,最後聽了“巔峰”的建議,還是設定了flag,解決了問題,下面解釋下建立過程的思想:

3.1分別用方式實現

題目 用遞迴和非遞迴方式,分別按照二叉樹先序、中序和後序列印所有的節點。 首先給出二叉樹節點結構定義: public class BinaryTreeNode { //二叉樹節點 private int data; private Bi

建立,前層次,以及統計葉子結點個數以及的深度

下面的程式碼實現了二叉樹的先序或者後序遞迴建立,然後實現了二叉樹的非遞迴的先序中序後序遍歷,還有層次遍歷,以及統計樹的葉子結點個數和樹的深度。其中非遞迴的先中後序遍歷用到了鏈棧,層次遍歷用到了佇列。 程式設計平臺為Visual Studio 2012,語言為C,但不是純C,

學習筆記--層次實現Python

一、二叉樹類的Python實現及其函式:包括統計結點個數,用遞迴實現的先序遍歷,非遞迴實現的先序遍歷,以及非遞迴實現的後序遍歷。class StackUnderflow(ValueError): pass class SStack(): d

首先需要去理解二叉樹的定義 : ------/** * 二叉樹 * 每個結點最多有兩個子結點 * * Created by on 2017/11/2. */ public class BinaryTree implements Serializable {

[C/C++] 建立| | 求深度節點數葉節點數 演算法實現

/* * BinTree.h */ #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #defi

Morris詳解—— 時間複雜度O(N),空間複雜度O(1)

Morris二叉樹遍歷: 來到當前的節點:Cur 如果Cur無左孩子,Cur向右移動 (Cur = Cur.right) 如果Cur有左孩子,找到Cur左子樹上最右的節點,記為 mostright

方式實現

先序遍歷:中、左、右 中序遍歷:左、中、右 後序遍歷:左、右、中 比如下面這科樹              1         2       3    4    5   6    7 packag

實現

利用棧實現二叉樹的先序,中序,後序遍歷的非遞迴操作 #include <stdio.h> #include <malloc.h> #include <stdlib.h> #include <queue> #include &l

為資料, 或者為根, 建立

#include<iostream> using namespace std; struct Tree{ int v; Tree *left, *right; }; Tree *create_node(int v){ Tree *node = new Tree; node

水平 程式碼包含前和水平四種

水平遍歷二叉樹要求一層一層從上往下從左往右遍歷,例如: 上面二叉樹的遍歷順序為:2、4、5、1、3 思路:利用佇列先進先出的性質 1、將根節點放入佇列 2、while迴圈佇列,只要佇列不為空,就取出第一個節點。獲取資料 3、將第二步取出的節點的左子節點和右子節點

+輸出前

引用: https://blog.csdn.net/m0_37698652/article/details/79218014 #include <iostream> #include <string> using namespace std; struct Tree