上次分享了二叉树的数据结构,这次楠哥专门拿出一节来分析二叉树的遍历(Traverse)问题。事实上,二叉树的搜索(Search)问题和遍历问题非常相似,不同的是遍历问题会访问树的每一个节点,而搜索问题一旦找到了所需要的结点就停止操作了。搜索问题楠哥会在后续算法相关的文章当中详解,本次主要分析最常用的两种遍历方法。(楠哥计算机学习网www.liubonan.com)

深度优先遍历(Depth First)是指对于一颗树,首先访问其左节点,后访问右节点,再访问其根节点;对于节点本身是子树的情况,则按此规则继续深入,直到叶节点位置。这种方法有两种实现的思路。第一种是使用递归(Recursion)的方式,即如果该节点不是叶节点则访问其左子树、右子树,在访问节点本身;另外一种思路是递推(Iteration)的方式,这里需要定义一个栈(Stack),即LIFO队列,如果栈顶结点不是叶节点,就将其左右子树压入栈;循环的从栈顶取结点,再按此规则进行处理。栈的实现Java已经给出,当然也可以使用自定义的类型,具体方式详见《Java中栈的实现》。

广度优先遍历(Breadth First)是指对一棵树,首先访问第一层的结点,在访问第二层的结点,依次类推。这里我们需要用一个FIFO队列(Queue)来实现:将每一个结点的所有子结点加入到队列中,再从队列中选取队首元素出队,依次规则进行循环直到所有结点全部出队。队列的实现Java同样也有现成的类,如果想自定义该数据结构,可以参考《Java中队列的实现》。(楠哥计算机学习网www.liubonan.com)

下面的代码实现了两种深度优先遍历方式和一种广度优先遍历方式,因为树的具体代码已经在上次文章中给出,本文只列出遍历函数的代码。全部代码详见《Java中的二叉树》。(楠哥计算机学习网www.liubonan.com)

public void dfs_re(Node current)
	{
		if((current.getLeft() == null)&&(current.getRight() == null))
			System.out.print(current.getData() + " ");
		else
		{
			if(current.getLeft() != null)
				dfs_re(current.getLeft());

			if(current.getRight() != null)
				dfs_re(current.getRight());

			System.out.print(current.getData() + " ");
		}
	}

	public void bfs()
	{
		Queue q = new LinkedList();

		q.add(root);

		while(!q.isEmpty())
		{
			Node temp = q.remove();
			if(temp.getLeft()!=null)
				q.add(temp.getLeft());
			if(temp.getRight()!=null)
				q.add(temp.getRight());
			System.out.print(temp.getData() + " ");
		}

	}

	public void dfs_it()
	{
		Stack s = new Stack();

		s.push(root);

		while(!s.isEmpty())
		{
			Node temp = s.pop();

			if(((temp.getLeft() == null)&&(temp.getRight() == null)) || (temp.isVisited()))
				System.out.print(temp.getData() + " ");
			else
			{

				if(temp.getRight() == null)
				{
					Node left = temp.getLeft();
					temp.setVisited(true);

					s.push(temp);
					s.push(left);

				}
				else
				{
					if(temp.getLeft() == null)
					{
						Node right = temp.getRight();
						temp.setVisited(true);

						s.push(temp);
						s.push(right);
					}
					else
					{
						Node left = temp.getLeft();
						Node right = temp.getRight();
						temp.setVisited(true);
						s.push(temp);
						s.push(right);
						s.push(left);
					}
				}
			}
		}

	}