二叉树的多种遍历

本文详细介绍了二叉树的先序遍历、中序遍历、后序遍历和层序遍历四种方法,包括递归实现和非递归实现,以及具体的遍历逻辑。此外,还提供了测试代码和相应的测试结果。
摘要由CSDN通过智能技术生成

二叉树的遍历:

递归就不用说了,3行代码就解决了

面试的时候遇到这个,想不起来了,现在总结一下。

参考博客:https://blog.csdn.net/u012102306/article/details/52841163

https://www.cnblogs.com/SHERO-Vae/p/5800363.html

先序遍历:

根左右。当前节点p放入栈中,判断P是否有左孩子,如果没有,则从栈中取出这个节点,并且将p的右孩子当做当前节点。如果有左孩子,则p的左孩子为当前节点。知道p为空并且栈为空,遍历结束。

p遍历树的时候直接输出再入栈

	/**
	 * 二叉树的先序遍历
	 * 遍历的时候输出
	 * 根左右
	 * 1245367
	 */
	public static void preOder(Tree tree){
		Tree p = tree;
		Stack<Tree> s = new Stack<Tree>();
		while(p != null || s.isEmpty()==false){
//			如果有左子树,入栈
			while(p != null){
				System.out.print(p.val);
				s.push(p);
				p = p.left;
			}
//			p指向栈顶元素
			if(!s.isEmpty()){
				Tree pop = s.pop();
				p = pop;
				p = p.right;
			}
		}
	}

中序遍历:

等到出栈的时候再输出栈顶元素

	/**
	 * 二叉树的中序遍历
	 * 出栈时再输出
	 * 左根右
	 * 4251637
	 */
	public static void midOder(Tree tree){
		Stack<Tree> s = new Stack<Tree>();
		Tree p = tree;
		while(p != null || s.isEmpty()==false){
			while(p != null){
				s.push(p);
				p = p.left;
			}//
			if(s.isEmpty()==false){
				Tree t = s.pop();
				System.out.print(t.val);
//				p指向栈顶元素
				p = t;
				p = p.right;
			}//if
		}//while
	}

后序遍历:

保证根节点必须在左右节点都遍历之后才能遍历,两个引用pre(上一次访问的节点),cur(当前访问的节点)

如果左右节点为空,则为叶子节点,输出

如果pre不为空,并且当前节点的左子树或者右子树等于pre,则表示左右节点已经访问过,输出

否则,

将当前节点的右孩子,左孩子分别入栈,右孩子先入栈,左孩子再入栈,这样栈顶的元素就是左孩子

/**
	 * 二叉树的后序遍历
	 * 左右根
	 * 4526731
	 */
	public static void postOder(Tree tree){
		Tree pre = null;//上一次访问的节点
		Tree cur = null;//当前节点
		Stack<Tree> s = new Stack<Tree>();
//		根节点先入栈
		s.push(tree);
		while(s.isEmpty()==false){
//			cur指向栈顶元素
			cur = s.peek();
			if((cur.left==null && cur.right==null)
					||
				(pre!=null&&(pre==cur.left || pre == cur.right))){
//				叶子节点或者当前节点的左右节点已经遍历过
				System.out.print(cur.val);
				s.pop();
				pre = cur;
			}else{
//				先push右节点,再左节点,这样左节点在上面,下次遍历栈得到的栈顶元素就是左节点
				if(cur.right!= null){
					s.push(cur.right);
				}
				if(cur.left!= null){
					s.push(cur.left);
				}
				
			}
		}
	}

层序遍历:

/**
	 * 二叉树的层序遍历
	 * 1234567
	 * @throws Exception 
	 */
	public static void Oder(Tree tree){
//		使用队列
		LinkedBlockingQueue<Tree> q = new LinkedBlockingQueue<Tree>();
		Tree p = tree;
//		根节点先进队列
		q.add(p);
		while(q.isEmpty()==false){
			Tree top = q.poll();
			p = top;
			System.out.print(p.val);
//			每次输出队列中一个元素,将这个节点的左右节点入队
			if(p.left!=null){
				q.add(p.left);
			}
			if(p.right!= null){
				q.add(p.right);
			}
		}
	}

按层遍历,并且按层换行:

/**
	 * 二叉树的层序遍历,按层输出
	 * @throws Exception 
	 */
	public static void Oder2(Tree tree){
//		使用队列
		LinkedBlockingQueue<Tree> q = new LinkedBlockingQueue<Tree>();
//		last执行每一行的最后一个元素
		Tree last = tree;
//		nlast指向队列中最新进入的一个元素
		Tree nlast = tree;
		Tree p = tree;
//		根节点先进队列
		q.add(p);
		while(!q.isEmpty()){
			p = q.poll();
			System.out.print(p.val);
//			nlast始终表示这一层的最后一个元素
			if(p.left!=null){
				q.add(p.left);
				nlast = p.left;
			}
			if(p.right!=null){
				q.add(p.right);
				nlast = p.right;
			}
			if(last == p){
//				当前出队的元素是某一行的最后一个元素,这时候输出换行,并且last指向下一行的最后一个元素
				System.out.println();
				last = nlast;
			}//
			
			
		}
		
	}

二叉树结构:

class Tree{
	int val;
	Tree left;
	Tree right;
	public Tree(int val){
		this.val = val;
	}
}

测试代码:

public static void main(String[] args) {
		Tree root = new Tree(1);
		Tree r1 = new Tree(2);
		Tree r2 = new Tree(3);
		Tree r3 = new Tree(4);
		Tree r4 = new Tree(5);
		Tree r5= new Tree(6);
		Tree r6 = new Tree(7);
		root.left = r1;
		root.right = r2;
		r1.left = r3;
		r1.right = r4;
		r2.left = r5;
		r2.right = r6;
		System.out.println("前序:");
		preOder(root);
		System.out.println("\n中序:");
		midOder(root);
		System.out.println("\n后序:");
		postOder(root);
		System.out.println("\n层序:");
		Oder(root);
		System.out.println("\n按层输出:");
		Oder2(root);
	}

测试结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值