使用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;
		}
		
	}
}

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

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

 

  • 13
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二叉链表是一种常见的二叉树存储结构,它由一个节点数据域、一个指向左子树的指针和一个指向右子树的指针组成。在Java中,可以通过类来实现二叉链表。下面是一个简单的二叉链表实现示例: ``` public class BinaryTreeNode { private int data; private BinaryTreeNode leftChild; private BinaryTreeNode rightChild; public BinaryTreeNode(int data) { this.data = data; this.leftChild = null; this.rightChild = null; } public int getData() { return data; } public void setData(int data) { this.data = data; } public BinaryTreeNode getLeftChild() { return leftChild; } public void setLeftChild(BinaryTreeNode leftChild) { this.leftChild = leftChild; } public BinaryTreeNode getRightChild() { return rightChild; } public void setRightChild(BinaryTreeNode rightChild) { this.rightChild = rightChild; } } ``` 在这个类中,我们定义了一个二叉树节点的数据结构,包括数据域和左右子树的指针。我们可以通过实例化这个类来创建一个二叉链表,其中每个节点都包含一个数据和指向左右子树节点的指针。 下面是一个简单的二叉链表的创建和遍历示例: ``` public class BinaryTree { private BinaryTreeNode rootNode; public void createBinaryTree(int[] array) { for (int i = 0; i < array.length; i++) { insert(array[i]); } } public void insert(int data) { BinaryTreeNode newNode = new BinaryTreeNode(data); if (rootNode == null) { rootNode = newNode; } else { BinaryTreeNode currentNode = rootNode; BinaryTreeNode parentNode; while (true) { parentNode = currentNode; if (data < currentNode.getData()) { currentNode = currentNode.getLeftChild(); if (currentNode == null) { parentNode.setLeftChild(newNode); return; } } else { currentNode = currentNode.getRightChild(); if (currentNode == null) { parentNode.setRightChild(newNode); return; } } } } } public void preOrderTraversal(BinaryTreeNode currentNode) { if (currentNode != null) { System.out.print(currentNode.getData() + " "); preOrderTraversal(currentNode.getLeftChild()); preOrderTraversal(currentNode.getRightChild()); } } public void inOrderTraversal(BinaryTreeNode currentNode) { if (currentNode != null) { inOrderTraversal(currentNode.getLeftChild()); System.out.print(currentNode.getData() + " "); inOrderTraversal(currentNode.getRightChild()); } } public void postOrderTraversal(BinaryTreeNode currentNode) { if (currentNode != null) { postOrderTraversal(currentNode.getLeftChild()); postOrderTraversal(currentNode.getRightChild()); System.out.print(currentNode.getData() + " "); } } public static void main(String[] args) { int[] array = {10, 6, 14, 4, 8, 12, 16}; BinaryTree binaryTree = new BinaryTree(); binaryTree.createBinaryTree(array); System.out.print("PreOrder Traversal: "); binaryTree.preOrderTraversal(binaryTree.rootNode); System.out.println(); System.out.print("InOrder Traversal: "); binaryTree.inOrderTraversal(binaryTree.rootNode); System.out.println(); System.out.print("PostOrder Traversal: "); binaryTree.postOrderTraversal(binaryTree.rootNode); } } ``` 在这个示例中,我们先定义了一个`BinaryTree`类,其中包含了创建二叉链表、插入数据和三种遍历方式的方法。在`createBinaryTree`方法中,我们可以通过传入一个整形数组来创建一个二叉链表。在`insert`方法中,我们可以向二叉链表中插入一个数据。在三种遍历方式的方法中,我们分别实现了先序遍历、中序遍历、后序遍历。在`main`方法中,我们创建了一个二叉链表,然后分别使用三种遍历方式输出二叉树中的节点数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值