javascript算法系列——树:二叉树和二叉查找树

二叉树的基本术语

  • 结点之间的关系
    • 若一个结点有子树,那么该结点称为子树根的双亲,子树的根称为该结点的孩子
    • 有相同双亲的结点互为兄弟
    • 一个结点的所有子树上的任何结点都是该结点的后裔
    • 从根结点到某个结点的路径上的所有结点都是该结点的祖先
  • 结点层:根结点的层定义为第一层,根的孩子为第二层,依此类推
  • 树的深度:树中最大的结点层
  • 结点的度:结点拥有的子树的个数
  • 树的度: 树中最大的结点度
  • 叶子结点:也叫终端结点,是度为 0 的结点
  • 分枝结点:度不为0的结点

二叉查找树

二叉查找树是一种 特殊的二叉树,相对较小的值保存在左节点中,较大的值保存在右节点中。这一特性使得 查找的效率很高,对于数值型和非数值型的数据,比如单词和字符串,都是如此。

实现二叉查找树

二叉查找树由节点组成,所以我们要定义的第一个对象就是 Node,该对象和前面介绍链表
时的对象类似。

function Node(data, left, right) {
    this.data = data
    this.left = left
    this.right = right
    this.show = show
}
function show() {
    return this.data;
}

Node 对象既保存数据,也保存和其他节点的链接(left 和 right),show() 方法用来显示 保存在节点中的数据。

function BST() {
    this.root = null;           // 根节点
    this.insert = insert;       // 插入节点
    this.preOrder = preOrder;   // 先序遍历
    this.inOrder = inOrder;     // 中序遍历
    this.postOrder = postOrder; // 后序遍历
    this.find = find;           // 查找节点
    this.getMin = getMin;       // 查找最小值
    this.getMax = getMax;       // 查找最大值
}
//insert:向树中添加新节点
function insert(data) {
    var n = new Node(data, null, null)
    if (this.root === null) {
        this.root = n
    } else {
        var curNode = this.root
        while (true) {
            if (data < curNode.data) {
                if (curNode.left === null) {
                    curNode.left = n
                    break
                }
                curNode = curNode.left
            }
            else {
                if (curNode.right === null) {
                    curNode.right = n
                    break
                }
                curNode = curNode.right
            }
        }
    }
}
var nums = new BST();
//插入数据
nums.insert(23);
nums.insert(45);
nums.insert(16);
nums.insert(37);
nums.insert(3);
nums.insert(99);
nums.insert(22);
nums.insert(45);
nums.insert(-1);
/* console.log('Node: /n ');
console.log(nums.root)
console.log('\n 前序 /n ');
preOrder(nums.root);
console.log('\n 中序 /n ');
inOrder(nums.root)
console.log('\n 后序 /n ');
postOrder(nums.root) */

/* 二叉树查找 */
//查找最小值
function getMin() {
    var current = this.root
    while (current.left !== null) {
        current = current.left
    }
    return current.show()
}
//查找最大值
function getMax() {
    var current = this.root
    while (current.right !== null) {
        current = current.right
    }
    return current.show()
}
/* console.log('min:',nums.getMin())
console.log('max:',nums.getMax())
 */

/* find */
function find(data) {
    var current = this.root
    while (current !== null && current.data !== data) {
        if (data < current.data) {
            current = current.left
        } else {
            current = current.right
        }
    }
    if (current === null) return null
    return current
}
console.log('find result:', nums.find(45));
遍历二叉树

有三种遍历 BST 的方式:中序、先序和后序。中序遍历按照节点上的键值,以升序访问 BST 上的所有节点。先序遍历先访问根节点,然后以同样方式访问左子树和右子树。后序 遍历先访问叶子节点,从左子树到右子树,再到根节点。

先序遍历

根结点 -> 左子树 -> 右子树
在这里插入图片描述

//递归方式
function preOrder(node) {
    if (!node) {
        console.log(node.show() + ' ')
        preOrder(node.left)
        preOrder(node.right)
    }
}

//非递归方式
function preOrder(root)
{
    var stack = [];
    var node = root;
    while(node || stack.length != 0){
        //循环访问节点的左子结点并入栈
        while(node){
            console.log(node.val);
            stack.push(node);
            node = node.left;
        }
        if(stack.length != 0){
            node = stack.pop();
            node = node.right();
        }
    }
}
中序遍历

左子树 -> 根结点 -> 右子树
在这里插入图片描述

//当node不为空,一直沿着左先遍历
//递归
function inOrder(node) {
    if (!(node == null)) {
        inOrder(node.left)
        console.log(node.show() + ' ')
        inOrder(node.right)
    }
}
//非递归
function inOrder(root)
{
    var stack = [];
    var node = root;
    while(node || stack.length != 0){
        while(node){
            stack.push(node);
            node = node.left;
        }
        if(stack.length != 0){
            node = stack.pop();
            console.log(node.val);
            node = node.right();
        }
    }
}
后序遍历

左子树 -> 右子树 -> 根结点
在这里插入图片描述

//递归
function postOrder(node) {
    if (!(node == null)) {
        postOrder(node.left)
        postOrder(node.right)
        console.log(node.show() + ' ')
    }
}

//非递归
function postOrder(root)
{
    var stack = [];
    var node = root;
    var lastVisit = null;   //标记每次遍历最后一次访问的结点
    while(node || stack.length != 0){
        while(node){
            stack.push(node);
            node = node.left;
        }
        if(stack.length != 0){
            node = stack.pop();
            //判断节点是否有右子结点,同时判断lastVisit避免重复输出右子结点)
            if(node.right == null || node.right == lastVisit){
                //如果没有则输出
                console.log(node.val);
                lastVisit = node;
                node = null;
            }
            else{
                //如果有则再次入栈,并访问节点的右子节点
                stack.push(node);
                node = node.right();
            }
        }
    }
}
层序遍历

层序遍历用队列实现

function levelOrder(root)
{
    var queue = [], res = [];
    queue.push(root);
    while(queue.length != 0){
        let len = queue.length;  //一层结点个数
        let temp = [];
        for(let i = 0; i < len; i++){
            var node = queue.shift();
            temp.push(node.val);
            if(node.left)
                queue.push(node.left);
            if(node.right)
                queue.push(node.right);
        }
        res.push(temp);
    }
    return res;
}
♡ ♡ ♡ ♡ ♡ ♡
关注我,每日都有新收获!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值