java用三叉链表构造二叉树_Java基础 - 二叉树的三叉链表存储

本文介绍了如何使用Java实现三叉链表存储二叉树,每个节点包含data、left、right和parent指针,方便访问子节点和父节点。详细讲解了节点的添加方法以及获取父节点、子节点的函数,并提供了计算树深度的函数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.yc.tree;

/**

* @author WB

* @param

*

* 三叉链表存储的思想是让每个节点不仅“记住”它的左、右两个子节点,还要“记住”它的父节点,因此需要为每个节点增加left、right和parent

* 三个指针,分别引用该节点的左、右两个子节点和父节点。因此,三叉链表的每个节点有如下图所示的结构。

* ↑parent

* _│_______________________

* │ │ │ │ │

* │ ● │ ● │ data │ ● │

* │____│____│______│____│

* │ │

* ↓left ↓right

*

* 二叉链表存储和三叉链表都是根据该二叉树的节点特征来划分的。对于二叉链表存储而言,二叉树的每个节点需要两个“分叉”,分别记录该节点的左、右两个子节点;

* 对于三叉链表存储而言,二叉树的每个节点需要三个“分叉”,分别记录该节点的左、右两个子节点和父节点。

*

* 因此,三叉链表存储的二叉树的节点大致有如下定义:

* class Node{

* Object data;

* Node left;

* Node right;

* Node parent;

* }

* 对于这种三叉链表存储的二叉树,如果程序需要,为指定节点添加子节点也非常容易,除了要维护父节点的left、right引用之外,还要维护新增节点的parent引用。

*

* 从下面的粗体字代码可以看出,三叉链表莻方式是对二叉链表的一种改进,通过为树节点增加一parent'引用,可以让每个节点都能非常方便地访问其父节点。

* 三叉链表存储的二叉树既可以方便地向下访问节点,也可以方便地向上访问节点。

*

* 下面程序实现了二叉树。

*/

public class ThreeLinkBinTree {

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、付费专栏及课程。

余额充值