您的位置:首页 > 编程语言 > Java开发

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

2016-11-09 20:03 465 查看
  
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("该节点为根节点,无父节点");
}
e878
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,无右子节点");
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: