使用java实现二叉树的二叉链表存储

       因为二叉树不属于线性结构,所以当使用二叉链表来存储二叉树的时候与之前的其他线性结构(栈、单链表、双链表等)有明显的不同。

注意的地方:

1.提供的内部类定义成静态的、公共的,之前在使用链表实现其他线性结构的数据结构时,基本上使用的都是私有的非静态的内部类。内部类中设有指向左孩子和右孩子的节点以及存放数据的变量。

2.使用二叉链表存储二叉树后,对二叉树的操作与使用数组存储二叉树有明显的不同。

3.在获取二叉树的深度的时候使用了递归调用

                              二叉树二叉链表存储的java实现

java的实现代码如下:

public class TwoLinkBinTree<T> {

	/*
	 * 使用java实现二叉树的二叉链表存储
	 * 注意:因为二叉树不是线性结构,当使用顺序存储(数组)时和其他线性结构的操作差别不是很大,
	 * 	   但是如果使用二叉链表来存储时,则差别很大!具体的差别见如下代码实现。
	 * 要求:
	 * 	1.定义一个私有的内部类,用来存储节点信息
	 * 	2.定义一个私有的节点变量,用来指向根节点
	 * 	3.提供诺干方法用来操作二叉树
	 * */
	
	public static class Node{
		Object data;
		Node left;
		Node right;
		public Node(){
			
		}
		public Node(Object data){
			this.data=data;
			this.left=null;
			this.right=null;
		}
		public Node(Object data,Node left,Node right){
			this.data=data;
			this.left=left;
			this.right=right;
		}
	}
	
	private Node root;
	
	//默认的无参构造函数
	public TwoLinkBinTree(){
		root = new Node();
	}
	
	//根据提供的元素构造二叉树
	public TwoLinkBinTree(T data){
		root = new Node(data);
	}
	
	
	//为指定节点添加子节点
	public Node add(Node parent,T data,boolean isLeft){
		//如果提供的节点为空,则不能添加子节点
		if(parent==null||parent.data==null){
			throw new RuntimeException("节点为空的不能添加子节点");
		}
		Node node=null;
		if(isLeft){//如果要添加的是左子节点
			if(parent.left!=null){
				throw new RuntimeException("该节点的左子节点已经存在");
			}else{
				node=new Node(data);
				parent.left=node;
			}
		}else{//否则添加的是右子节点
			if(parent.right!=null){
				throw new RuntimeException("该节点的右子节点已经存在");
			}else{
				node=new Node(data);
				parent.right=node;
			}
		}
		
		return node;
	}
	
	//判断二叉树是否为空
	public boolean isEmpty(){
		//这里之所以是对data进行判断是因为提供的构造函数都能够保证root不为空,但是data有可能为空
		return root.data==null;
	}
	
	//获取根节点
	public Node getRoot(){
		if(isEmpty()){
			throw new RuntimeException("树为空,不能获取根节点");
		}
		return root;
		
	}
	
	//如果使用的是无参的二叉树构造函数,则可以调用这个方法为root的data设置值
	public void setRootData(T data){
		if(root!=null&&root.data==null){
			root.data=data;
		}else{
			throw new RuntimeException("该根节点已经有数据,不能重新设置");
		}
	}
	
	//获取指定节点的左子节点
	public Node getLeft(Node parent){
		if(parent==null){
			throw new RuntimeException("该根节点为空没有左子节点");
		}else{
			return parent.left;
		}
	}
	
	//获取指定节点的右子节点
	public Node getRight(Node parent){
		if(parent==null){
			throw new RuntimeException("该根节点为空没有右子节点");
		}else{
			return parent.right;
		}
	}
	
	//获取二叉树的深度
	public int getDeep(){
		return deep(root);
	}
	
	//获取指定节点之下的深度
	private int deep(Node node){
		if(node==null){
			return 0;
		}
		if(node.left==null&&node.right==null){
			return 1;
		}else{//采用递归的算法,遍历整个二叉树,每次将节点的最大深度(左子树、右子树深度不一致)传递给父节点
			int leftDeep=deep(node.left);
			int rightDeep=deep(node.right);
			//去深度最大值
			int max=leftDeep>rightDeep?leftDeep:rightDeep;
			return max+1;
		}
		
	}
}

       对于这种二叉链表的二叉树,因为采用链表来记录树中所有节点,所以添加节点没有限制,而且不会希像顺序存储那样产生大量的空间浪费。当然,这种二叉链表的存储方式在遍历树节点时效率不高,指定节点访问其父节点时也是如此,程序必须采用遍历二叉树的方式来搜寻其父节点。至于二叉树的遍历方式我会在接下来的另外一篇博客做详细的介绍。

接下来是二叉树的三叉链表实现,加油!

猜你喜欢

转载自blog.csdn.net/qq_41300571/article/details/82973975