对于二叉树的操作,有些是关于节点的(如指向子结点和获取值),而有一些则是关于整棵树的(如初始化),所以要分别实现二叉树和结点
实现二叉树结点
首先定义结点的一个接口,指出结点类应有的功能,即结点的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是树类的一个成员函数,并且结点子类对树类的用户是透明的,则应优先选择第一种。如果有意把结点与树相互分开,不让树的用户知道结点的存在,则应优先考虑第二种。
未完持续