二叉树的遍历

 常见的二叉树的四种遍历方式为先序遍历,中序遍历,后序遍历及层次遍历。

所谓的先序、中序及后序遍历,都是先递归的访问左子树,再递归访问右子树,而根结点要么是在访问左子树之前访问,要么是在左子树之后右子树之前访问,要么是在右子树之后访问,这就是对应了先序、中序及后序遍历。也就是如下:

先序是:根左右

中序是:左根右

后序是:左右根

而层次遍历是从上到下按照每一层的顺序遍历,每一层中按照从左到右的顺序遍历。

一、先序遍历

1、递归方法

按照递归的定义,利用递归很容易实现二叉树的先序遍历。

//先序遍历
//递归实现
public List<Value> preOrder() {
	List<Value> list = new ArrayList<Value>();
	list = preOrder(root,list);
	return list;
}

private List<Value> preOrder(Node node, List<Value> list) {
	if(node == null)
		return list;
	list.add(node.val );
	list = preOrder(node.left, list);
	list = preOrder(node.right,list);
	return list;
}

 2、迭代的方法(1)

根据先序遍历的定义,先访问根结点,再访问左子树,最后访问右子树,我们可以利用一个栈来递归的实现。

//先序遍历的迭代实现1
private List<Value> preOrder1(Node node, List<Value> list) {
	if(node == null)
		return list;
	Stack<Node> stack = new Stack<Node>();
	stack.push(node);
	while(!stack.isEmpty()) {
		Node n = stack.pop();
		list.add(n.val);
		if(n.right != null)
			stack.push(n.right);
		if(n.left != null)
			stack.push(n.left);
	}
	return list;
}

下面是一个采用此迭代方法的一个实例。

但是这种方法不能有效的推广到中序、后序遍历中,因此,换一种思路,我们可以得到新的迭代的方法。

3、迭代的方法(2)

 观察一下以下这个先序遍历二叉树的一个实例。

通过观察,我们可以将二叉树的先序遍历总结为这样一个过程,如下图所示:

我们总是以根结点开始,首先从上到下沿着它的最左边的那条路径访问,直到最左边的那个结点不再有左子结点;然后,我们再从下到上,依次访问前面最左边路径上的每个结点的右结点所对应的子树。

这种方法的实现依旧需要使用到一个栈,具体的代码实现如下:

//先序遍历的迭代实现2
private List<Value> preOrder2(Node node, List<Value> list) {
	if(node == null)
		return list;
	Stack<Node> stack = new Stack<Node>();
	while(true) {
		visitLeftLine(node,list,stack);
		if(stack.isEmpty())
			break;
		node = stack.pop();
	}
	return list;
}

//从上到下依次遍历完以node为根结点的二叉树的最左边路径上的所有结点
private List<Value> visitLeftLine(Node node, List<Value> list, Stack<Node> stack) {
	while(node != null) {
		list.add(node.val);
		if(node.right != null)
			stack.push(node.right);
		node = node.left;
	}
	return list;
}

利用此方法的进行遍历的过程的一个实例如下图所示

 二、中序遍历

1、递归方法

首先,根据中序遍历的定义,通过递归仍然可以很容易的进行中序遍历:

//中序遍历,递归
public List<Value> inOrder() {
	List<Value> list = new ArrayList<Value>();
	
	list = inOrder(root,list);
	
	return list;
}

private List<Value> inOrder(Node node, List<Value> list) {
	if(node == null)
		return list;
	list = inOrder(node.left, list);
	list.add(node.val);
	list = inOrder(node.right,list);
	return list;
}

2、迭代方法:

首先观察中序遍历的规律:

通过观察,我们可以总结出如下规律:

对于一颗二叉树,中序遍历首先总是沿着最左侧路径向下,直到某个结点的左结点为空,然后访问该节点,再访问该结点的右子树,访问完成之后,再沿着左侧路径向上,依次向上遍历。

为了能够迭代实现,依然需要使用一个栈,具体的代码如下:

//迭代方法
private List<Value> inOrder1(Node node, List<Value> list) {
	if(node == null)
		return list;
	Stack<Node> stack = new Stack<Node>();
	while(true) {
		goAlongLeftLine(node, stack);
		if(stack.isEmpty())
			break;
		node = stack.pop();
		list.add(node.val);
		node = node.right;
	}
	return list;
}

private void goAlongLeftLine(Node node, Stack<Node> stack) {
	while(node != null) {
		stack.push(node);
		node = node.left;
	}
}

下面是一个迭代方法对二叉树进行中序遍历的实例:

三、后序遍历

1、递归实现:

//后序遍历
public List<Value> postOrder() {
	List<Value> list = new ArrayList<Value>();
	list = postOrder1(root,list);
	return list;
}
//递归方法
private List<Value> postOrder(Node node, List<Value> list) {
	if(node == null)
		return list;
	list = postOrder(node.left, list);
	list = postOrder(node.right,list);
	list.add(node.val);
	return list;
}

四、层次遍历

利用队列实现:

//层次遍历
public List<Value> order() {
    List<Value> list = new ArrayList<Value>();
    Queue<Node> queue = new LinkedBlockingQueue<Node>();
    if(root == null)
        return list;
    queue.add(root);
    while(!queue.isEmpty()) {
	Node node = queue.remove();
	list.add(node.val);
	if(node.left != null)
            queue.add(node.left);
	if(node.right != null)
       	    queue.add(node.right);
    }
    return list;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值