Java实现二叉树

来源:互联网 发布:oracle数据库自动备份 编辑:程序博客网 时间:2024/05/16 12:33

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

实现二叉树结点

首先定义结点的一个接口,指出结点类应有的功能,即结点的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;}@Overridepublic Object val() {return this.element;}@Overridepublic void setVal(Object obj) {this.element = obj;}@Overridepublic BinNode left() {return lc;}@Overridepublic void setLeft(BinNode bn) {lc = (BinNodePtr) bn;}@Overridepublic BinNode right() {return rc;}@Overridepublic void setRight(BinNode bn) {rc = (BinNodePtr) bn;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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是树类的一个成员函数,并且结点子类对树类的用户是透明的,则应优先选择第一种。如果有意把结点与树相互分开,不让树的用户知道结点的存在,则应优先考虑第二种。


未完持续

原创粉丝点击