二叉树

1 描述

二叉树一个节点有两个后继,称为左右孩子,左右孩子有序不能相互跌倒。二叉树又衍生出多种不同的形态,如红黑树、二叉排序树、B-树、AVL树等。(本节主要提供二叉树的算法实现,没有提供其原理和操作流程的讲解)
在这里插入图片描述

2 算法实现

2.1 节点设计

	protected static class Node<E>{
		public E element;
		public Node<E> left;
		public Node<E> right;
		public Node<E> parent;
		public Node(E element,Node<E> parent){
			this.element = element;
			this.parent = parent;
		}
		
		public boolean isLeaf(){
			return left == null && right == null;
		}
		
		public boolean hasTwoChildren(){
			if(left != null && right != null){
				return true;
			}
			return false;
		}
		
		public boolean isLeftChild(){
			return parent != null && this == parent.left;
		}
		
		public boolean isRightChild(){
			return parent != null && this == parent.right;
		}
		
		/**
		 * 获取兄弟节点
		 * @return
		 */
		public Node<E> sibling(){
			if(parent == null) return null;
			if(isLeftChild()){
				return parent.right;
			}else{
				return parent.left;
			}
		}
	}

2.2 类设计


public class BinaryTree<E> implements TreePrinter<E>  {
	protected int size;
	protected Node<E> root;
	public BinaryTree(){
		this.size = 0;
	}
	//获取二叉树大小(节点个数)
	public int size() {
		return size;
	}
	//二叉树是否为空
	public boolean isEmpty() {
		return root == null;
	}
	//清空二叉树
	public void clear() {
		root = null;
		size = 0;
	}
	//构造一个二叉树节点
	protected Node<E> createNode(E element,Node<E> parent){
		return new Node<>(element,parent);
	}

2.3 TreePrinter接口设计(遍历)

public interface TreePrinter<E> {
	//先序
	void preTraver(Visitor<E> visitor);
	//中序
	void inTraver(Visitor<E> visitor);
	//后序
	void postTraver(Visitor<E> visitor);
	//层序
	void levelTraver(Visitor<E> visitor);
	//用栈先序
	void preTraverWithStack(Visitor<E> visitor);
	//用栈中序
	void inTraverWithStack(Visitor<E> visitor);
	//用栈后序
	void postTraverWithStack(Visitor<E> visitor);
}

2.4 Visitor抽象类

	public abstract class Visitor<E> {
		boolean stop = false;
		public abstract boolean visit(E e); //访问后是否停止遍历
	}

2.5 TreePrinter接口的实现(遍历)

  • 先序遍历
	@Override
	public void preTraver(Visitor<E> visitor) {
		if(visitor == null){
			return;
		}
		preTraver(root,visitor);
	}
	
	public void preTraver(Node<E> root,Visitor<E> visitor){
		if(root == null || visitor.stop){
			return;
		}
		//每次需要更新stop的状态,因为在某次visit访问后可能需要停止访问
		visitor.stop = visitor.visit(root.element);
		preTraver(root.left,visitor);
		preTraver(root.right,visitor);
	}
  • 中序遍历
	@Override
	public void inTraver(Visitor<E> visitor) {
		if(visitor == null){
			return;
		}
		inTraver(root,visitor);
	}
	
	public void inTraver(Node<E> root,Visitor<E> visitor){
		if(root == null || visitor.stop){
			return;
		}
		inTraver(root.left,visitor);
		visitor.stop = visitor.visit(root.element);
		if(visitor.stop) return;
		inTraver(root.right,visitor);	
	}
	
  • 后序遍历
	@Override
	public void postTraver(Visitor<E> visitor) {
		if(visitor == null){
			return;
		}
		postTraver(root,visitor);
	}

	public void postTraver(Node<E> root,Visitor<E> visitor){
		if(root == null || visitor.stop){
			return;
		}
		postTraver(root.left,visitor);
		postTraver(root.right,visitor);	
		visitor.stop = visitor.visit(root.element);
		if(visitor.stop) return;
	}
  • 层序遍历
	@Override
	public void levelTraver(Visitor<E> visitor) {
		if(root == null || visitor == null){
			return;
		}
		Queue<Node<E>> que = new LinkedList<Node<E>>();
		que.offer(root);
		while(!que.isEmpty()){
			Node<E> node = que.poll();
			if(node == null){
				break;
			}
			visitor.stop = visitor.visit(node.element);
			if(visitor.stop){
				return;
			}
			if(node.left != null) que.offer(node.left);
			if(node.right != null) que.offer(node.right);
		}
	}
  • 用栈先序遍历(利用栈的先进后出的思想,先遍历右子树后遍历左子树)
	@Override
	public void preTraverWithStack(Visitor<E> visitor) {
		if(visitor == null || root == null){
			return;
		}
		Stack<Node<E>> stack = new Stack<Node<E>>();
		stack.push(root);
		while(!stack.isEmpty()){
			Node<E> node = stack.pop();
			visitor.stop = visitor.visit(node.element);
			if(visitor.stop){
				return;
			}
			if(node.right != null) stack.push(node.right);
			if(node.left != null) stack.push(node.left);
		}
	}
  • 用栈中序遍历(如果左子树结点存在则一直压栈,然后访问自身,最后如果右子树结点存在则继续入栈,重复上述操作)
	@Override
	public void inTraverWithStack(Visitor<E> visitor) {
		if(visitor == null || root == null){
			return;
		}
		Stack<Node<E>> stack = new Stack<Node<E>>();
		stack.push(root);
		Node<E> p = root;
		while(!stack.isEmpty()){
			while(p.left != null){
				stack.push(p.left);
				p = p.left;
			}
			while(!stack.isEmpty()){
				Node<E> node = stack.pop();
				if(visitor.stop = visitor.visit(node.element)){
					return;
				}
				if(node.right != null){
					stack.push(node.right);
					p = node.right;
					break;
				}
			}
		}
	}
  • 用栈后续遍历(后续遍历的结果逆序,发现其为先遍历右子树后遍历左子树的结果,因此只需要将4中的方法返回来,最后用栈逆序即可)
	@Override
	public void postTraverWithStack(Visitor<E> visitor) {
		if(visitor == null || root == null){
			return;
		}
		Stack<Node<E>> stack1 = new Stack<Node<E>>();
		Stack<Node<E>> stack2 = new Stack<Node<E>>();
		stack1.push(root);
		while(!stack1.isEmpty()){
			Node<E> node = stack1.pop();
			stack2.push(node);
			if(node.left != null)stack1.push(node.left);
			if(node.right != null)stack1.push(node.right);
		}
		while(!stack2.isEmpty()){
			if(visitor.stop = visitor.visit(stack2.pop().element)){
				return;
			}
		}
	}

2.6 其他常用的一些函数

  • 将儿叉树翻转,左子树变又子树,右子树变左子树
	public void reverse(){
		reverse(root);
	}
	
	private void reverse(Node<E> root){
		if(root == null){
			return;
		}
		Node<E> tmp = root.left;
		root.left = root.right;
		root.right = tmp;
		reverse(root.left);
		reverse(root.right);
	}
  • 判定是否为完全二叉树
	public boolean isComplite() {
		if(root == null) return false;
		Queue<Node<E>> que = new LinkedList<Node<E>>();
		que.offer(root);
		boolean leaf = false;
		while(!que.isEmpty()){
			Node<E> node = que.poll();
			if(leaf & !node.isLeaf()){
				return false;
			}
			if(node.left != null){
				que.offer(node.left);
			}else if(node.right != null){
				return false;
			}
			if(node.right != null){
				 que.offer(node.right);
			}else{		
				//left==null&&right==null或者 left!=null&&right==null的情况,后面的结点一定都是叶子结点
				leaf = true;
			}
		}
		return true;
	}
  • 递归法获取树的高度
	public int hight(){
		int hight = 0;
		if(root == null){
			return hight;
		}
		int levelSize = 1;
		Queue<Node<E>> que = new LinkedList<Node<E>>();
		que.offer(root);
		while(!que.isEmpty()){
			Node<E> node = que.poll();
			levelSize --;
			if(node.left != null) que.offer(node.left);
			if(node.right != null) que.offer(node.right);
			if(levelSize == 0){	//0表示已经访问完毕
				levelSize = que.size();
				hight ++;
			}
		}		
		return hight;	
	}

3 完整代码

点击跳转到Github

posted @ 2020-06-03 16:38  、、、路遥  阅读(237)  评论(0编辑  收藏  举报