欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

二叉树建立 二叉树遍历 二叉树 递归 非递归 先序 中序 后序 层序遍历

程序员文章站 2022-05-06 21:26:19
...

给定树结构和先序序列

二叉树建立 二叉树遍历 二叉树 递归 非递归 先序 中序 后序 层序遍历


二叉树递归创建:本质上和二叉树递归遍历一样,但是需要知道何时节点孩子为空,因此这里用#做分隔符。

先序建立:先给当前节点分配数据,然后创建左子树,然后创建又子树。

	public Node createTree(){//递归先序创建树
		if(index >= input.length){
			return null;
		}
		if(input[index]=='#'){
			index++;
			return null;
		}
		Node node = new Node();
		node.data = input[index++];
		node.left = createTree();//创建左子树
		node.right = createTree();//创建右子树
		return node;
	}


二叉树递归遍历比较简单,这里不在累述。

	public void preOrderTraverseRec(Node root){
		if(root==null){
			System.out.print("#");
			return;
		}
		System.out.print(root.data);
		preOrderTraverseRec(root.left);
		preOrderTraverseRec(root.right);
	}
	public void inOrderTraverseRec(Node root){
		if(root==null){
			System.out.print("#");
			return;
		}
		inOrderTraverseRec(root.left);
		System.out.print(root.data);
		inOrderTraverseRec(root.right);
	}
	public void postOrderTraverseRec(Node  root){
		if(root==null){
			System.out.print("#");
			return;
		}
		postOrderTraverseRec(root.left);
		postOrderTraverseRec(root.right);
		System.out.print(root.data);
	}

二叉树非递归先序1:从根节点开始,如果当前要访问的结点不为空就访问,然后将节点压入栈,开始遍历节点的左孩子;否则,从栈中弹出一个节点,弹出节点时就开始遍历节点的右孩子(因为当前节点和左孩子都访问过了)。

	public void preOrderTraverse1(Node root){
		Stack<Node> stack = new Stack<Node>();
		if(root == null){
			return;
		}
		Node node = root;
		while(!stack.empty()||node!=null){
			if(node != null){//当前要访问的结点不为空就访问,然后将节点压入栈,访问节点的左孩子
				System.out.print(node.data);
				stack.push(node);
				node = node.left;
			}else{
				node = stack.pop();
				node = node.right;
			}

		}
	}

二叉树非递归先序2:从根节点开始,根节点入栈。每次都弹出一个节点访问,因为栈是后进先出的,所以先看右孩子是否为空,不为空就进栈,然后同理检查左孩子。

	public void preOrderTraverse2(Node root){
		Stack<Node> stack = new Stack<Node>();
		if(root == null){
			return;
		}
		
		Node node = root;
		stack.push(node);
		while(!stack.empty()){
			node = stack.pop();
			System.out.print(node.data);
			if(node.right!=null){
				stack.push(node.right);
			}
			if(node.left != null){
				stack.push(node.left);
			}
		}
	}

二叉树中序非递归遍历:从根节点开始。从当前节点直接走到最左边,然后弹出的时候访问,访问完开始遍历右子树。

	public void inOrderTraverse(Node root){
		Stack<Node> stack = new Stack<Node>();
		Node node = root;
		while(!stack.empty()||node!=null){
			while(node != null){
				stack.push(node);
				node = node.left;
			}
			node = stack.pop();
			System.out.print(node.data);
			node = node.right;
		}
	}

二叉树后序非递归遍历:因为判断当前结点是否需要访问,需要根据上一个节点是不是它的孩子,所以需要用一个pre节点指向上次访问的节点。从根节点开始:1.首先判断左边孩子是否需要访问,如果当前结点左孩子不为空,并且上次访问的节点不是左孩子也不是右孩子,需要先访问左孩子。2.然后判断右边孩子是否需要访问,如果当前结点右孩子不为空,并且上次访问的节点不是右孩子,需要访问右孩子。3.如果以上都不需要访问,说明左右孩子都访问过了,可以访问当前结点。

	public void postOrderTraverse(Node root){
		Stack<Node> stack = new Stack<Node>();
		Node cur = root;
		Node pre = root;
		stack.push(cur);
		while(!stack.empty()){
			cur = stack.peek();
			if(cur.left !=null && pre!=cur.left&&pre!=cur.right){
				stack.push(cur.left);
			}else if(cur.right != null && pre!=cur.right){
				stack.push(cur.right);
			}else{
				cur = stack.pop();
				System.out.print(cur.data);
				pre = cur;
			}
		}
	}

二叉树层序非递归遍历:直接使用一个队列,每次先访问当前结点,然后出队,访问完看是否有左孩子,有就入队;然后看是否有右孩子,有也入队。(可以这样理解,当前层,从左往右访问,访问的时候当前节点左右孩子入队,这样下一层的顺序就是从左向右按顺序的)

	public void levelOrderTraverse(Node root){
		Queue<Node> queue = new LinkedList<Node>();
		queue.add(root);
		Node node = root;
		while(!queue.isEmpty()){
			node = queue.poll();
			System.out.print(node.data);
			if(node.left != null){
				queue.add(node.left);
			}
			if(node.right != null){
				queue.add(node.right);
			}
		}
	}

下面贴一下总体的代码:

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

public class BinaryTree {
	/*
	 *           A
	 *          / \
	 *         /   \
	 *        /     \
	 *       /       \
	 *      B         C
	 *     / \       / \
	 *    D   E     F   G
	 *   /     \   / \ / \
	 *  H       I J   KL  M
	 */
	static class Node{
		char data;
		Node left;
		Node right;
	}
	
	String str  = "ABDH###E#I##CFJ##K##GL##M##";
	int index = 0;
	char [] input = str.toCharArray();
	
	public static void main(String[] args) {
		BinaryTree bt = new BinaryTree();
		Node root = bt.createTree();
		System.out.println("-----递归先序遍历------");
		bt.preOrderTraverseRec(root);
		System.out.println("\n-----递归中序遍历------");
		bt.inOrderTraverseRec(root);
		System.out.println("\n-----递归后序遍历------");
		bt.postOrderTraverseRec(root);
		System.out.println();
		
		System.out.println("\n-----非递归先序遍历1------");
		bt.preOrderTraverse1(root);
		System.out.println("\n-----非递归先序遍历3------");
		bt.preOrderTraverse2(root);
		System.out.println("\n-----非递归中序遍历------");
		bt.inOrderTraverse(root);
		System.out.println("\n-----非递归后序遍历------");
		bt.postOrderTraverse(root);
		System.out.println("\n-----非递归层序遍历------");
		bt.levelOrderTraverse(root);
		
	}

	public Node createTree(){//递归先序创建树
		if(index >= input.length){
			return null;
		}
		if(input[index]=='#'){
			index++;
			return null;
		}
		Node node = new Node();
		node.data = input[index++];
		node.left = createTree();//创建左子树
		node.right = createTree();//创建右子树
		return node;
	}
	
	
	public void preOrderTraverseRec(Node root){
		if(root==null){
			System.out.print("#");
			return;
		}
		System.out.print(root.data);
		preOrderTraverseRec(root.left);
		preOrderTraverseRec(root.right);
	}
	public void inOrderTraverseRec(Node root){
		if(root==null){
			System.out.print("#");
			return;
		}
		inOrderTraverseRec(root.left);
		System.out.print(root.data);
		inOrderTraverseRec(root.right);
	}
	public void postOrderTraverseRec(Node  root){
		if(root==null){
			System.out.print("#");
			return;
		}
		postOrderTraverseRec(root.left);
		postOrderTraverseRec(root.right);
		System.out.print(root.data);
	}
	
	public void preOrderTraverse1(Node root){
		Stack<Node> stack = new Stack<Node>();
		if(root == null){
			return;
		}
		Node node = root;
		while(!stack.empty()||node!=null){
			if(node != null){//当前要访问的结点不为空就访问,然后将节点压入栈,访问节点的左孩子
				System.out.print(node.data);
				stack.push(node);
				node = node.left;
			}else{
				node = stack.pop();
				node = node.right;
			}

		}
	}
	
	public void preOrderTraverse2(Node root){
		Stack<Node> stack = new Stack<Node>();
		if(root == null){
			return;
		}
		
		Node node = root;
		stack.push(node);
		while(!stack.empty()){
			node = stack.pop();
			System.out.print(node.data);
			if(node.right!=null){
				stack.push(node.right);
			}
			if(node.left != null){
				stack.push(node.left);
			}
		}
	}
	
	public void inOrderTraverse(Node root){
		Stack<Node> stack = new Stack<Node>();
		Node node = root;
		while(!stack.empty()||node!=null){
			while(node != null){
				stack.push(node);
				node = node.left;
			}
			node = stack.pop();
			System.out.print(node.data);
			node = node.right;
		}
	}
	
	public void postOrderTraverse(Node root){
		Stack<Node> stack = new Stack<Node>();
		Node cur = root;
		Node pre = root;
		stack.push(cur);
		while(!stack.empty()){
			cur = stack.peek();
			if(cur.left !=null && pre!=cur.left&&pre!=cur.right){
				stack.push(cur.left);
			}else if(cur.right != null && pre!=cur.right){
				stack.push(cur.right);
			}else{
				cur = stack.pop();
				System.out.print(cur.data);
				pre = cur;
			}
		}
	}
	
	public void levelOrderTraverse(Node root){
		Queue<Node> queue = new LinkedList<Node>();
		queue.add(root);
		Node node = root;
		while(!queue.isEmpty()){
			node = queue.poll();
			System.out.print(node.data);
			if(node.left != null){
				queue.add(node.left);
			}
			if(node.right != null){
				queue.add(node.right);
			}
		}
	}
}