二叉树的链表存储,就是让每个节点都能保存指向其左右节点的信息。为每个节点添加left和right两个指向(指针),分别引用该节点的左右节点。
首先定义节点:
package my.bintree;
public class TreeNode<T> {
private T data;
private TreeNode<T> left;
private TreeNode<T> right;
public TreeNode(){
}
public TreeNode(T data){
this.data = data;
}
public TreeNode(T data, TreeNode<T> left, TreeNode<T> right){
this.data = data;
this.left = left;
this.right = right;
}
public Object getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public TreeNode<T> getLeft() {
return left;
}
public void setLeft(TreeNode<T> left) {
this.left = left;
}
public TreeNode<T> getRight() {
return right;
}
public void setRight(TreeNode<T> right) {
this.right = right;
}
}
然后,实现二叉树的链表存储,其中获取二叉树的深度为关键操作。
package my.bintree;
public class LinkBinTree<T> {
private TreeNode<T> root;
public LinkBinTree(TreeNode<T> root){
this.root = root;
}
public LinkBinTree(T data){
this.root = new TreeNode<T>(data);
}
public boolean isEmpty(){
return root == null;
}
//获取根节点,如果非空
public TreeNode<T> getRoot(){
if(isEmpty()){
throw new RuntimeException("tree is empty");
}
return this.root;
}
//获取指定节点(非根节点)的父节点,需要遍历整个二叉树
public TreeNode<T> getParent(TreeNode<T> node){
return null;
}
//返回指定节点(非叶子节点)的左节点的数据,如果左节点不在返回null
@SuppressWarnings("unchecked")
public T leftChild(TreeNode<T> parent){
if(parent == null){
throw new RuntimeException("节点为空");
}
return parent.getLeft() == null ? null : (T)parent.getLeft().getData();
}
//返回指定节点(非叶子节点)的右节点的数据,如果左节点不在返回null
@SuppressWarnings("unchecked")
public T rightChild(TreeNode<T> parent){
if(parent == null){
throw new RuntimeException("节点为空");
}
return parent.getRight() == null ? null : (T)parent.getRight().getData();
}
/**
* 为指定节点添加子节点
* @param parent 需要添加左右节点的节点
* @param data 子节点的数据
* @param isLeft 是否为左右节点:true 左节点,false 右节点
* @return
*/
public TreeNode<T> addNode(TreeNode<T> parent, T data, boolean isLeft){
if(parent == null){
throw new RuntimeException("节点为空,不能添加子节点");
}
if(isLeft && parent.getLeft() != null){
throw new RuntimeException("节点也有左节点,不能添加子节点");
}
if(!isLeft && parent.getRight() != null){
throw new RuntimeException("节点也有右节点,不能添加子节点");
}
TreeNode<T> newNode = new TreeNode<T>(data);
if(isLeft){
parent.setLeft(newNode);
}else{
parent.setRight(newNode);
}
return newNode;
}
public int getDeep(){
return getDeep(this.root);
}
//采用递归的方式来获取节点的深度
public int getDeep(TreeNode<T> node){
if(node == null){
return 0;
}
if(node.getLeft() == null && node.getRight() == null){
return 1;
}else{
int leftDeep = getDeep(node.getLeft());
int rightDeep = getDeep(node.getRight());
int max = leftDeep > rightDeep ? leftDeep : rightDeep;
//如果该节点有子树,必须计算一次
return max + 1;
}
}
}
最后,编写一个客户端,来时测试二叉树的链表存储是否正确:
package my.bintree;
public class LinkBinTreeClient {
public static void main(String[] args){
LinkBinTree<String> tree = new LinkBinTree<String>("root");
TreeNode<String> b = tree.addNode(tree.getRoot(), "left", true);
TreeNode<String> c = tree.addNode(tree.getRoot(), "right", false);
tree.addNode(b,"left",true);
System.out.println(tree.toString());
System.out.println(tree.getDeep());
}
}
控制台输出:
my.bintree.LinkBinTree@1fc4bec
3