二叉树的递归与非递归方式的先序、中序、后序、层序遍历算法(Java版本)

36 篇文章 1 订阅

介绍

本文提供了二叉树的构造、递归与非递归方式的遍历算法,其中递归方式较为简单。但在实际应用中,递归的遍历方式适用于递归深度不高的算法中,其一般使用非递归方式来解决。

二叉树建树

实验一:输入测试数据序列:A B # D # # C # #

构造二叉树示意图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

非递归遍历二叉树的原理

递归方式遍历二叉树较为简单,本文不做过多描述。非递归方式需要用到栈作为辅助数据结构来实现,非递归遍历二叉树的主要原理在于:利用栈的后进先出性质,来安排二叉树的左右子树的先后遍历次序。例如,
1、若使用栈对二叉树进行先序遍历,我们已知先序遍历是先访问自身,然后访问左子树,最后访问右子树,因此,当一个结点被访问后,我们可将该结点的右子树的根结点先入栈,后将左子树的根结点入栈,最后在出栈时,会先访问左子树,后访问右子树。
2、若使用栈中序遍历二叉树,我们需要将树中最左边的结点入栈,因此需要先通过循环找到树中最左边的结点入栈,出栈时先访问该结点,若该结点有右子树,继续寻找右子树中的最左边的结点,重复上述步骤即可。
3、若使用栈后序遍历二叉树,我们观察后序遍历的结果发现,后序遍历的逆序列,即为先序遍历先访问右子树后访问左子树的结果。因此我们可使用栈,做类似先序遍历的操作,并将结果保存到另一个栈,最后将另一个栈中的结果输出即可。
4、若层序遍历啊二叉树,我们希望二叉树的遍历结果一层一层从上到下,从左到右,均有先后顺序,因此可使用队列作为辅助数据结构,先将根结点入队,当该结点出队时,先将左孩子入队后将右孩子入队。
层序遍历原理示意图:
在这里插入图片描述
层序遍历得到访问序列:ABCD

算法描述

包结构:
在这里插入图片描述

import java.util.Scanner;

public class BTNode {
	protected BTNode lchild;
	protected BTNode rchild;
	protected Object t;
	private static Scanner scanner = new Scanner(System.in);
	//构造二叉树
	public static BTNode createBTNode(){
		String str = scanner.next();
		if(str.equals("#")){
			return null;
		}
		BTNode node = new BTNode();
		node.t = str;
		node.lchild = createBTNode();	//构造左子树
		node.rchild = createBTNode();	//构造右子树
		return node;
	}
	//先序遍历
	public void preTraverse(BTNode root){
		if(root != null){
			System.out.println(root.t);
			preTraverse(root.lchild);
			preTraverse(root.rchild);
		}
	}
	//中序遍历
	public void middleTraverse(BTNode root){
		if(root != null){
			middleTraverse(root.lchild);
			System.out.println(root.t);
			middleTraverse(root.rchild);
		}
	}
	//后序遍历
	public void afterTraverse(BTNode root){
		if(root != null){
			afterTraverse(root.lchild);
			afterTraverse(root.rchild);
			System.out.println(root.t);
		}
	}
	//用栈先序遍历
	public void preTraverseWithStack(BTNode root){
		BTNode stack[] = new BTNode[100];
		int top = -1;
		if(root != null){
			stack[++top] = root;
			while(top != -1){
				BTNode node = stack[top--];
				System.out.println(node.t);
				if(node.rchild != null){			//右孩子存在将右边孩子入栈
					stack[++top] = node.rchild;
				}
				if(node.lchild != null){
					stack[++top] = node.lchild;
				}
			}
		}
	}
	//用栈中序遍历
	public void middleTraverseWithStack(BTNode root){
		BTNode stack[] = new BTNode[100];
		int top = -1;
		if(root != null){
			stack[++top] = root;
			BTNode p = root;
			while(top != -1 || p !=null){
				while(p.lchild != null){
					stack[++top] = p.lchild;
					p = p.lchild;
				}
				if(top != -1){
					BTNode node = stack[top--];
					System.out.println(node.t);
					if(node.rchild != null){
						stack[++top] = node.rchild;
						p = node.rchild;
					}
				}
			}
		}
	}
	//用栈后序遍历,将后序序列反过来,就是先序先遍历右子树后遍历左子树的结果,因此这里使用两个栈,栈2用来反转结果
	public void afterTraverseWithStack(BTNode root){
		BTNode stack1[] = new BTNode[100];
		BTNode stack2[] = new BTNode[100];
		int top1 = -1;
		int top2 = -1;
		if(root != null){
			stack1[++top1] = root;
			while(top1 != -1){
				BTNode node = stack1[top1--];
				stack2[++top2] = node;
				if(node.lchild != null){
					stack1[++top1] = node.lchild;
				}
				if(node.rchild != null){
					stack1[++top1] = node.rchild;
				}
			}
			while(top2 != -1){
				System.out.println(stack2[top2--].t);
			}
		}
	}
	
	public void levelTraverseWithQueue(BTNode root){
		int max = 100;
		BTNode que[] = new BTNode[max];
		int front,rear;
		front = rear = 0;
		if(root != null){
			rear = (rear + 1)%max;
			que[rear] = root;
			while(front != rear){
				front = (front + 1)%max;
				BTNode node = que[front];
				System.out.println(node.t);
				if(node.lchild != null){
					rear = (rear + 1)%max;
					que[rear] = node.lchild;
				}
				if(node.rchild != null){
					rear = (rear + 1)%max;
					que[rear] = node.rchild;
				}
			}
		}
	}
}
import java.util.Scanner;

public class Main {
	public static void main(String [] args){
		BTNode root = null;
		Scanner scanner = new Scanner(System.in);
		System.out.println("选择序号:");
		System.out.println("1、构造二叉树:");
		System.out.println("2、递归先序遍历:");
		System.out.println("3、递归中序遍历:");
		System.out.println("4、递归后序遍历:");
		System.out.println("5、非递归先序遍历:");
		System.out.println("6、非递归中序遍历:");
		System.out.println("7、非递归后序遍历:");
		System.out.println("8、非递归层序遍历:");
		System.out.println("9、退出:");
		while(true){	
			System.out.println("输入操作的序号:");
			int index = scanner.nextInt();
			switch(index){
				case 1:
					root = BTNode.createBTNode();
					break;
				case 2:
					root.preTraverse(root);
					break;
				case 3:
					root.middleTraverse(root);
					break;
				case 4:
					root.afterTraverse(root);
					break;
				case 5:
					root.preTraverseWithStack(root);
					break;
				case 6:
					root.middleTraverseWithStack(root);
					break;
				case 7:
					root.afterTraverseWithStack(root);
					break;
				case 8:
					root.levelTraverseWithQueue(root);
					break;
				case 9:
					scanner.close();
					System.exit(0);
					break;
			}
			System.out.println();
		}
	}
}

结果测试

选择序号:
1、构造二叉树:
2、递归先序遍历:
3、递归中序遍历:
4、递归后序遍历:
5、非递归先序遍历:
6、非递归中序遍历:
7、非递归后序遍历:
8、非递归层序遍历:
9、退出:
输入操作的序号:
1
A B # D # # C # #

输入操作的序号:
4
D
B
C
A

输入操作的序号:
7
D
B
C
A

输入操作的序号:
8
A
B
C
D

输入操作的序号:

总结

本文提供了二叉树的构造、先序、中序、后序、层序的递归与非递归方式的遍历算法,使用Java描述了这些算法,最终通过一组数据来对上述算法进行测试。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值