JAVA二叉树的重构

__ 最近复习到了搜索二叉树,实现了搜索二叉树的一些主要的方法。写完后代码十分繁杂。于是对代码进行重构,分为Binarytree(父类),和BTS(子类)。本代码仅供学习参考使用,转载请附出处,搜索二叉树的代码在另一篇中。
~~Binary实现的主要方法有:求树的大小,求树是否为空,树的清空,前序遍历,中序遍历,后续遍历,层序遍历,求树的高度,求前驱,求后继,求是否为完全二叉树,以及简单的打印树状二叉树
其中加入了Visitor抽象类,用来实现二叉树打印随时停止,还有对数据的操作逻辑。

代码如下

package tree;

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

/**
 * 树的重构 
 * @author 65481
 *
 * @param <E>
 */


public class BinaryTree<E> {
	/*
	 成员变量
	 */
	protected int size;
	protected Node<E> root;	
	
	
	
	/*
	 节点类
	 */
	protected static class Node<E>{
		E element;
		Node<E> left;
		Node<E> right;
		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() {
			return left != null && right != null;
		}	
	}
	
	
	
	/*
	 自定义抽象类 完成对数据的操作逻辑
	 boolean visit 如果返回true 则停止遍历
	 */
	public static abstract class Visitor<E>{
		boolean stop;
		abstract boolean visit(E element);
	}
	
	
	/*
	 节点数量方法
	 */
	public int size() {
		return size;
	}
	
	/*
	 树是否为空方法
	 */
	public boolean isEmpty() {
		return size == 0;
	}
	
	/*
	 清空树的方法
	 */
	public void clear() {
		root = null;
		size = 0;
	}
	
	/*
	 递归的前序遍历
	 */
	public void preorderTraversal(Visitor<E> visitor) {
		if (visitor == null) {
			return;
		}
		preorderTraversal(root,visitor);
		
	}
	
	//从根节点开始
	private void preorderTraversal(Node<E> node,Visitor<E> visitor){
		//递归出来的条件
		if (node == null||visitor.stop) {
			return;
		}
		if (visitor.stop) return;
		visitor.stop = visitor.visit(node.element);
		preorderTraversal(node.left,visitor);
		preorderTraversal(node.right,visitor);
	}
	
	/*
	 递归的中序遍历
	 */
	public void midorderTraversal(Visitor<E> visitor) {
		midorderTraversal(root,visitor);
	}
	
	private void midorderTraversal(Node<E> node,Visitor<E> visitor) {
		//递归出来条件
		if (node == null||visitor.stop) {
			return;
		}
		
		midorderTraversal(node.left,visitor);
		if (visitor.stop) return;
		visitor.stop = visitor.visit(node.element);
		midorderTraversal(node.right,visitor);
		
	}
	
	/*
	 后续遍历
	 */
	public void lastorderTraversal(Visitor<E> visitor) {
		lastorderTraversal(root,visitor);
	}
	
	private void lastorderTraversal(Node<E> node,Visitor<E> visitor) {
		//递归出来条件
		if (node == null||visitor.stop) {
			return;
		}
		lastorderTraversal(node.left,visitor);
		lastorderTraversal(node.right,visitor);
		if (visitor.stop) return;
		visitor.stop = visitor.visit(node.element);
	}
	
	/*
	 层序遍历
	 */
	public void levelOrderTranversal(Visitor<E> visitor) {
		if (root == null) {
			return;
		}
		//创建队列
		Queue<Node<E>> queue = new LinkedList<>();
		queue.offer(root);
		
		while(!queue.isEmpty()) {
			//弹出头结点
			Node<E> poll = queue.poll();
			//打印
			if (visitor.visit(poll.element)) {
				return;
			}
			
			if (poll.left != null) {
				queue.offer(poll.left);
			}
			
			if (poll.right != null) {
				queue.offer(poll.right);
			}
			
		}
		
	}
	
	/*
	 树状打印二叉树
	 */
	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer();
		toString(root,sb,"");
		return sb.toString();
	}
	/**
	 * 
	 * @param node  节点
	 * @param sb	用于拼接
	 * @param prdix 此节点的前驱
	 */
	public void toString(Node<E> node,StringBuffer sb,String prefix) {
		
		if (node == null) {
			return;
		}
		
		toString(node.left,sb,prefix + "L--");
		sb.append(prefix).append(node.element).append("\n");
		toString(node.right,sb,prefix + "R--");
		
	}
	
	/*
	前驱节点 
	 */
	
	protected Node<E> predecessor(Node<E> node) {
		//空节点
		if (node == null) {
			return null;
		}
		
		//前驱节点在左子树当中 left.right.right.right
		Node<E> p = node.left;
		if (p != null) {
			
			while(p.right != null) {
				p = p.right;
			}
			return p;
		}
		//从祖父节点中寻找前驱节点
		while(node.parent != null && node == node.parent.left) {
			node = node.parent;
		}
		return node.parent;
	}
	
	
	/*
	 后继节点
	 */
	
	protected Node<E> successor(Node<E> node) {
		//空节点
		if (node == null) {
			return null;
		}
		//后继节点在右子树中 right.left.left.left
		Node<E> p = node.right;
		if (p != null) {
			while(p.left != null) {
				p = p.left;
			}
			return p;
		}
		//从祖父节点中寻找前驱
		while(node.parent != null && node == node.parent.right) {
			node = node.parent;
		}
		return node.parent;
		
	}
	
	/*
	 判断一棵树是完全二叉树
	 */
	public boolean isComplete() {
		
		//根节点为空
		if (root == null) { return false;}
		
		//队列加入子节点
		Queue<Node<E>> queue = new LinkedList<>();
		queue.offer(root);
		
		//判断标识 false为不是叶子节点 true为是叶子节点
		boolean leaf = false;
		
		
		//判断逻辑
		while(!queue.isEmpty()) {

			
			Node<E> node = queue.poll();
			
			if (node.isLeaf() && !leaf) {
				return false;
			}
			if (node.left != null) {
				queue.offer(node.left);
			}else if (node.right != null) {
				return false;
			}
			
			if (node.right != null) {
				queue.offer(node.right);
			}else {
				//剩下的节点都是叶子节点
				leaf = true;
			}
			
		}
		
		return true;
	}

	/*
	 二叉树的高度
	 */	
	//非递归实现(使用了层序遍历)
	public int height() {
		if (root == null) {
			return 0;
		}
		//树的高度
		int height = 0;
		
		//存储着每一层的元素数量
		int levelSize = 1;
		
		//创建队列
		Queue<Node<E>> queue = new LinkedList<>();
		queue.offer(root);
		
		while(!queue.isEmpty()) {
			//弹出头结点
			Node<E> poll = queue.poll();
			levelSize --;
			
			if (poll.left != null) {
				queue.offer(poll.left);
			}
			
			if (poll.right != null) {
				queue.offer(poll.right);
			}
			
			//说明即将访问下一层
			if (levelSize == 0) {
				levelSize = queue.size();
				height ++;
			}
		}
		return height;
}
}

猜你喜欢

转载自blog.csdn.net/qq_43507104/article/details/105800203