二叉树的仿真JAVA实现
本程序用链表去仿真二叉树查找树与二叉平衡树
以下代码用Eclipse3.40编译通过
使用的文件清单如下:
Node.java //链结点interface
SLNode.java //单向链结点实现类
DLNode.java //双向链结点实现类
Strategy.java //两个数据比较interface
DefaultStrategy.java //两个数据比较实现类
SearchTable.java //查找表interface
BinTreeNode.java //二叉树结点
BinTree.java //二叉树interface
BinaryTreeLinked.java //链式二叉树
BSTree.java //二叉查找树
AVLTree.java //二叉平衡树
BTeeDemo.java //二叉树功能测试类
*******************************************************
//编译OK chinanetboy with Eclipse
//Node.java
//链结点接口
package dsa.datastruct;
public interface Node{
//获取结点数据域
public Object getData();
//设置结点数据域
public void setData(Object obj);
}
*******************************************************
//编译OK chinanetboy with Eclipse
//SLNode.java
//单向链表实现
package dsa.datastruct;
public class SLNode implements Node{
private Object element; //数据成员
private SLNode next; //指向下一个成员结点
//两个构造器
public SLNode(){this(null,null);}
public SLNode(Object obj, SLNode nextnode){
this.element=obj;
this.next =nextnode;
}
//2对属性读取器
public void setNext(SLNode nextnode){this.next=nextnode;}
public SLNode getNext(){return next;}
public void setData(Object obj){element=obj;}
public Object getData(){return element;}
}
*******************************************************
//file name: DLNode.java
//双向链表的实现类
package dsa.datastruct;
import dsa.datastruct.Node;
public class DLNode implements Node {
private Object element;
private DLNode pre;
private DLNode next;
//0.构造器
public DLNode(){this(null,null,null);}
public DLNode(Object obj,DLNode p,DLNode n){
this.element=obj;
this.pre=p;
this.next=n;
}
//1.Next存取器
public DLNode getNext(){return next;}
public void setNext(DLNode n){this.next=n;}
//2.pre存取器
public DLNode getPre(){return pre;}
public void setPre(DLNode p){this.pre=p;}
//3.element存取器
public Object getData() {return element;}
public void setData(Object o) {this.element=o;}
}
*******************************************************
/*file name:SearchTable.java
*查找表接口
**/
package dsa.datastruct;
public interface SearchTable {
//1.查询查找表当前的规模
public int getSize();
//2.判断查找表是否为空
public boolean isEmpty();
//3.返回查找表中与元素ele关键字相同的元素位置;否则,返回null
public Node search(Object ele);
//4.返回所有关键字与元素ele相同的元素位置
public Iterator searchAll(Object ele);
//5.按关键字插入元素ele
public void insert(Object ele);
//6.若查找表中存在与元素ele关键字相同元素,则删除一个并返回;否则,返回null
public Object remove(Object ele);
}
*******************************************************
//file name:Strategy.java
//判断两个对象之间是否相同或者相等
package dsa.datastruct;
public interface Strategy {
//判断两个数据元素是否相等
/**
* 比较两个数据元素的大小
* 如果obj1 < obj2 返回-1
* 如果obj1 = obj2 返回0
* 如果obj1 > obj2 返回1
*/
public boolean equal(Object obj1, Object obj2);
public int compare(Object obj1, Object obj2);
}
*******************************************************
//filename DefaultStrategy.java
//判断两个对象是否相等的类实现
package dsa.datastruct;
public class DefaultStrategy implements Strategy {
public boolean equal(Object obj1, Object obj2){
return obj1.toString().equals(obj2.toString());
}
public int compare(Object obj1, Object obj2){
int comp = obj1.toString().compareTo(obj2.toString());
if (comp==0) return 0;
else if (comp>0) return 1;
else return -1;
}
}
*******************************************************
/*file name:SearchTable.java
*查找表接口
**/
package dsa.datastruct;
public interface SearchTable {
//1.查询查找表当前的规模
public int getSize();
//2.判断查找表是否为空
public boolean isEmpty();
//3.返回查找表中与元素ele关键字相同的元素位置;否则,返回null
public Node search(Object ele);
//4.返回所有关键字与元素ele相同的元素位置
public Iterator searchAll(Object ele);
//5.按关键字插入元素ele
public void insert(Object ele);
//6.若查找表中存在与元素ele关键字相同元素,则删除一个并返回;否则,返回null
public Object remove(Object ele);
}
*******************************************************
//BinTreeNode.java
//二叉树结点专用类
package dsa.datastruct;
public class BinTreeNode implements Node {
private Object data; //数据域
private BinTreeNode parent;//父结点
private BinTreeNode lChild;//左孩子
private BinTreeNode rChild;//右孩子
private int height; //树的高度
private int size; //该结点子孙数
//0.构造器2个
public BinTreeNode() {this(null);}
public BinTreeNode(Object e){
data = e;
parent = lChild = rChild = null;
height = 0;
size = 1;
}
//1.Node接口实现方法
public Object getData(){return data;}
public void setData(Object obj){data=obj;}
/*2.判断当前结点位置方法*/
//判断是否有父亲
public boolean hasParent(){ return parent!=null;}
//判断是否有左孩子
public boolean hasLChild(){ return lChild!=null;}
//判断是否有右孩子
public boolean hasRChild(){ return rChild!=null;}
//判断是否为叶子结点
public boolean isLeaf(){ return !hasLChild()&&!hasRChild();}
//判断是否为某结点的左孩子
public boolean isLChild(){ return (hasParent()&&this==parent.lChild);}
//判断是否为某结点的右孩子
public boolean isRChild(){ return (hasParent()&&this==parent.rChild);}
/*3.height相关方法*/
//取结点的高度,即以该结点为根的树的高度
public int getHeight() { return height; }
//更新当前结点及其祖先的高度
public void updateHeight(){
int newH = 0;//新高度初始化为0,高度等于左右子树高度加1中大的
if (hasLChild()) newH = Math.max(newH,1+getLChild().getHeight());
if (hasRChild()) newH = Math.max(newH,1+getRChild().getHeight());
if (newH==height) return; //高度没有发生变化则直接返回
height = newH; //否则更新高度
if (hasParent()) getParent().updateHeight(); //递归更新祖先的高度
}
/*4.size相关方法*/
//取以该结点为根的树的结点数
public int getSize() { return size; }
//更新当前结点及其祖先的子孙数
public void updateSize(){
size = 1; //初始化为1,结点本身
if (hasLChild()) size += getLChild().getSize(); //加上左子树规模
if (hasRChild()) size += getRChild().getSize(); //加上右子树规模
if (hasParent()) getParent().updateSize(); //递归更新祖先的规模
}
/*5.parent相关方法*/
//取父结点
public BinTreeNode getParent() { return parent; }
//断开与父亲的关系
public void sever(){
if (!hasParent()) return;
if (isLChild()) parent.lChild = null;
else parent.rChild = null;
parent.updateHeight(); //更新父结点及其祖先高度
parent.updateSize(); //更新父结点及其祖先规模
parent = null;
}
/*6.与左孩子lChild相关方法*/
//取左孩子
public BinTreeNode getLChild() { return lChild; }
//设置当前结点的左孩子,返回原左孩子
public BinTreeNode setLChild(BinTreeNode lc){
BinTreeNode oldLC = this.lChild;
if (hasLChild()) { lChild.sever();} //断开当前左孩子与结点的关系
if (lc!=null){
lc.sever(); //断开lc与其父结点的关系
this.lChild = lc; //确定父子关系
lc.parent = this;
this.updateHeight(); //更新当前结点及其祖先高度
this.updateSize(); //更新当前结点及其祖先规模
}
return oldLC; //返回原左孩子
}
/*7.与右孩子rChild相关方法*/
//取右孩子
public BinTreeNode getRChild() { return rChild; }
//设置当前结点的右孩子,返回原右孩子
public BinTreeNode setRChild(BinTreeNode rc){
BinTreeNode oldRC = this.rChild;
if (hasRChild()) { rChild.sever();} //断开当前右孩子与结点的关系
if (rc!=null){
rc.sever(); //断开lc与其父结点的关系
this.rChild = rc; //确定父子关系
rc.parent = this;
this.updateHeight(); //更新当前结点及其祖先高度
this.updateSize(); //更新当前结点及其祖先规模
}
return oldRC; //返回原右孩子
}
}
*******************************************************
/*file name:BinTree.java
* 二叉树接口interface
* */
package dsa.datastruct;
//导入二叉树结点类
import dsa.datastruct.BinTreeNode;
public interface BinTree {
//返回树的规模
public int getSize();
//判断树是否为空
public boolean isEmpty();
//返回根结点引用
public BinTreeNode getRoot();
//获取树的高度
public int getHeight();
//在树中查找元素e,返回其所在结点
public BinTreeNode find(Object e);
//先序遍历二叉树
public Iterator preOrder();
//中序遍历二叉树
public Iterator inOrder();
//后序遍历二叉树
public Iterator postOrder();
//按层遍历二叉树
public Iterator levelOrder();
}
*******************************************************
/*file name:BinaryTreeLinked.java
*二叉树实现类
**/
package dsa.datastruct;
import dsa.datastruct.BinTree;
import dsa.datastruct.BinTreeNode;
import dsa.datastruct.Strategy;
import dsa.datastruct.DefaultStrategy;
import dsa.datastruct.LinkedList;
import dsa.datastruct.LinkedListDLNode;
public class BinaryTreeLinked implements BinTree {
protected BinTreeNode root;
protected Strategy strategy;
//0.构造器
public BinaryTreeLinked(){ this(null); }
public BinaryTreeLinked(BinTreeNode root) { this(root,new DefaultStrategy());}
public BinaryTreeLinked(BinTreeNode root, Strategy strategy){
this.root = root;
this.strategy = strategy;
}
//1.返回树的规模
public int getSize() { return root==null?0:root.getSize(); }
//2.判断树是否为空
public boolean isEmpty() { return root==null;}
//3.返回根结点引用
public BinTreeNode getRoot() { return root;}
//4.获取树的高度
public int getHeight() { return isEmpty()?-1:root.getHeight();}
//5.在树中查找元素e,返回其所在结点
public BinTreeNode find(Object e) { return searchE(root,e); }
//6.递归查找元素e
private BinTreeNode searchE(BinTreeNode rt, Object e) {
if (rt==null) return null;
if (strategy.equal(rt.getData(),e)) return rt; //如果是根结点,返回根
BinTreeNode v = searchE(rt.getLChild(),e); //否则在左子树中找
if (v==null) v = searchE(rt.getRChild(),e); //没找到,在右子树中找
return v;
}
//7.1先序遍历二叉树
public Iterator preOrder() {
LinkedList list = new LinkedListDLNode();
preOrderRecursion(this.root,list);
return list.elements();
}
//7.2先序遍历的递归算法
private void preOrderRecursion(BinTreeNode rt, LinkedList list){
if (rt==null) return; //递归基,空树直接返回
list.insertLast(rt); //访问根结点
preOrderRecursion(rt.getLChild(),list); //遍历左子树
preOrderRecursion(rt.getRChild(),list); //遍历右子树
}
//7.3先序遍历的非递归算法
private void preOrderTraverse(BinTreeNode rt, LinkedList list){
if (rt==null) return;
BinTreeNode p = rt;
Stack s = new StackSLinked();
while (p!=null){
while (p!=null){ //向左走到尽头
list.insertLast(p); //访问根
if (p.hasRChild()) s.push(p.getRChild()); //右子树根结点入栈
p = p.getLChild();
}
if (!s.isEmpty()) p = (BinTreeNode)s.pop(); //右子树根退栈遍历右子树
}
}
//8.1中序遍历二叉树
public Iterator inOrder(){
LinkedList list = new LinkedListDLNode();
inOrderRecursion(this.root,list);
return list.elements();
}
//8.2中序遍历的递归算法
private void inOrderRecursion(BinTreeNode rt, LinkedList list){
if (rt==null) return; //递归基,空树直接返回
inOrderRecursion(rt.getLChild(),list); //遍历左子树
list.insertLast(rt); //访问根结点
inOrderRecursion(rt.getRChild(),list); //遍历右子树
}
//8.3中序遍历的非递归算法
private void inOrderTraverse(BinTreeNode rt, LinkedList list){
if (rt==null) return;
BinTreeNode p = rt;
Stack s = new StackSLinked();
while (p!=null||!s.isEmpty()){
while (p!=null){ //一直向左走
s.push(p); //将根结点入栈
p = p.getLChild();
}
if (!s.isEmpty()){
p = (BinTreeNode)s.pop();//取出栈顶根结点访问之
list.insertLast(p);
p = p.getRChild(); //转向根的右子树进行遍历
}//if
}//out while
}
//9.1后序遍历二叉树
public Iterator postOrder(){
LinkedList list = new LinkedListDLNode();
postOrderRecursion(this.root,list);
return list.elements();
}
//9.2后序遍历的递归算法
private void postOrderRecursion(BinTreeNode rt, LinkedList list){
if (rt==null) return; //递归基,空树直接返回
postOrderRecursion(rt.getLChild(),list);//遍历左子树
postOrderRecursion(rt.getRChild(),list);//遍历右子树
list.insertLast(rt); //访问根结点
}
//9.3后序遍历的非递归算法
private void postOrderTraverse(BinTreeNode rt, LinkedList list){
if (rt==null) return;
BinTreeNode p = rt;
Stack s = new StackSLinked();
while(p!=null||!s.isEmpty()){
while (p!=null){ //先左后右不断深入
s.push(p); //将根节点入栈
if (p.hasLChild()) p = p.getLChild();
else p = p.getRChild();
}
if (!s.isEmpty()){
p = (BinTreeNode)s.pop(); //取出栈顶根结点访问之
list.insertLast(p);
}
//满足条件时,说明栈顶根节点右子树已访问,应出栈访问之
while (!s.isEmpty()&&((BinTreeNode)s.peek()).getRChild()==p){
p = (BinTreeNode)s.pop();
list.insertLast(p);
}
//转向栈顶根结点的右子树继续后序遍历
if (!s.isEmpty()) p = ((BinTreeNode)s.peek()).getRChild();
else p = null;
}
}
//10.按层遍历二叉树
public Iterator levelOrder(){
LinkedList list = new LinkedListDLNode();
levelOrderTraverse(this.root,list);
return list.elements();
}
//11.使用对列完成二叉树的按层遍历
private void levelOrderTraverse(BinTreeNode rt, LinkedList list){
if (rt==null) return;
Queue q = new QueueArray();
q.enqueue(rt); //根结点入队
while (!q.isEmpty()){
BinTreeNode p = (BinTreeNode)q.dequeue(); //取出队首结点p并访问
list.insertLast(p);
if (p.hasLChild()) q.enqueue(p.getLChild());//将p的非空左右孩子依次入队
if (p.hasRChild()) q.enqueue(p.getRChild());
}
}
}
*******************************************************
/*file name:BSTree.java
*二叉查找平衡树实现
*
**/
package dsa.datastruct;
import dsa.datastruct.BinaryTreeLinked;
import dsa.datastruct.SearchTable;
import dsa.datastruct.Strategy;
import dsa.datastruct.DefaultStrategy;
public class BSTree extends BinaryTreeLinked implements SearchTable {
protected BinTreeNode startBN; //在AVL树中重新平衡的起始结点
//0.构造方法2个
public BSTree() { this(new DefaultStrategy());}
public BSTree(Strategy strategy){
this.root = null;
this.strategy = strategy;
startBN = null;
}
//1.查询查找表当前的规模
public int getSize(){return root==null?0:root.getSize();}
//2.判断查找表是否为空
public boolean isEmpty(){ return getSize()==0; }
//3返回查找表中与元素ele关键字相同的元素位置;否则,返回null
public Node search(Object ele){ return binTSearch(root, ele);}
//3.1
private Node binTSearchRe(BinTreeNode rt, Object ele){
if (rt==null) return null;
switch(strategy.compare(ele,rt.getData()))
{
case 0: return rt; //等于
case -1: return binTSearchRe(rt.getLChild(),ele);//小于
default: return binTSearchRe(rt.getRChild(),ele);//大于
}
}
//3.2
private Node binTSearch(BinTreeNode rt, Object ele){
while(rt!=null){
switch(strategy.compare(ele,rt.getData()))
{
case 0: return rt; //等于
case -1: rt = rt.getLChild(); break;//小于
default: rt = rt.getRChild(); //大于
}
}
return null;
}
//4返回所有关键字与元素ele相同的元素位置
public Iterator searchAll(Object ele){
LinkedList list = new LinkedListDLNode();
binTSearchAll(root, ele, list);
return list.elements();
}
//5.
public void binTSearchAll(BinTreeNode rt, Object ele, LinkedList list){
if (rt==null) return;
int comp = strategy.compare(ele,rt.getData());
if (comp<=0) binTSearchAll(rt.getLChild(),ele,list);
if (comp==0) list.insertLast(rt);
if (comp>=0) binTSearchAll(rt.getRChild(),ele,list);
}
//6.按关键字插入元素ele
public void insert(Object ele){
BinTreeNode p = null;
BinTreeNode current = root;
while (current!=null){ //找到待插入位置
p = current;
if (strategy.compare(ele,current.getData())<0)
current = current.getLChild();
else
current = current.getRChild();
}
startBN = p; //待平衡出发点
if (p==null)
root = new BinTreeNode(ele); //树为空
else if (strategy.compare(ele,p.getData())<0)
p.setLChild(new BinTreeNode(ele));
else
p.setRChild(new BinTreeNode(ele));
}
//7.若查找表中存在与元素ele关键字相同元素,则删除一个并返回;否则,返回null
public Object remove(Object ele){
BinTreeNode v = (BinTreeNode)binTSearch(root,ele);
if (v==null) return null; //查找失败
BinTreeNode del = null; //待删结点
BinTreeNode subT = null; //del的子树
if (!v.hasLChild()||!v.hasRChild()) //确定待删结点
del = v;
else{
del = getPredecessor(v);
Object old = v.getData();
v.setData(del.getData());
del.setData(old);
}
startBN = del.getParent(); //待平衡出发点
//此时待删结点只有左子树或右子树
if (del.hasLChild())
subT = del.getLChild();
else
subT = del.getRChild();
if (del==root) { //若待删结点为根
if (subT!=null) subT.sever();
root = subT;
} else
if (subT!=null){
//del为非叶子结点
if (del.isLChild()) del.getParent().setLChild(subT);
else del.getParent().setRChild(subT);
}
else//del为叶子结点
del.sever();
return del.getData();
}
//8.返回以v为根的二叉查找树中最小(大)元素的位置
public Node min(BinTreeNode v){
if (v!=null)
while (v.hasLChild()) v = v.getLChild();
return v;
}
public Node max(BinTreeNode v){
if (v!=null)
while (v.hasRChild()) v = v.getRChild();
return v;
}
//8.1返回结点v在中序遍历序列中的前驱结点
private BinTreeNode getPredecessor(BinTreeNode v){
if (v==null) return null;
if (v.hasLChild()) return (BinTreeNode)max(v.getLChild());
while (v.isLChild()) v = v.getParent();
return v.getParent();
}
//8.2返回结点v在中序遍历序列中的后续结点
private BinTreeNode getSuccessor (BinTreeNode v){
if (v==null) return null;
if (v.hasRChild()) return (BinTreeNode)min(v.getRChild());
while (v.isRChild()) v = v.getParent();
return v.getParent();
}
}
*******************************************************
/*file name AVLTree.java
*平衡的二叉查找树类实现
**/
package dsa.datastruct;
import dsa.datastruct.BSTree;
import dsa.datastruct.Strategy;
import dsa.datastruct.DefaultStrategy;
public class AVLTree extends BSTree {
//1.构造器
public AVLTree() { super();}
public AVLTree(Strategy strategy) { super(strategy); }
//2.插入元素ele
public void insert(Object ele){
super.insert(ele);
root = reBalance(startBN);
}
//3.删除元素
//则删除一个并返回;否则,返回null
public Object remove(Object ele){
Object obj = super.remove(ele);
root = reBalance(startBN);
return obj;
}
//私有方法
private boolean isBalance(BinTreeNode v){
if (v==null) return true;
int lH = (v.hasLChild()) ? v.getLChild().getHeight():-1;
int rH = (v.hasRChild()) ? v.getRChild().getHeight():-1;
return (Math.abs(lH - rH)<=1);
}
//私有方法
private BinTreeNode higherSubT(BinTreeNode v){
if (v==null) return null;
int lH = (v.hasLChild()) ? v.getLChild().getHeight():-1;
int rH = (v.hasRChild()) ? v.getRChild().getHeight():-1;
if (lH>rH) return v.getLChild();
if (lH<rH) return v.getRChild();
if (v.isLChild()) return v.getLChild();
else return v.getRChild();
}
//私有方法
private BinTreeNode rotate(BinTreeNode z){
BinTreeNode y = higherSubT(z); //取y为z更高的孩子
BinTreeNode x = higherSubT(y); //取x为y更高的孩子
boolean isLeft = z.isLChild(); //记录:z是否左孩子
BinTreeNode p = z.getParent(); //p为z的父亲
BinTreeNode a, b, c; //自左向右,三个节点
BinTreeNode t0, t1, t2, t3; //自左向右,四棵子树
// 以下分四种情况
if (y.isLChild()) { //若y是左孩子,则
c = z; t3 = z.getRChild();
if (x.isLChild()) { //若x是左孩子(左左失衡)
b = y; t2 = y.getRChild();
a = x; t1 = x.getRChild(); t0 = x.getLChild();
} else { //若x是右孩子(左右失衡)
a = y; t0 = y.getLChild();
b = x; t1 = x.getLChild(); t2 = x.getRChild();
}
} else { //若y是右孩子,则
a = z; t0 = z.getLChild();
if (x.isRChild()) { //若x是右孩子(右右失衡)
b = y; t1 = y.getLChild();
c = x; t2 = x.getLChild(); t3 = x.getRChild();
} else { //若x是左孩子(右左失衡)
c = y; t3 = y.getRChild();
b = x; t1 = x.getLChild(); t2 = x.getRChild();
}
}
//摘下三个节点
z.sever();
y.sever();
x.sever();
//摘下四棵子树
if (t0!=null) t0.sever();
if (t1!=null) t1.sever();
if (t2!=null) t2.sever();
if (t3!=null) t3.sever();
//重新链接
a.setLChild(t0); a.setRChild(t1);
c.setLChild(t2); c.setRChild(t3);
b.setLChild(a); b.setRChild(c);
//子树重新接入原树
if (p!=null)
if (isLeft) p.setLChild(b);
else p.setRChild(b);
return b;//返回新的子树根
}
//私有方法
private BinTreeNode reBalance(BinTreeNode v){
if (v==null) return root;
BinTreeNode c = v;
while (v!=null) { //从v开始,向上逐一检查z的祖先
if (!isBalance(v))
v = rotate(v); //若v失衡,则旋转使之重新平衡
c = v;
v = v.getParent(); //继续检查其父亲
}//while
return c;
}
}
*******************************************************
//BTeeDemo.java
//complied ok with Eclipse 3.40
//测试二叉平衡树,查找树功能
package dsa.test;
import dsa.datastruct.AVLTree;
import dsa.datastruct.BSTree;
public class BTreeDemo {
public static void main(String[] args) {
System.out.println("二叉平衡树...");
BSTree bt=new BSTree();//1.二叉查找树BSTree
bt.insert(11);
bt.insert(66);
bt.insert(33);
bt.insert(99);
bt.insert(44);
bt.insert(55);
bt.remove(11);
System.out.println("bt.isEmpty()="+bt.isEmpty());
System.out.println("bt.getSize()="+bt.getSize());
System.out.println("bt.getHeight()="+bt.getHeight());
System.out.println("bt.search(55)="+bt.search(55).getData());
System.out.println("bt.getRoot()="+bt.getRoot().getData());
System.out.println("二叉平衡树...");
AVLTree avl=new AVLTree();//2.二叉平衡树AVL
avl.insert(33);
avl.insert(44);
avl.insert(55);
avl.insert(77);
avl.insert(99);
avl.insert(88);
System.out.println("avl.getHeight()="+avl.getHeight());
System.out.println("avl.getSize()="+avl.getSize());
}
}
运行结果:
二叉平衡树...
bt.isEmpty()=false
bt.getSize()=5
bt.getHeight()=3
bt.search(55)=55
bt.getRoot()=66
二叉平衡树...
avl.getHeight()=2
avl.getSize()=6
通过例子证明二叉平衡树比二叉查找树生成的高度更小,操作效率更高
*******************************************************