数据结构(java语言描述)树(二叉树)的构建和遍历操作
二叉树:度为二的,分左右孩子的树。
树结点的结构:
package tree;
public class BitreeNode {
private Object data;//树结点的数据
private BitreeNode lchild,rchild;//树结点的左右孩子结点
public BitreeNode(){//无参构造函数
this(null);
}
//构造一颗左孩子和右孩子都为空的二叉树结点
public BitreeNode(Object data){
this.data=data;
this.lchild=null;
this.rchild=null;
}
//构造一颗数据域和左孩子和右孩子都不为空的二叉树结点
public BitreeNode(Object data,BitreeNode lchild,BitreeNode rchild){
this.data=data;
this.lchild=lchild;
this.rchild=rchild;
}
//三个数据结点的设置
public Object getData(){
return data;
}
public BitreeNode getlchild(){
return lchild;
}
public BitreeNode getrchild(){
return rchild;
}
public void setData(Object data){
this.data=data;
}
public void setlchild(BitreeNode lchild){
this.lchild=lchild;
}
public void setrchild(BitreeNode rchild){
this.rchild=rchild;
}
}
树的递归和非递归的遍历操作:
原理理解:
package tree;
import queue.Linkqueue;
import stack.Linkstack;
public class Bitree {
private BitreeNode root;
//构造一颗空树
public Bitree(){
this.root=null;
}
//构造一棵树
public Bitree(BitreeNode root){
this.root=root;
}
public BitreeNode getRoot(){
return root;
}
public void setRoot(BitreeNode root){
this.root=root;
}
//由先根遍历和中根遍历的顺序建立一颗二叉树的算法
public Bitree(String preOrder,String inOrder,int preindex,int inIndex,int count){
}
//
//二叉树的遍历算法,递归
/************DLR/LDR/LRD*******************/
/************特点:结构简单,但时空开销相对较大,从而导致运行效率较低,并且有些程序设计环境不支持递归*******************/
public void prerootTraverse(BitreeNode t){
if(t!=null){
System.out.print(t.getData());//先根遍历。先访问根节点的数据域
prerootTraverse(t.getlchild());//其次递归遍历左子树
prerootTraverse(t.getrchild());//最后遍历右子树
}
}
public void InrootTraverse(BitreeNode t){
if(t!=null){
InrootTraverse(t.getlchild());//中根遍历。先递归遍历左子树
System.out.print(t.getData());//其次访问根节点的数据域
InrootTraverse(t.getrchild());//最后遍历右子树
}
}
public void PostrootTraverse(BitreeNode t){
if(t!=null){
InrootTraverse(t.getlchild());//后根遍历。先递归遍历左子树
InrootTraverse(t.getrchild());//其次遍历右子树
System.out.print(t.getData());//最后访问根节点的数据域
}
}
//二叉树的遍历算法,非递归
/************DLR/LDR/LRD
* @throws Exception *******************/
//先根遍历借助一个栈来存储右孩子结点
/************原理:树的根节点入栈,出栈,访问树的根节点,然后访问根节点的左孩子结点,右孩子入栈,
* 递归遍历左子树**************/
public void preroottraverse() throws Exception{
BitreeNode t=root;
if(t!=null){
Linkstack s=new Linkstack();//如果树非空,先创建栈,然后根入栈
s.push(t);
while(!s.isEmpty()){//当栈顶元素为非空时,将栈顶元素弹出并访问该结点
t=(BitreeNode)s.pop();//移除栈顶元素并返回其值
System.out.print(t.getData());
while(t!=null){
if(t.getlchild()!=null)
System.out.print(t.getlchild().getData());//访问左子树的根节点
if(t.getrchild()!=null)//右子树根节点入栈
s.push(t.getrchild());
t=t.getlchild();//遍历左子树
}//while t!=null
}//while !s.isEmpty
}//t!=null
}
//中根遍历借助一个栈来存储根结点和所有的n-1层次的左孩子结点
/************原理:树的根节点入栈,然后左孩子结点依次入栈,出栈访问,右孩子入栈,。。。
* **************/
public void inroottraverse()throws Exception{
BitreeNode t=root;
if(t!=null){//树非空,则创建栈表,并将树的根节点入栈
Linkstack s=new Linkstack();
s.push(t);
while(!s.isEmpty()){//若栈非空
while(s.peek()!=null){//判断栈顶元素不为空
s.push(((BitreeNode) s.peek()).getlchild());//栈顶元素的左孩子结点入栈
}
s.pop();//非空结点退栈 ??????
if(!s.isEmpty()){
t=(BitreeNode)s.pop();
System.out.print(t.getData());
s.push(t.getrchild());
}
}
}
}
//先根遍历借助一个栈来依次存储左孩子结点,及右孩子
/************原理:树的根节点入栈,根节点的左孩子结点依次入栈。若最左下角的结点右孩子为空或已经访问则访问该结点,flag
* 标记为true,否则右孩子入栈flag标记为false,**************/
public void postroottraverse()throws Exception{
BitreeNode t=root;
if(t!=null){
Linkstack s=new Linkstack();//树非空则创建栈链
s.push(t);//根节点入栈
Boolean flag;
BitreeNode p=null;//p指向刚刚被访问的结点
while(!s.isEmpty()){
while(s.peek()!=null){
s.push(((BitreeNode)s.peek()).getlchild());//左孩子入栈
}
s.pop();//空结点出栈
while(!s.isEmpty()){
t=(BitreeNode)s.peek();
if(t.getlchild()==null||t.getrchild()==p){
System.out.print(t.getData());
s.pop();
p=t;
flag=true;
}else{
s.push(t.getrchild());
flag=false;
}
if(!flag)
break;
}
}
}
}
//层次遍历,借助的是队列,依次根节点入队,当队列不为空时,队首出队,然后出队结点的左孩子和右孩子依次入队。
//即一个出队,则左右孩子入队。。。
public void leveltranverse()throws Exception{
BitreeNode t=root;
if(t!=null){
Linkqueue q=new Linkqueue();//若树非空,建立队列,并将树的根节点先入队
q.offer(t);
while(!q.isEmpty()){//若队列非空,输出队首元素,并判断该结点的左右孩子结点,分别入队
t=(BitreeNode)q.poll();
System.out.print(t.getData());//每次访问的都是队首元素
if(t.getlchild()!=null){
q.offer(t.getlchild());
}
if(t.getrchild()!=null)
q.offer(t.getrchild());
}
}
}
}
3.树的创建和遍历
package tree;
public class tree {
public Bitree createBitree(){
BitreeNode d=new BitreeNode('D');
BitreeNode g=new BitreeNode('g');
BitreeNode h=new BitreeNode('h');
BitreeNode e=new BitreeNode('e',g,null);
BitreeNode b=new BitreeNode('b',d,e);
BitreeNode f=new BitreeNode('f',null,h);
BitreeNode c=new BitreeNode('c',f,null);
BitreeNode a=new BitreeNode('a',b,c);
return new Bitree(a);
}
public static void main(String[] args) throws Exception{
tree tree1=new tree();
Bitree bitree=tree1.createBitree();
BitreeNode root=bitree.getRoot();
System.out.println("(递归)先根遍历序列:");
bitree.prerootTraverse(root);
System.out.println();
System.out.println("(非递归)先根遍历序列:");
bitree.preroottraverse();
System.out.println();
System.out.println("(递归)中根遍历序列:");
bitree.InrootTraverse(root);
System.out.println();
System.out.println("(非递归)中根遍历序列:");
bitree.inroottraverse();
System.out.println();
System.out.println("(递归)后根遍历序列:");
bitree.PostrootTraverse(root);
System.out.println();
System.out.println("(非递归)后根遍历序列:");
// bitree.postroottraverse();
System.out.println();
System.out.println("层次遍历序列:");
bitree.leveltranverse();
System.out.println();
}
}
结果:
(递归)先根遍历序列:
abDegcfh
(非递归)先根遍历序列:
abDegcfh
(递归)中根遍历序列:
Dbgeafhc
(非递归)中根遍历序列:
Dbgeafhc
(递归)后根遍历序列:
Dbgefhca
(非递归)后根遍历序列:
层次遍历序列:
abcDefgh