欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

二叉树的遍历

程序员文章站 2022-06-05 18:57:59
...

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

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

先序是:根左右

中序是:左根右

后序是:左右根

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

一、先序遍历

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;
}

 

相关标签: 二叉树 遍历