zoukankan      html  css  js  c++  java
  • 二叉树创建与前、中、后序遍历

    二叉搜索树的创建

    定义Node为节点类,Tree为二叉树,设置方法insert用于增加树上的结点,根据节点和树上已有结点的权值大小确定插入位置。
    二叉树

    /* 结点 */
    function Node(val, left, right) {
        this.val = val;
        this.left = null;
        this.right = null;
    }
    /* 树 */
    function Tree() {
        this.root = null;
    }
    /* 结点插入二叉树 */
    Tree.prototype.insert = function (val) {
        /* 创建新节点 */
        let newNode = new Node(val, null, null);
        /* 树根为空直接赋值 */
        if (!this.root) {
            this.root = newNode;
        } else {
            let cur = this.root;
            /* 找到位置才能退出循环 */
            while (true) {
                if (newNode.val > cur.val) {
                    /* 右子树为空,直接将新节点作为右孩子 */
                    if (!cur.right) {
                        cur.right = newNode;
                        break;
                    } else {
                        cur = cur.right;
                    }
                }
                if (newNode.val < cur.val) {
                    if (!cur.left) {
                        cur.left = newNode;
                        break;
                    } else {
                        cur = cur.left;
                    }
                }
            }
        }
    }
    let tree = new Tree();
    let arr = [4, 6, 5, 2, 3, 1];
    arr.forEach(v => tree.insert(v));
    

    递归方式实现三种遍历

    递归调用,选择对应时机输出即可,缺点是太耗性能.

    var orderTraversal = function (root) {
        let res = [];
        function order(rt) {
            if (rt) {
                res.push(rt.val);//前序
                order(rt.left);
                // res.push(rt.val);//中序
                order(rt.right);
                // res.push(rt.val);//后序
            }
        }
        order(root);
        return res;
    }
    

    前序遍历

    实现: 弹出栈顶元素node,将栈顶元素的右结点right左结点left放到栈里面,然后取出栈顶元素left作为父结点重复该操作,只有left下的所有结点全部输出完,right才会进行输出,从而实现根->左->右的输出顺序。
    leetcode:https://leetcode-cn.com/problems/binary-tree-preorder-traversal/

    每次循环stack变化:
    [4]--------->4出栈,62进栈
    [6,2]------->2出栈,31进栈
    [6,3,1]----->1出栈
    [6,3]------->3出栈
    [6]--------->6出栈,5进栈
    [5]--------->5出栈
    
    /* 根->左->右 */
    var preorderTraversal = function (root) {
        if (!root) return [];
        let res = [], stack = [root];
        /* 设置栈存序列 */
        while (stack.length) {
            let node = stack.pop();/* 栈顶元素 */
            res.push(node.val);
            /* 后进先出,左边的在后面进入,确保每次先弹出左边结点 */
            if (node.right) stack.push(node.right);
            if (node.left) stack.push(node.left);
        }
        return res;
    };
    console.log(preorderTraversal(tree.root));//[ 4, 2, 1, 3, 6, 5 ]
    

    中序遍历

    实现: 用栈来存储结点,只有结点左子树全部输出完该结点才可能输出,查到没有左孩子的结点node进行输出,然后再到node的右子树进行同样的操作.
    leetcode:https://leetcode-cn.com/problems/binary-tree-inorder-traversal/

    /* 左->根->右 */
    var inorderTraversal = function (root) {
        if (!root) return [];
        let res = [], stack = [], parent = root;
        while (stack.length || parent) {
            /* 一直往左下找,直到最左下方结点 */
            while (parent) {
                stack.push(parent);
                parent = parent.left;
            }
            let node = stack.pop();//弹出最左下方结点
            res.push(node.val);
            parent=node.right;//完成(左->根),对该结点右下方的结点进行遍历
        }
        return res;
    };
    console.log(inorderTraversal(tree.root));//[ 1, 2, 3, 4, 5, 6 ]
    

    后序遍历

    实现: 在中序遍历的基础上添加一个判断,只有右子树全部输出才能输出当前结点。
    leetcode:https://leetcode-cn.com/problems/binary-tree-postorder-traversal/

    /* 左->右->根 */
    var postorderTraversal = function (root) {
        if (!root) return [];
        let set = new Set();//记录结点是否被访问过
        let stack = [], res = [], parent = root;
        while (stack.length || parent) {
            while (parent) {
                stack.push(parent);
                parent = parent.left;
            }
            let node = stack[stack.length - 1];/* 栈顶元素 */
            /* 对还未输出的右子树进行遍历输出 */
            if (node.right && !set.has(node.right)) {
                set.add(node.right);//标记node.right下的子树已经输出
                parent = node.right;
            } else {
                res.push(node.val);
                stack.pop();
            }
        }
        return res;
    }
    console.log(postorderTraversal(tree.root));//[ 1, 3, 2, 5, 6, 4 ]
    
  • 相关阅读:
    [GEF]实现模板功能
    一篇WTP文章
    写代码的代码:JET
    投票选择eclipse.org的新界面
    在SWT里显示AWT对象
    Plugin.xml > Manifest.mf
    关于本体编程的实现
    一个用OWLS组装Web服务的例子
    感受Ruby on Rails
    通过OCP考试
  • 原文地址:https://www.cnblogs.com/aeipyuan/p/12726193.html
Copyright © 2011-2022 走看看