二叉树遍历

本文主要参考资料:https://mp.weixin.qq.com/s?__biz=MzUxNjY5NTYxNA==&mid=2247484654&idx=1&sn=0c22c8b8771acc2387bf37ac255749f0&scene=21#wechat_redirect

深度遍历

递归遍历

递归算法的三要素

  1. 确定递归函数的参数和返回值
  2. 确定终止条件:如果递归没有终止,操作系统的内存栈必然就会溢出。
  3. 确定单层递归的逻辑:确定每一层递归需要处理的信息,可能会重复调用自己来实现递归

树结构

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) {
    val = x;
    }
}

二叉树递归遍历

  1. 前序遍历
  2. 中序遍历
  3. 后序遍历

二叉树迭代遍历

1. 先序遍历

思路:重复以下步骤,直至node==null&&s.empty()
1)循环将node的左链(同色为同一左链)存入栈中,并在存栈(1)后访问node
2)若到达当前node的左链末端(null),若栈不空,则取出栈中node.right赋值node
先序遍历

图1 先序遍历的7字形访问路径
public List<Integer> preorderTraversal(TreeNode root) {
    List<Integer> res = new Stack<Integer>();
    Stack<TreeNode> s = new Stack<TreeNode>();
    TreeNode p = root;
    while (!s.empty() || p != null) {
       while (p != null) {
           s.push(p);
           res.add(p.val);
           p = p.left;
       }
       if (!s.empty()) {
           p = s.peek();
           s.pop();
           p = p.right;
       }
    }
    return res;
}
2. 中序遍历

思路:重复以下步骤,直至node==null&&s.empty()
1)循环将node的左链(同色为同一左链)存入栈(1)中
2)若到达node的左链末端且若栈不空,则弹栈(2)并访问node,将node.right赋值node

public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> res = new Stack<Integer>();
    Stack<TreeNode> s = new Stack<TreeNode>();
    TreeNode p = root;
    while (!s.empty() || p != null) {
        while (p != null) {
            s.push(p);
            p = p.left;
        }
        if (!s.empty()) {
            p = s.peek();
            s.pop();
            res.add(p.val);
            p = p.right;
        }
    }
    return res;
}
3. 后序遍历

思路:重复以下步骤,直至node==null&&s.empty()
1)循环将node的左链(同色为同一左链)存入栈(1)中
2)若到达node的左链末端且若栈不空,则查看栈顶node
 i) 若其right未被访问(2),则将node.right赋值给node
 ii)若其right已被访问(3),则弹栈并访问node

public List<Integer> inorderTraversal(TreeNode root) {
       List<Integer> res = new Stack<Integer>();
       Stack<TreeNode> s = new Stack<TreeNode>();
       TreeNode r = null;
       TreeNode p = root;
       while (!s.empty() || p != null) {
           if(p != null) {
               s.push(p);
               p = p.left;
           }
           else{
               p = s.peek();
               if(p.right==null||r==p.right) {
                   s.pop();
                   res.add(p.val);
                   r=p;
                   p=null;//再次引发出栈,也可以导致循环结束
               }
               else {
                   p = p.right;
               }
           }
       }
       return res;
}

二叉树morris遍历

1. morris实现原理

1)如果cur无左孩子,cur向右移动(cur=cur.right)
2)如果cur有左孩子,找到cur左子树上最右的节点,记为mostright
如果mostright的right指针指向空,让其指向cur,并设置cur=cur.left
如果mostright的right指针指向cur,让其指向空,并设置cur=cur.right

在这里插入图片描述

图2 morris遍历树时的节点
#### 2. morris先序遍历
public static void morrisPre(Node head) {
    Node cur = head;
    Node mostRight = null;
    while (cur != null){
        mostRight = cur.left;
        if(mostRight != null){
            while (mostRight.right !=null && mostRight.right != cur){
                mostRight = mostRight.right;
            }
            if(mostRight.right == null){
                mostRight.right = cur;
                System.out.print(cur.value+" ");
                cur = cur.left;
                continue;
            }else {
                mostRight.right = null;
            }
        }else {
            System.out.print(cur.value + " ");
        }
        cur = cur.right;
    }
}
3.morris中序遍历
public static void morrisIn(Node head) {
    Node cur = head;
    Node mostRight = null;
    while (cur != null){
        mostRight = cur.left;
        if(mostRight != null){
            while (mostRight.right !=null && mostRight.right != cur){
                mostRight = mostRight.right;
            }
            if(mostRight.right == null){
                mostRight.right = cur;
                cur = cur.left;
                continue;
            }else {
                mostRight.right = null;
            }
        }
        System.out.print(cur.value+" ");
        cur = cur.right;
    }
    System.out.println();
}
4.morris后序遍历
public static void morrisPos(Node head) {
       Node cur = head;
       Node mostRight = null;
       while (cur != null){
           mostRight = cur.left;
           if(mostRight != null){
               while (mostRight.right !=null && mostRight.right != cur){
                   mostRight = mostRight.right;
               }
               if(mostRight.right == null){
                   mostRight.right = cur;
                   cur = cur.left;
                   continue;
               }else {
                   mostRight.right = null;
                   printEdge(cur.left);
               }
           }
           cur = cur.right;
       }
       printEdge(head);
       System.out.println();
   }
   public static void printEdge(Node node){
       Node tail =reverseEdge(node);
       Node cur = tail;
       while (cur != null ){
           System.out.print(cur.value+" ");
           cur =cur.right;
       }
       reverseEdge(tail);
   }
   public static Node reverseEdge(Node node){
       Node pre = null;
       Node next = null;
       while (node != null){
           next = node.right;
           node.right = pre;
           pre = node;
           node = next;
       }
       return pre;
   }

广度遍历

思路:当cur==rear时,该层遍历结束

public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();
    if(root==null){
        return res;
    }
    LinkedList<TreeNode> queue = new LinkedList<>();
    List<Integer> partRes = new ArrayList<>();
    TreeNode rear = root;
    queue.add(root);
    while(!queue.isEmpty()){
        TreeNode cur = queue.poll();
        partRes.add(cur.val);
        if(cur.left != null){
            queue.add(cur.left);
        }
        if(cur.right!=null){
            queue.add(cur.right);
        }
        if(cur == rear){
            res.add(partRes);
            partRes=new ArrayList<>();
            if(!queue.isEmpty())
                rear=queue.getLast();
        }
    }
    return res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值