二叉树的遍历

二叉树的遍历应该说是非常常见的,用递归的话程序非常简单明了,而有的时候需要写非递归的遍历程序,这个时候就需要对此有一定的了解。

二叉树的遍历根据根节点和左右子节点遍历顺序的不同,可以分为三种:前序遍历,中序遍历,后序遍历。前序遍历就是先根节点->左节点->右节点。非递归前序遍历编写最简单,最难的是后续遍历。下面就来一一写出它们的程序,这里用的是Java。非递归遍历是一种DFS(深度优先搜素),从根节点开始一直遍历到叶子节点,然后在从根节点往另一个路径继续遍历。这里用到的数据结构是栈。Java里面用的是Stack类,它是数组实现,也可以用链表LinkedList来做栈。其实递归遍历也用到了栈,只不过是系统栈,没有显示的输出。

Node节点的定义:

public  class Node
{
	private T element;
	private Node left;
	private Node right;
	public Node(T element,Node left,Node right)
	{
		this.element=element;
		this.left=left;
		this.right=right;
	}
}


递归二叉树遍历:

//前序遍历
public void printTree(Node node)
{
	if(node!=null)
	{
		System.out.print(node.element+" ");
		printTree(node.left);
		printTree(node.right);

	}
}
//中序遍历
public void printTree(Node node)
{
	if(node!=null)
	{
		printTree(node.left);
		System.out.print(node.element+" ");
		printTree(node.right);
	}
}
//后续遍历
public void printTree(Node node)
{
	if(node!=null)
	{
		printTree(node.left);
		printTree(node.right);
		System.out.print(node.element+" "); 
	}
}


非递归二叉树遍历:

//前序遍历 非递归实现 三种遍历中最简单的
public void preTrave(Node root)
{
	if(root==null)
		return;
	Stack st=new Stack();
	st.push(root);
	while(!st.isEmpty())
	{
		Node n=st.pop();
		System.out.print(n.element+" ");
		if(n.right!=null)	
			st.push(n.right);  //先入栈右节点,再入栈左节点
		if(n.left!=null)	
			st.push(n.left);
	}	
}

//中序遍历 非递归实现 三种遍历中的
public void midTrave(Node root)
{
	if(root==null)
		return;
	Stack st=new Stack();
	Node no=root;
	while(no!=null || !st.isEmpty())
	{
		while(no!=null)
		{
			st.push(no); //不停地插入左节点
			no=no.left;
		}
		if(!st.isEmpty())
		{
			Node n=st.pop();
			System.out.print(n.element+" ");
			no=n.right;  //获取出栈节点的右节点
		}
	}	
}

//后序遍历 非递归实现 三种遍历中是最难的,需要每个节点保存一个变量代表是否被读取过
public void postTrave(Node root)
{
	if(root==null)
		return;
	Map.Entry me;//这里用到Map内部类,类似于C++的pair函数,否则要自己重写个类
	Stack> st=new Stack>();
	Node no=root;
	while(no!=null || !st.isEmpty())
	{
		while(no!=null)
		{
			me=new AbstractMap.SimpleEntry(no,false);
			st.push(me); //不停地插入左节点
			no=no.left;
		}
		if(!st.isEmpty())
		{
			
			Map.Entry n=st.pop();
			if(n.getValue()==false)
			{
				st.push(n);
				n.setValue(true);   //代表读过该节点一次
				no=n.getKey().right;
			}
			else   //代表出栈的节点右节点已经读取
			{
				System.out.print(n.getKey().element+" ");
				no=null;  
			}
		}
	}	
}


除了上面的三种遍历,二叉树还可以分层遍历。这就是BFS(广度优先搜索),先第一层,再第二层,以此类推。BFS用到的数据结构是队列,先入先出。程序如下,它和前序遍历类似,只不过把栈改成了队列,然后左右节点进入的顺序掉了一下。

程序如下:

//按层遍历 就是将前序遍历的栈改用为队列,左右节点入队顺序改变一下
public void cengTrave(Node root)
{
	if(root==null)
		return;
	ArrayDeque st=new ArrayDeque();
	st.offer(root);
	while(!st.isEmpty())
	{
		Node n=st.pop();
		System.out.print(n.element+" ");
		if(n.left!=null)	
			st.offer(n.left);  //先左节点入队列,再右节点
		if(n.right!=null)	
			st.offer(n.right);
	}	
}




你可能感兴趣的:(数据结构,Java)