本次拟整理一下二叉树的中序、后序、先序、层次遍历的递归以及非递归代码实现,
1.基础知识:
根据访问结点操作发生位置命名:
① NLR:前序遍历(Preorder Traversal 亦称(先序遍历))
——访问根结点的操作发生在遍历其左右子树之前。
② LNR:中序遍历(Inorder Traversal)
——访问根结点的操作发生在遍历其左右子树之中(间)。
③ LRN:后序遍历(Postorder Traversal)
——访问根结点的操作发生在遍历其左右子树之后。
注意:
由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。
2.先(根)序遍历的递归算法定义:
若二叉树非空,则依次执行如下操作:
⑴ 访问根结点;
⑵ 遍历左子树;
⑶ 遍历右子树。
3.中(根)序遍历的递归算法定义:
若二叉树非空,则依次执行如下操作:
⑴遍历左子树;
⑵访问根结点;
⑶遍历右子树。
4.后(根)序遍历得递归算法定义:
若二叉树非空,则依次执行如下操作:
⑴遍历左子树;
⑵遍历右子树;
⑶访问根结点。
5.递归实现代码
public static class TreeNode{//Definition for a binary tree node.
int val;
TreeNode left;
TreeNode right;
public TreeNode(int x) //有参构造
{ val = x; }
}
①先序递归遍历
public static void Pre_visit(TreeNode root){
if(root!=null){
System.out.print(root.val);
Pre_visit(root.left);
Pre_visit(root.right);
}
}
②中序递归遍历
public static void in_visit(TreeNode root){
if(root!=null){
Pre_visit(root.left);
System.out.print(root.val);
Pre_visit(root.right);
}
}
③后序递归遍历
public static void post_visit(TreeNode root){
if(root!=null){
Pre_visit(root.left);
Pre_visit(root.right);
System.out.print(root.val);
}
}
非递归遍历:
先序,中序,后序借助于栈
层序遍历借助于队列先进先出的性质
//先序非递归
public static void pre_visit_no(TreeNode root){
if(root!=null){
Stack<TreeNode> S = new Stack<TreeNode>();
S.push(root);
while(!S.isEmpty()){
root = (TreeNode) S.pop();
System.out.print(root.val);
while(root !=null){
if(root.left !=null){
System.out.print(root.left.val);
}
if(root.right != null){
S.push(root.right);
}
root = root.left;
}
}
}
}
//中序非递归
public static void in_visit_no(TreeNode root){
if(root!=null){
Stack<TreeNode> S = new Stack<TreeNode>();
S.push(root);
while(!S.isEmpty()){
while(S.peek() !=null){
//将栈顶节点的做孩子节点相继入栈
S.push( ((TreeNode) S.peek()).left );
}
S.pop();//空节点退栈
if(!S.isEmpty()){
root = S.pop();//移除栈顶元素,并返回其值
System.out.println(root.val);//访问节点
S.push(root.right);//节点的右孩子入栈
}
}
}
}
//后序非递归
public static void post_visit_no(TreeNode root){
if(root != null){
Stack<TreeNode> S = new Stack<TreeNode>();
S.push(root);//根节点进栈
Boolean flag = false;//访问标记
TreeNode p = null;//p指向刚被访问的结点
while(!S.isEmpty()){
while(S.peek() != null){
S.push(S.peek().left);//将栈顶结点的做孩子相继入栈
}
S.pop();//空节点退栈
while(!S.isEmpty()){
root =S.peek();
if(root.left == null || root.right == p){
System.out.println(root.val);//访问节点
S.pop();//移除栈顶元素
p = root;//p指向刚被访问的结点
flag = true;//设置访问标记
}else {
S.push(root.right);//右孩子结点入栈
flag = false;//设置未被访问标记
}
if(!flag){
break;
}
}
}
}
}
//层序遍历
public static void levelTraverse(TreeNode root){
if(root != null){
Queue L = new Queue();
//构造队列
L.offer(root);//根节点入队列
while(!L.isEmpty()){
root = (TreeNode) L.poll();
System.out.println(root.val);//访问节点
if(root.left != null){
L.offer(root.left);//左孩子非空入队列
}
if(root.right != null){
L.offer(root.right);//右孩子非空,入队列
}
}
}
}
如有错误,请留言指出。