二叉树的分步遍历

这个名字起的不太能理解!

二叉树的分步遍历是指,在规定了一棵二叉树的遍历方法后,每次只访问当前结点的数据元素,然后使当前结点为当前结点的后继结点(我类个去,绕口令啊),直到达到二叉树的最后一个结点为止,就像操作单链表一样。

在看概念:二叉树遍历有两种情况,一种是一次性遍历,如之前提到的四种遍历方法一次性遍历显示二叉树结点的数据元素值;另一种是分步遍历。

大白话理解:结合上面两个,我认为是可以这样理解分步遍历,原先的四种遍历方法是给一个遍历入口,然后必须一次性递归遍历(层序除外)到结束,否则中断的话就不知道遍历到哪一个结点了。而分步遍历其实就是设置一个当前结点指针,即便中断,也可以根据指针继续后面的遍历,其实就是转换成了一种非递归加指针的遍历。

那么,能实现分步的方法其一就有通过游标类实现,建立一个游标类给出分步的总路线,然后各个遍历方法通过继承完成自己的分步遍历。

二叉树游标类设计如下:

package Tree;
/**
* @author sun
* 创建时间:2017年4月27日上午9:48:37
*/
/*二叉树游标类
 * 不同的遍历,reset和next函数实现方法不同,故设置为空函数
 * 由其子类覆盖实现
*/
public class BiTreeInterator {
	BiTreeNode root;//根指针
	BiTreeNode current;//当前结点
	int iteComplete;//到达尾部标记
	
	BiTreeInterator(){}//构造函数
	
	BiTreeInterator(BiTreeNode tree){
		root = tree;
		current = tree;
		iteComplete = 1;
	}
	
	public void reset(){}//重置,子类实现
	
	public void next(){}//下一个结点,子类实现
	
	public boolean endOfBiTree(){
		return iteComplete == 1;
	}
	
	public Object getData(){
		if(current == null)
			return null;
		else
			return current.data;
	}
}

以中序遍历举例,其非递归的算法如下(为了和游标类设计一致,有意把部分地方重复):

(1)设置一个堆栈并初始化;

(2)使结点对象引用t等于二叉树根指针,如t非空令结束标记为0,否则为1;

(3)当t的左孩子结点不空时循环,否则转向步骤4;

a、把t入栈;

b、t等于t的左孩子结点;

(4)如果t为空则令结束标记为1;

(5)如果结束标记为1转向步骤8,否则继续;

(6)访问t结点;

(7)如果t的右孩子结点非空,则使t等于t的右孩子结点,转向步骤3,;否则如果堆栈不空,则退栈使t等于栈顶结点,转向步骤5;否则令结束标记为1,转向步骤5。

(8)算法结束。

上面的算法可以举个例子帮忙理解,reset函数实现了步骤1至4,next函数实现了步骤7。二叉树中序游标类如下:

package Tree;
import StackAndQueue.LinStack;
/**
* @author sun
* 创建时间:2017年4月27日上午9:59:41
*/
//二叉树中序游标类
public class BiTrInIterator extends BiTreeInterator {
	private LinStack s = new LinStack();//创建堆栈类对象
	BiTrInIterator(BiTreeNode t){
		super(t);//调用父类的构造函数
	}
	
	private BiTreeNode goFarLeft(BiTreeNode t){//寻找最左孩子结点
		if(t == null) return null;
		while(t.getLeft()!=null){
			s.push(t);
			t = t.getLeft();
		}
		return t;
	}
	
	public void reset(){
		if(root==null) iteComplete = 1;
		else iteComplete = 0;
		if(root==null) return;
		current = goFarLeft(root);
	}
	
	public void next(){
		if(iteComplete==1){
			System.out.println("已到二叉树尾!");
			return;
		}
		if(current.getRight()!=null){
			current = goFarLeft(current.getRight());
			//寻找当前结点右孩子结点的最左结点
		}
		else if(s.notEmpty()){
			try{
				current = (BiTreeNode)s.pop();
			}
			catch(Exception e){
				e.printStackTrace();
			}
		}
		else
			iteComplete = 1;
	}
}

主函数测试:

package Tree;
/**
* @author sun
* 创建时间:2017年4月27日上午10:30:52
*/
public class TestBiTrInIterator {
	public static BiTreeNode getTreeNode(Object item,BiTreeNode left,BiTreeNode right){
		BiTreeNode temp = new BiTreeNode(item,left,right);
		return temp;
	}
	
	public static BiTreeNode makeTree(){
	//构造一个不带头结点的二叉链存储结构的二叉树
		BiTreeNode b,c,d,e,f,g;
		g = getTreeNode(new Character('G'),null,null);
		d = getTreeNode(new Character('D'),null,g);
		b = getTreeNode(new Character('B'),d,null);
		e = getTreeNode(new Character('E'),null,null);
		f = getTreeNode(new Character('F'),null,null);
		c = getTreeNode(new Character('C'),e,f);
		return getTreeNode(new Character('A'),b,c);
	}
	
	public static void main(String[] args) {
		BiTreeNode root;
		root = makeTree();
		BiTrInIterator myIter = new BiTrInIterator(root);
		System.out.print("中序遍历序列为:");
		for(myIter.reset();!myIter.endOfBiTree();myIter.next())
			System.out.print(myIter.getData()+" ");
	}
}
//中序遍历序列为:D G B A E C F 
二叉树层序游标类如下(不做详细说明):

package Tree;
import StackAndQueue.LinQueue;
/**
* @author sun
* 创建时间:2017年4月27日上午10:38:02
*/
//二叉树层序游标类
public class BiTrLeIterator extends BiTreeInterator{
	private LinQueue q = new LinQueue();
	BiTrLeIterator(BiTreeNode t){
		super(t);//调用父类的构造函数
	}
	
	public void reset(){
		if(root==null) iteComplete = 1;
		else iteComplete = 0;
		if(root==null) return;
		current = root;
		try{
			if(root.getLeft()!=null)
				q.append(root.getLeft());//左孩子入队列
			if(root.getRight()!=null)
				q.append(root.getRight());//右孩子入队列
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public void next(){
		if(iteComplete==1){
			System.out.println("已到二叉树尾!");
			return;
		}
		if(q.notEmpty()){
			try{
				current = (BiTreeNode)q.delete();
				if(current.getLeft()!=null)
					q.append(current.getLeft());
				if(current.getRight()!=null)
					q.append(current.getRight());
			}
			catch(Exception e){
				e.printStackTrace();
			}
		}
		else
			iteComplete = 1;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值