二叉树的遍历
递归遍历
递归遍历算法比较简单,暂时不表
递归前序遍历
递归中序遍历
递归后序遍历
非递归遍历
优点:比递归快
缺点:经过做题发现,如下的这些非递归的遍历方式,对于求路径上和值等等问题不太方便,因为下面这些算法都是对一个栈进行操作的,当节点往上退时,不清楚是跳过了哪些节点。这是非递归遍历的缺点。如果有更好的解决办法,请留言。
应用:当题目比较复杂,且不限制使用递归时,就用递归结构解答较为复杂的二叉树问题。
非递归前序遍历
方法一:
static void preorderBinaryTree(TreeNode root){
TreeNode p=root;
Stack<TreeNode> s=new Stack<TreeNode>();
//前序遍历二叉树
while(!s.empty() || p!=null){
if(p!=null){
System.out.println(p.val);//访问的位置
s.push(p);
p=p.left;
}
else{
p=s.pop();
p=p.right;
}
}
}
方法二:
//前序遍历方法二
static void preorderBinaryTree2(TreeNode root){
TreeNode p=root;
Stack<TreeNode> s=new Stack<TreeNode>();
//前序遍历二叉树
s.push(p);
while(!s.empty()){
//访问的位置
p=s.pop();
System.out.print(p.val);
if(p.right!=null){
s.push(p.right);
}
if(p.left!=null){
s.push(p.left);
}
}
}
非递归中序遍历
//中序遍历
//对前序遍历方法一稍加改动,即可得到中序遍历。它们仅仅是访问位置不同
static void inorderBinaryTree(TreeNode root){
TreeNode p=root;
//初始化栈
Stack<TreeNode> s=new Stack<TreeNode>();
//中序遍历二叉树
while(!s.empty() || p!=null){
if(p!=null){
s.push(p);
p=p.left;
}
else{
p=s.pop();
System.out.println(p.val);
p=p.right;
}
}
}
非递归后序遍历
方法一:
//后序遍历(双栈法)
//对前序遍历方法二,稍加改动,即可得到后序遍历。
static void postBinaryTree(TreeNode root){
if(root==null) System.out.println("error");
TreeNode p=root;
Stack<TreeNode> s1=new Stack<TreeNode>();
Stack<TreeNode> s2=new Stack<TreeNode>();
s1.push(p);
while(!s1.empty()){
//访问的位置,将S1弹出的节点压入S2
p=s1.pop();
s2.push(p);
if(p.left!=null){
s1.push(p.left);
}
if(p.right!=null){
s1.push(p.right);
}
}
//算法原理即在于此,后序遍历的顺序和左右子树交换后的前序遍历是相反的
while(!s2.empty()){
System.out.print(s2.pop().val);
}
}
方法二:
static void postBinaryTree2(TreeNode root){
if(root==null) System.out.println("error");
Stack<TreeNode> s=new Stack<TreeNode>();
TreeNode p=root;
//此算法必须设置一个变量,保存前一个访问的节点。也只用保存上一个即可。
TreeNode preVisited=null;
while(!s.empty() || p!=null){
//先遍历最左边,直到为空
while(p!=null){
s.push(p);
p=p.left;
}
//从栈中获取元素
p=s.peek();
//如果右孩子为空或者已经被访问,则访问当前节点。否则访问右孩子
//判断的条件都是针对右孩子的,别写错
if(p.right==null || p.right==preVisited){
//访问节点
System.out.print(p.val);
s.pop();
//千万别忘了下面的更新操作
preVisited=p;
p=null;
}
else{
p=p.right;//访问右孩子
}
}