二叉树的遍历:
递归就不用说了,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);
}