Java实现二叉树

对于二叉树的操作,有些是关于节点的(如指向子结点和获取值),而有一些则是关于整棵树的(如初始化),所以要分别实现二叉树和结点

实现二叉树结点

首先定义结点的一个接口,指出结点类应有的功能,即结点的ADT

package binaryTree;

//二叉树节点的接口
public interface BinNode {
	//得到当前节点的值
	Object val();
	//设置当前节点的值
	void setVal(Object obj);
	//获得当前节点的左子节点
	BinNode left();
	//设置当前的左子节点
	void setLeft(BinNode bn);
	//获得当前节点的右子节点
	BinNode right();
	//设置当前结点的右子结点
	void setRight(BinNode bn);
	//判断当前节点是否是叶子节点
	boolean isLeaf();
}

接着实现二叉树的结点类,这里实现可以分开叶子结点和内部结点,也可以不分开

首先不分开实现

package binaryTree;

public class BinNodePtr implements BinNode {
	private Object element;
	private BinNodePtr lc;
	private BinNodePtr rc;
	
	public BinNodePtr()
	{
		lc = rc = null;
	}
	public BinNodePtr(Object element,BinNodePtr lc,BinNodePtr rc)
	{
		this.element = element;
		this.lc = lc;
		this.rc = rc;
	}
	@Override
	public Object val() {
		return this.element;
	}

	@Override
	public void setVal(Object obj) {
		this.element = obj;
		
	}

	@Override
	public BinNode left() {
		return lc;
	}

	@Override
	public void setLeft(BinNode bn) {
		lc = (BinNodePtr) bn;
		
	}

	@Override
	public BinNode right() {
		return rc;
	}

	@Override
	public void setRight(BinNode bn) {
		rc = (BinNodePtr) bn;
		
	}
	@Override
	public boolean isLeaf() {
		return (lc == null) && (rc == null);
	}

	public static void main(String[] args)
	{
		
	}
}

分开叶子结点和内部结点(不实现所有功能)
package binaryTree;



public class VarBinNode {
	private enum Nodetype{leaf,internal};
	
	Nodetype mytype;
	class InnerNode
	{
		VarBinNode left;
		VarBinNode right;
		Object opx;
	}
	InnerNode intl = new InnerNode();
	Object var;
	public VarBinNode(Object var)
	{
		mytype = Nodetype.leaf;
		this.var = var;
	}
	
	public VarBinNode(Object op,VarBinNode left,VarBinNode right)
	{
		mytype = Nodetype.internal;
		intl.opx = op;
		intl.left = left;
		intl.right = right;
	}
	
	boolean isLeaf()
	{
		return mytype == Nodetype.leaf;
	}
	VarBinNode leftchild()
	{
		return intl.left;
	}
	VarBinNode rightchild()
	{
		return intl.right;
	}
	
	void traverse(VarBinNode subroot)//中序遍历二叉树
	{
		if(subroot == null)
			return;
		if(subroot.isLeaf())
			System.out.println("Leaf:" + subroot.var);
		else
		{
			System.out.println("Internal:" + subroot.intl.opx);
			traverse(subroot.leftchild());
			traverse(subroot.rightchild());
		}
	}
	public static void main(String[] args)
	{
		VarBinNode vbnl = new VarBinNode(3);
		VarBinNode vbnr = new VarBinNode(2);
		VarBinNode vbnlr = new VarBinNode((Object)1,vbnl,vbnr);
		vbnlr.traverse(vbnlr);
	}
}

为叶子结点和内部结点分开建类,以便添加更多的细节

package binNodeTest;

interface VarBinNode
{
	boolean isLeaf();
}

class LeafNode implements VarBinNode
{
	private Object obj;
	
	public LeafNode(Object obj)
	{
		this.obj = obj;
	}
	@Override
	public boolean isLeaf() {
		return true;
	}
	public Object value()
	{
		return obj;
	}
	
}

class IntlNode implements VarBinNode
{
	private VarBinNode left;
	private VarBinNode right;
	private Object obj;
	
	public IntlNode(Object obj,VarBinNode left,VarBinNode right)
	{
		this.obj = obj;
		this.left = left;
		this.right = right;
	}
	@Override
	public boolean isLeaf() {
		return false;
	}
	VarBinNode leftchild()
	{
		return left;
	}
	VarBinNode rightchild()
	{
		return right;
	}
	Object value()
	{
		return obj;
	}
}
public class BinNodeTest {
	void traverse(VarBinNode subroot)//前序遍历
	{
		if(subroot == null)
			return;
		if(subroot.isLeaf())
			System.out.println("LeafNode : " + ((LeafNode)subroot).value());
		else
		{
			System.out.println("IntlNode : " + ((IntlNode)subroot).value());
			traverse(((IntlNode)subroot).leftchild());
			traverse(((IntlNode)subroot).rightchild());
		}
	}
	
	public static void main(String[] args)
	{
		
	}
	

}

另一种实现traverse()函数的方法

package binNodeTest;

interface VarBinNode
{
	boolean isLeaf();

	void trav();
}

class LeafNode implements VarBinNode
{
	private Object obj;
	
	public LeafNode(Object obj)
	{
		this.obj = obj;
	}
	@Override
	public boolean isLeaf() {
		return true;
	}
	public Object value()
	{
		return obj;
	}
	public void trav()
	{
		System.out.println("LeafNode : " + value());
	}
}

class IntlNode implements VarBinNode
{
	private VarBinNode left;
	private VarBinNode right;
	private Object obj;
	
	public IntlNode(Object obj,VarBinNode left,VarBinNode right)
	{
		this.obj = obj;
		this.left = left;
		this.right = right;
	}
	@Override
	public boolean isLeaf() {
		return false;
	}
	VarBinNode leftchild()
	{
		return left;
	}
	VarBinNode rightchild()
	{
		return right;
	}
	Object value()
	{
		return obj;
	}
	public void trav()
	{
		System.out.println("IntlNode : " + value());
		if(leftchild() != null)
			leftchild().trav();
		if(rightchild() != null)
			rightchild().trav();
	}
}
public class BinNodeTest {
	/*void traverse(VarBinNode subroot)//前序遍历
	{
		if(subroot == null)
			return;
		if(subroot.isLeaf())
			System.out.println("LeafNode : " + ((LeafNode)subroot).value());
		else
		{
			System.out.println("IntlNode : " + ((IntlNode)subroot).value());
			traverse(((IntlNode)subroot).leftchild());
			traverse(((IntlNode)subroot).rightchild());
		}
	}*/
	void traverse(VarBinNode root)
	{
		if(root != null)
			root.trav();
	}
	public static void main(String[] args)
	{
		
	}
	

}

比较两中实现方法,两种方法都有自己的优缺点

1、第一种方法不要求结点类明确支持traverse函数,用这种方法很容易给树类添加新的周游方法,而第二种方法要求对树进行周游的新操作都要在结点的子类中实现

2、第二种方法使得traverse不必了解结点子类独特的功能细节,子类自己负责周游处理工作

3、第二种方法traverse函数不需要明确的枚举所有不同的子类,直接就能做合适的操作

4、一般情况下,如果traverse是树类的一个成员函数,并且结点子类对树类的用户是透明的,则应优先选择第一种。如果有意把结点与树相互分开,不让树的用户知道结点的存在,则应优先考虑第二种。


未完持续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值