学习日志---非递归二叉树游标遍历(前中后层序)

实现:

//二叉树类
public class MyBiTree {

	private MyBiTreeNode  root;//根节点

	MyBiTree()
	{
		this.root = null;
	}

	MyBiTree(Object data,MyBiTree left,MyBiTree right)
	{
		MyBiTreeNode l,r;
		if(left==null)
		{
			l = null;
		}
		else
		{
		   l=left.root; 
		}

		if(right==null)
		{
			r = null;
		}
		else
		{
			r = right.root;
		}

		this.root = new MyBiTreeNode(data,l,r);
	}

	//打印二叉树
	public static void printBiTree(MyBiTreeNode root,int level)
	{
		if(root!=null)
		{
			printBiTree(root.getRightChild(),level+1);

			if(level!=0)
			{
				//输出6*(level-1)个空格
				for(int i=0;i<6*(level-1);i++)
				{
					System.out.print(" ");
				}
				System.out.print("-----");
			}
			System.out.println(root.getData());

		    printBiTree(root.getLeftChild(),level+1);
		}
	}

	//获得二叉树的结点
	public static MyBiTreeNode getTreeNode(Object data,MyBiTreeNode left,MyBiTreeNode right)
	{
		MyBiTreeNode node = new MyBiTreeNode(data,left,right);
		return node;
	}

	//查找指定元素
	public static MyBiTreeNode search(MyBiTreeNode root,Object obj)
	{
		MyBiTreeNode node=null;
		if(root==null)
		{
			return null;
		}
		if(root.getData().equals(obj))
		{
			return root;
		}
		if(root.getLeftChild()!=null)
		{
			node = search(root.getLeftChild(),obj);
		}
		if(root.getRightChild()!=null)
		{
			node = search(root.getRightChild(),obj);
		}

		return node;
	}
}

二叉树节点类

//二叉树结点类
public class MyBiTreeNode {

	private MyBiTreeNode leftChild; // 左孩子
	private MyBiTreeNode rightChild; // 右孩子
	private Object data; // 数据元素

	MyBiTreeNode() {
		this.leftChild = null;
		this.rightChild = null;
	}
    
	MyBiTreeNode(Object data,MyBiTreeNode leftNode,MyBiTreeNode rightNode)
	{
		this.data = data;
		this.leftChild = leftNode;
		this.rightChild = rightNode;
	}

	public MyBiTreeNode getLeftChild() {
		return leftChild;
	}

	public void setLeftChild(MyBiTreeNode leftChild) {
		this.leftChild = leftChild;
	}

	public MyBiTreeNode getRightChild() {
		return rightChild;
	}

	public void setRightChild(MyBiTreeNode rightChild) {
		this.rightChild = rightChild;
	}

	public Object getData() {
		return data;
	}

	public void setData(Object data) {
		this.data = data;
	}
}

游标遍历类:

reset方法是初始化;

如果栈中无元素了,isComplete则为false,结束标志。

其中的next方法是指:取得待打印的下一个节点,用next方法取得的节点就是要处理的节点。

public class MyBiTreeIterator {
   
	MyBiTreeNode root; //根节点
	MyBiTreeNode curr;// 当前结点;
	boolean isComplete;  //判断是否遍历结束

	MyBiTreeIterator()
	{

	}
	、
	MyBiTreeIterator(MyBiTreeNode root)
	{
		this.root = root;
	}

	public void reset()
	{

	}

	public void next()
	{
	  
	}

	public boolean endOfBiTree()
	{
	  return isComplete;
	}

	public Object getData()
	{
		return this.curr.getData();
	}
}

前序遍历:

//二叉树游标前序遍历类
public class MyBiTreePreIterator extends MyBiTreeIterator{
   
	Stack<MyBiTreeNode> stack = new Stack<MyBiTreeNode>();
     

	MyBiTreePreIterator()
	{

	}
	MyBiTreePreIterator(MyBiTreeNode root)
	{
	   super(root);
	}

	@Override
	public void next() {
		// TODO Auto-generated method stub
		if(this.isComplete)
		{
			System.out.println("已经遍历到二叉树结尾!");
			return ;
		}
		if(this.curr.getRightChild()!=null)
		{
			stack.push(this.curr.getRightChild());
		}
		if(this.curr.getLeftChild()!=null)
		{
			stack.push(this.curr.getLeftChild());
		}

		if(!stack.empty())
		{
			this.curr = stack.pop();
		}
		else
		{
			this.isComplete = true;
		}
	}

	@Override
	public void reset() {
		// TODO Auto-generated method stub
		if(this.root==null)
		{
			this.isComplete = true;
		}
		else
		{
			this.isComplete = false;
		}
		if(this.root==null)
		{
			return ;
		}
		this.curr = this.root;
	}
}

中序遍历:

getFarLeft是找出最左侧节点,用于打印。

next方法是找到下一个需要处理的节点。

相比较上面的前序遍历,这里是左根右的方法,因此要处理每一个节点是,在过程中,把路过的节点入栈,用getFarLeft方法把最左侧的节点找出,并赋值给current节点。打印这个节点的data后,用next的方法再去找下一个,会先判断是否有右侧节点,如果有,则会在用getFarLeft方法找这个节点最左侧的节点,如果没有则用栈里的元素向上找。

////二叉树游标中序遍历类
public class MyBiTreeInIterator extends MyBiTreeIterator {
  
	Stack<MyBiTreeNode> stack = new Stack<MyBiTreeNode>();
    
	MyBiTreeInIterator()
	{

	}
	MyBiTreeInIterator(MyBiTreeNode root)
	{
		super(root);
	}
    
	//得到最左边的结点
	public MyBiTreeNode getFarLeft(MyBiTreeNode node)
	{
	   if(node==null)
	   {
		   return null;
	   }
	   while(node.getLeftChild()!=null)
	   {
		  stack.push(node);
		  node = node.getLeftChild(); 
	   }
	   return node;
	}

	@Override
	public void next() {
		// TODO Auto-generated method stub
		if(this.isComplete)
		{
			System.out.println("已经遍历到二叉树结尾!");
			return ;
		}

		//这里如果执行了next,说明已经打印了这个节点,下一步要看右侧节点是否有子节点。
		if(this.curr.getRightChild()!=null)
		{
			//在右孩子当中找最左边的。
			this.curr = getFarLeft(this.curr.getRightChild());
		}
		else if(!stack.isEmpty())
		{
			this.curr = stack.pop();
		}
		else
		{
			this.isComplete = true;
		}
	}

	@Override
	//这里进行初始化时,就要用getFarLeft找到最右侧的点进行打印。
	public void reset() {
		// TODO Auto-generated method stub
		if(this.root==null)
		{
			this.isComplete = true;
		}
		else
		{
			this.isComplete = false;
		}
		if(this.root==null)
		{
			return ;
		}
		this.curr = getFarLeft(this.root);
	}
}

中序遍历(2)

 public static void inTraverse(BinaryTree root) {
  Stack s = new Stack();
  BinaryTree p = root;
  while(p!=null || !s.isEmpty()) {
   if(p!=null) {
   //这里只管push元素,然后找左侧元素
    s.push(p);
    p = p.lchild;
   }
   else {
   //如果p为空的话,则说明左侧没有元素,把p这个点的元素打印出,再找右侧元素
    p = (BinaryTree)s.pop();
    visit(p);
    p = p.rchild;
   }
  }
 }

后序遍历:

双堆栈方法!把所有的元素顺序全都放入temp栈中。stack栈就是一个中间栈。

///二叉树游标后序遍历类
public class MyBiTreePostIterator extends MyBiTreeIterator{
  
	Stack<MyBiTreeNode> stack = new Stack<MyBiTreeNode>();
	Stack<MyBiTreeNode> temp = new Stack<MyBiTreeNode>();

	MyBiTreePostIterator()
	{

	}
	MyBiTreePostIterator(MyBiTreeNode root)
	{
	   super(root);
	}

	@Override
	public void next() {
		// TODO Auto-generated method stub
		if(this.isComplete)
		{
			System.out.println("已经遍历到二叉树结尾!");
			return ;
		}
		if(!temp.isEmpty())
		{
			this.curr = temp.pop();
		}
		else
		{
			this.isComplete = true;
		}
	}
	@Override
	public void reset() {
		// TODO Auto-generated method stub
		if (this.root == null) {
			this.isComplete = true;
		} else {
			this.isComplete = false;

		}
		if (this.root == null) {
			return;
		}
		this.curr = root;

		while (this.curr != null || stack.size() > 0)
		{    
                    while (this.curr != null) {    
                        temp.push(this.curr);
                        //System.out.println(this.curr.getData());
                        stack.push(this.curr);    
                        curr = this.curr.getRightChild();    
                    }    
                    if (stack.size() > 0) {    
                        this.curr = stack.pop();    
                        this.curr = this.curr.getLeftChild();    
                    }    
                }   
		this.curr = temp.pop();
	}
}

层序遍历

这里使用的是队列;

//二叉树游标层次遍历类
public class MyBiTreeLevIterator extends MyBiTreeIterator {
   
	Queue<MyBiTreeNode> queue = new LinkedList<MyBiTreeNode>();

	MyBiTreeLevIterator()
	{

	}

	MyBiTreeLevIterator(MyBiTreeNode root)
	{
	  super(root);
	}

	@Override
	public void next() {
		// TODO Auto-generated method stub
		if(this.isComplete)
		{
			System.out.println("已经遍历到二叉树结尾!");
			return ;
		}
		if(!queue.isEmpty())
		{
			this.curr = queue.remove();
			if(this.curr.getLeftChild()!=null)
			{
				queue.add(this.curr.getLeftChild());
			}
			if(this.curr.getRightChild()!=null)
			{
				queue.add(this.curr.getRightChild());
			}
		}
		else
		{
			this.isComplete = true;
		}
	}

	@Override
	public void reset() {
		// TODO Auto-generated method stub
		if (this.root == null) {
			this.isComplete = true;
		} else {
			this.isComplete = false;

		}
		if (this.root == null) {
			return;
		}
		this.curr = root;
		if(this.curr.getLeftChild()!=null)
		{
			queue.add(this.curr.getLeftChild());
		}
		if(this.curr.getRightChild()!=null)
		{
			queue.add(this.curr.getRightChild());
		}
	}

}

后序遍历的牛逼方法:

在遍历的同时通过flag来判断是否需要打印,如不是flag,则就需找到该节点两侧的子节点。

public static void main(String[] args) {
		//这个是创建一个树
		BiTreeNode root = Test.makeTree();

		final Object flag = new Object(); // 仅作为标记用的对象
		Deque<Object> stack = new LinkedList<Object>();
		stack.push(root);
		while (!stack.isEmpty()){
			if (stack.peek() == flag){ // 检查是否输出标记
				stack.pop();
				BiTreeNode node = (BiTreeNode)stack.pop();
				System.out.print(node.getData());
			}else{
			         // 注意这里把节点留在栈里了
				BiTreeNode node = (BiTreeNode)stack.peek();
				stack.push(flag); // 嵌入输出标记,以示输出栈顶节点
				if (node.getRightChild() != null) 
					stack.push(node.getRightChild());
				if (node.getLeftChild() != null) 
					stack.push(node.getLeftChild());
			}
		}
		System.out.println();
	}

}
时间: 2024-10-29 13:28:20

学习日志---非递归二叉树游标遍历(前中后层序)的相关文章

非递归二叉树的遍历

我们都知道,对二叉树进行递归遍历非常简单,但递归算法需要额外的栈机制来存储每次递归的值.既然递归算法内部使用栈实现的,那么我们也可以借助于栈来实现二叉树的非递归遍历.下面我们将讲解利用非递归实现二叉树的前序.中序和后序遍历. 1.非递归二叉树前序遍历: 我们知道,二叉树的前序遍历对节点的访问顺序是根节点.左子节点然后右自节点.根据其访问顺序我们可以很容易用栈来实现.具体实现思路如下: 1.遍历根节点的左子树,将每个节点的左子节点存入栈中,并在访问遍历的节点. 2.当遇到左子节点为空时,从栈中取出

非递归前中后序遍历二叉树

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 写在前面: 最近准备找工作,捡起原来学习过的各种知识,加上一些自己的理解,梳理一下流程,巩固自己的认识,一步两步,一步两步... ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 二叉树的遍历是树操作的基础,一般的前中后序递归遍历比较简单,这里就不列出了,主要是非递归实

【算法导论】二叉树的前中后序非递归遍历实现

二叉树的递归遍历实现起来比较简单,而且代码简洁:而非递归遍历则不那么简单,我们需要利用另一种数据结构---栈来实现.二叉树的遍历又可以分为前序.中序和后序三种,它们是按照根结点在遍历时的位置划分的,前序遍历则根结点先被遍历,中序则根结点在左右叶子节点之间被遍历,后序则是根结点最后被遍历.三种非递归遍历中,前序和中序都不是太复制,而后序遍历则相对较难. 一.前序遍历 我们这里前序遍历按照"根-左-右"的顺序来遍历.这里按照"递归--非递归"的次序来研究,之后的几种亦是

非递归的方法遍历二叉树

//非递归遍历一棵树 需要借助栈 #include<stdio.h> #include<stdlib.h> struct Tree { int nValue; Tree *pLeft; Tree *pRight; }; struct Stack { Tree *root; Stack *pNext; }; Stack *pStack = NULL; void push(Tree *root) { Stack *temp = (Stack*)malloc(sizeof(Stack))

二叉树的前序建立,前中后序遍历的非递归算法

二叉树的前序建立递归算法以及前中后序遍历的递归算法已经是人尽皆知了,递归算法也确实为代码的编写带来了很大的方便.然而,有时我们也确实需要它们的非递归算法.将递归算法转化为非递归算法可以帮助我们深入了解函数的调用与栈的原理.这里总结一下二叉树的这些重要的非递归算法. 一.前序建树 前序建树的基本思路是,接收用户输入的一组字符串,其中'#'代表空树,其他代表树结点的数据域值.例如,要建立如下一棵树 需要输入"AB#D##C##". 而非递归的思路是,1.设一个标志位来判断当前创建的结点是左

每天刷个算法题20160518:非递归二叉树遍历

版权所有.所有权利保留. 欢迎转载,转载时请注明出处: http://blog.csdn.net/xiaofei_it/article/details/51502254 为了防止思维僵化,每天刷个算法题.已经刷了几天了,现在贴点代码. 2002年我初中二年级,开始学习BASIC语言.2004年中考之后,开始参加NOIP,系统学习算法.一直非常喜欢算法,但工作后几乎不再碰这些东西.现在准备重新捡起来. 我已经建了一个开源项目,每天的题目都在里面: https://github.com/Xiaofe

二叉树——前序遍历、中序遍历、后序遍历、层序遍历详解(递归非递归)

前言 前面介绍了二叉排序树的构造和基本方法的实现.但是排序遍历也是比较重要的一环.所以笔者将前中后序.和层序遍历梳理一遍. 了解树的遍历,需要具有的只是储备有队列,递归,和栈.这里笔者都有进行过详细介绍,可以关注笔者数据结构与算法专栏.持续分享,共同学习. 层序遍历 层序遍历.听名字也知道是按层遍历.我们知道一个节点有左右节点.而每一层一层的遍历都和左右节点有着很大的关系.也就是我们选用的数据结构不能一股脑的往一个方向钻,而左右应该均衡考虑.这样我们就选用队列来实现. 对于队列,现进先出.从根节

二叉树的前中后序遍历简单的递归

二叉树的遍历 无外乎广度和深度 其中深度又分为前中后序遍历三种情况  这三种遍历若只是递归方法 自然很是简单 但递归代码简单 若嵌套层次太深 会栈溢出 二叉树节点数据结构: struct Binary_node{    int val;    Binary_node *left;    Binary_node *right;    Binary_node(int v = 0, Binary_node *le = nullptr, Binary_node *ri = nullptr) :val(v

二叉树的前中后序遍历

#include<stdio.h> #include<string.h> #include<stdlib.h> #define Size 100 #define Resize 10 typedef struct Bitnode{ //定义结点 char data; struct Bitnode *lchild,*rchild; }Bitnode,*Bitree; typedef struct Stack{ //定义栈 Bitree *base; int top; int