Java基础 - 二叉树的三叉链表存储

  
package com.yc.tree;


/**
 * @author WB
 * @param <E>
 * 
 * 三叉链表存储的思想是让每个节点不仅“记住”它的左、右两个子节点,还要“记住”它的父节点,因此需要为每个节点增加left、right和parent
 * 三个指针,分别引用该节点的左、右两个子节点和父节点。因此,三叉链表的每个节点有如下图所示的结构。
 *   ↑parent
 *  _│_______________________
 * │    │    │      │    │
 * │ ● │ ● │ data │ ● │
 * │____│____│______│____│
 * 	    │		  │
 * 	    ↓left	  ↓right
 * 
 * 二叉链表存储和三叉链表都是根据该二叉树的节点特征来划分的。对于二叉链表存储而言,二叉树的每个节点需要两个“分叉”,分别记录该节点的左、右两个子节点;
 * 对于三叉链表存储而言,二叉树的每个节点需要三个“分叉”,分别记录该节点的左、右两个子节点和父节点。
 * 
 * 因此,三叉链表存储的二叉树的节点大致有如下定义:
 * class Node{
 * 		Object data;
 * 		Node left;
 * 		Node right;
 * 		Node parent;
 * }
 * 对于这种三叉链表存储的二叉树,如果程序需要,为指定节点添加子节点也非常容易,除了要维护父节点的left、right引用之外,还要维护新增节点的parent引用。
 * 
 * 从下面的粗体字代码可以看出,三叉链表莻方式是对二叉链表的一种改进,通过为树节点增加一parent'引用,可以让每个节点都能非常方便地访问其父节点。
 * 三叉链表存储的二叉树既可以方便地向下访问节点,也可以方便地向上访问节点。
 * 
 * 下面程序实现了二叉树。
 */
public class ThreeLinkBinTree <E>{
	public static class Node{
		Object data;
		Node parent;
		Node left;
		Node right;

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

	private Node root;

	public ThreeLinkBinTree(){
		this.root = new Node();
	}
	public ThreeLinkBinTree(E data){
		this.root = new Node(data);
	}

	//根据根节点中的data判断是否为空树
	public boolean isEmpty(){
		return root.data == null;
	}

	//返回根节点
	public Node root(){
		exceptionForRoot();
		return root;
	}
	/**
	 * 为指定节点添加子节点
	 * @param parent :指定节点
	 * @param data	   :数据元素
	 * @param isLeft :是否是左子节点
	 */
	public void add(Node parent, Object data, boolean isLeft){
		exceptionForAdd(parent, isLeft);
		Node newNode = new Node(data);
		if(isLeft){
			parent.left = newNode;
			newNode.parent = parent;
		}else{
			parent.right = newNode;
			newNode.parent = parent;
		}
	}

	/*
	 * 向指定节点添加子节点并返回该子节点
	 */
	public Node addAndReturn(Node parent, Object data, boolean isLeft){
		exceptionForAdd(parent, isLeft);
		Node newNode = new Node(data);
		if(isLeft){
			parent.left = newNode;
			newNode.parent = parent;
		}else{
			parent.right = newNode;
			newNode.parent = parent;
		}
		return newNode;
	}

	//返回非根节点的父节点
	public Node parent(Node node){
		exceptionForParent(node);
		
		return node.parent;
	}

	//返回左子节点
	@SuppressWarnings("unchecked")
	public E leftChild(Node node){
		exceptionForLeftChild(node);

		return  node.left == null ? null : (E)node.left.data;
	}

	//返回右子节点
	@SuppressWarnings("unchecked")
	public E rightChild(Node node){
		exceptionForRightChild(node);

		return  node.right == null ? null : (E)node.right.data;
	}

	//返回该树的深度
	public int deep(){
		return deep(root);
	}

	private int deep(Node node) {
		if(node == null){
			return 0;
		}

		if(node.left == null && node.right == null){
			return 1;
		}else{
			int deepRight = deep(node.right);
			int deepLeft = deep(node.left);
			return deepLeft > deepRight ? deepLeft + 1 : deepRight + 1;
		}

	}
	private void exceptionForAdd(Node parent, boolean isLeft){
		if(parent == null){
			throw new RuntimeException("指定节点在二叉链表中不存在,无法为其添加子节点");
		}
		if(isLeft && parent.left != null){
			throw new RuntimeException("指定节点在二叉链表中已存在左子节点");
		}
		if(!isLeft && parent.right != null){
			throw new RuntimeException("指定节点在二叉链表中已存在右子节点");
		}
	}
	private void exceptionForRoot(){
		if(isEmpty()){
			throw new RuntimeException("该树为空树,无根节点");
		}
	}
	private void exceptionForParent(Node node){
		if(node == root){
			throw new RuntimeException("该节点为根节点,无父节点");
		}
		if(node == null){
			throw new RuntimeException("该节点为null,无父节点");
		}
	}
	private void exceptionForLeftChild(Node node){
		if(node == null){
			throw new RuntimeException("该节点为null,无左子节点");
		}
	}
	private void exceptionForRightChild(Node node) {
		if(node == null){
			throw new RuntimeException("该节点为null,无右子节点");
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值