1. 程式人生 > >java實現二叉樹的建立及5種遍歷

java實現二叉樹的建立及5種遍歷

用java實現的陣列建立二叉樹以及遞迴先序遍歷,遞迴中序遍歷,遞迴後序遍歷,非遞迴前序遍歷,非遞迴中序遍歷,非遞迴後序遍歷,深度優先遍歷,廣度優先遍歷8種遍歷方式:

package myTest;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;

public class myClass {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		myClass tree = new myClass();
		int[] datas = new int[]{1,2,3,4,5,6,7,8,9};
		List<Node> nodelist = new LinkedList<>();
		tree.creatBinaryTree(datas, nodelist);
		Node root = nodelist.get(0);
		System.out.println("遞迴先序遍歷:");
		tree.preOrderTraversal(root);
		System.out.println();
		System.out.println("非遞迴先序遍歷:");
		tree.preOrderTraversalbyLoop(root);
		System.out.println();
		System.out.println("遞迴中序遍歷:");
		tree.inOrderTraversal(root);
		System.out.println();
		System.out.println("非遞迴中序遍歷:");
		tree.inOrderTraversalbyLoop(root);
		System.out.println();
		System.out.println("遞迴後序遍歷:");
		tree.postOrderTraversal(root);
		System.out.println();
		System.out.println("非遞迴後序遍歷:");
		tree.postOrderTraversalbyLoop(root);
		System.out.println();
		System.out.println("廣度優先遍歷:");
		tree.bfs(root);
		System.out.println();
		System.out.println("深度優先遍歷:");
		List<List<Integer>> rst = new ArrayList<>();
		List<Integer> list = new ArrayList<>();
		tree.dfs(root,rst,list);
		System.out.println(rst);
	}
	/**
	 * 
	 * @param datas 實現二叉樹各節點值的陣列
	 * @param nodelist 二叉樹list
	 */
	private void creatBinaryTree(int[] datas,List<Node> nodelist){
		//將陣列變成node節點
		for(int nodeindex=0;nodeindex<datas.length;nodeindex++){
			Node node = new Node(datas[nodeindex]);
			nodelist.add(node);
		}
		//給所有父節點設定子節點
		for(int index=0;index<nodelist.size()/2-1;index++){
			//編號為n的節點他的左子節點編號為2*n 右子節點編號為2*n+1 但是因為list從0開始編號,所以還要+1
			//這裡父節點有1(2,3),2(4,5),3(6,7),4(8,9) 但是最後一個父節點有可能沒有右子節點 需要單獨處理
			nodelist.get(index).setLeft(nodelist.get(index*2+1)); 
			nodelist.get(index).setRight(nodelist.get(index*2+2));
		}
		//單獨處理最後一個父節點  因為它有可能沒有右子節點
		int index = nodelist.size()/2-1;
		nodelist.get(index).setLeft(nodelist.get(index*2+1)); //先設定左子節點
		if(nodelist.size() % 2 == 1){ //如果有奇數個節點,最後一個父節點才有右子節點
			nodelist.get(index).setRight(nodelist.get(index*2+2));
		}
	}
	/**
	 * 遍歷當前節點的值
	 * @param nodelist
	 * @param node
	 */
	public void checkCurrentNode(Node node){
		System.out.print(node.getVar()+" ");
	}
	/**
	 * 先序遍歷二叉樹
	 * @param root 二叉樹根節點
	 */
	public void preOrderTraversal(Node node){
		if (node == null)  //很重要,必須加上 當遇到葉子節點用來停止向下遍歷
            return;  
		checkCurrentNode(node);
		preOrderTraversal(node.getLeft());
		preOrderTraversal(node.getRight());
	}
	/**
	 * 中序遍歷二叉樹
	 * @param root 根節點
	 */
	public void inOrderTraversal(Node node){
		if (node == null)  //很重要,必須加上
            return;  
		inOrderTraversal(node.getLeft());
		checkCurrentNode(node);
		inOrderTraversal(node.getRight());
	}
	/**
	 * 後序遍歷二叉樹
	 * @param root 根節點
	 */
	public void postOrderTraversal(Node node){
		if (node == null)  //很重要,必須加上
            return;  
		postOrderTraversal(node.getLeft());
		postOrderTraversal(node.getRight());
		checkCurrentNode(node);
	}
	
	/**
	 * 非遞迴前序遍歷
	 * @param node
	 */
	public void preOrderTraversalbyLoop(Node node){
		Stack<Node> stack = new Stack();
		Node p = node;
		while(p!=null || !stack.isEmpty()){
			while(p!=null){ //當p不為空時,就讀取p的值,並不斷更新p為其左子節點,即不斷讀取左子節點
				checkCurrentNode(p);
				stack.push(p); //將p入棧
				p = p.getLeft();
			}
			if(!stack.isEmpty()){
				p = stack.pop();
				p = p.getRight();
			}
		}
	}
	/**
	 * 非遞迴中序遍歷
	 * @param node
	 */
	public void inOrderTraversalbyLoop(Node node){
		Stack<Node> stack = new Stack();
		Node p = node;
		while(p!=null || !stack.isEmpty()){
			while(p!=null){
				stack.push(p);
				p = p.getLeft();
			}
			if(!stack.isEmpty()){	
				p = stack.pop();
				checkCurrentNode(p);
				p = p.getRight();
			}
		}
	}
	/**
	 * 非遞迴後序遍歷
	 * @param node
	 */
	public void postOrderTraversalbyLoop(Node node){
		Stack<Node> stack = new Stack<>();
		Node p = node,prev = node;
		while(p!=null || !stack.isEmpty()){
			while(p!=null){
				stack.push(p);
				p = p.getLeft();
			}
			if(!stack.isEmpty()){
				Node temp = stack.peek().getRight();
				if(temp == null||temp == prev){
					p = stack.pop();
					checkCurrentNode(p);
					prev = p;
					p = null;
				}else{
					p = temp;
				}	
			}
		}
	}
	
	/**
	 * 廣度優先遍歷(從上到下遍歷二叉樹)
	 * @param root
	 */
	public void bfs(Node root){
		  if(root == null) return;
		  LinkedList<Node> queue = new LinkedList<Node>();
		  queue.offer(root); //首先將根節點存入佇列
		  //當佇列裡有值時,每次取出隊首的node列印,列印之後判斷node是否有子節點,若有,則將子節點加入佇列
		  while(queue.size() > 0){ 
			Node node = queue.peek();
		    queue.poll(); //取出隊首元素並列印
		    System.out.print(node.var+" ");
		    if(node.left != null){ //如果有左子節點,則將其存入佇列
		      queue.offer(node.left);
		    }
		    if(node.right != null){ //如果有右子節點,則將其存入佇列
		      queue.offer(node.right);
		    }
		  }
	}
	/**
	 * 深度優先遍歷
	 * @param node
	 * @param rst
	 * @param list
	 */
	public void dfs(Node node,List<List<Integer>> rst,List<Integer> list){
		if(node == null) return;
		if(node.left == null && node.right == null){
			list.add(node.var);
			/* 這裡將list存入rst中時,不能直接將list存入,而是通過新建一個list來實現,
			 * 因為如果直接用list的話,後面remove的時候也會將其最後一個存的節點刪掉*/
			rst.add(new ArrayList<>(list));
			list.remove(list.size()-1);
		}
		list.add(node.var);
		dfs(node.left,rst,list);
		dfs(node.right,rst,list);
		list.remove(list.size()-1);
	}
	/**
	 * 節點類
	 * var 節點值
	 * left 節點左子節點
	 * right 右子節點
	 */ 
	class Node{
		int var;
		Node left;
		Node right;
		public Node(int var){
			this.var = var;
			this.left = null;
			this.right = null;
		}
		public void setLeft(Node left) {
			this.left = left;
		}
		public void setRight(Node right) {
			this.right = right;
		}
		public int getVar() {
			return var;
		}
		public void setVar(int var) {
			this.var = var;
		}
		public Node getLeft() {
			return left;
		}
		public Node getRight() {
			return right;
		}
		
	}

}

執行結果:
遞迴先序遍歷:
1 2 4 8 9 5 3 6 7 
非遞迴先序遍歷:
1 2 4 8 9 5 3 6 7 
遞迴中序遍歷:
8 4 9 2 5 1 6 3 7 
非遞迴中序遍歷:
8 4 9 2 5 1 6 3 7 
遞迴後序遍歷:
8 9 4 5 2 6 7 3 1 
非遞迴後序遍歷:
8 9 4 5 2 6 7 3 1 
廣度優先遍歷:
1 2 3 4 5 6 7 8 9 
深度優先遍歷:
[[1, 2, 4, 8], [1, 2, 4, 9], [1, 2, 5], [1, 3, 6], [1, 3, 7]]