树结构

树在优点:搜索速度快,插入删除速度快。

一、插入

 insert 添加node,先判断是否有根节点,如果没有则直接插入根节点,如果已经有根节点,则调用isertNode方法。

代码实现:

var Tree = function() {
    var root = null; 
    var Node = function(val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }

    // insertNode 递归插入
    var insertNode = function(node, newNode) {
        if(newNode.val < node.val) {
            // 插入左边
            if(node.left == null) {
                node.left = newNode;
            } else {
                insertNode(node.left, newNode)
            }
        } else {
            // 插入右边
            if (node.right == null) {
                node.right = newNode;
            } else {
                insertNode(node.right, newNode)
            }
        }
    }

    // insert 插入节点
    this.insert = function(val) {
        var node = new Node(val);
        // 判断root
        if(root == null) {
            root = node;
        } else {
            insertNode(root, node);
        }
    }
    // 
    this.getRoot = function() {
        return root;
    }
}
var tree1 = new Tree();
tree1.insert(8)
tree1.insert(2)
tree1.insert(3)
tree1.insert(9)
console.log(tree1.getRoot());

 

二、遍历

代码实现:

    // traverseNode
    var traverseNode = function(node, callback) {
        if(node == null) return;
        // callback(node.val); //  8 2 3 9 前序遍历
        traverseNode(node.left,callback);
        // callback(node.val); // 2 3 8 9 中序遍历
        traverseNode(node.right, callback);
        callback(node.val); // 3 2 9 8 后序遍历
    }
    // traverse 遍历树并执行自定义操作
    this.traverse = function(callback) {
        traverseNode(root,callback);
    }

 使用:

var tree1 = new Tree();
tree1.insert(8)
tree1.insert(2)
tree1.insert(3)
tree1.insert(9)
console.log(tree1.getRoot());
var print = function(val) {
    console.log(val)
}
console.log(tree1.traverse(print));

 

三、移除

移除: 先查找到想删除的节点;

  • 当节点为叶节点时替换为null,并返回;
  • 当节点有一个子节点:将node替换为子节点;
  • 当节点有两个子节点:查找到右树的最小子节点,替换node,并将右树最小子节点删除

注意:移除成功后都要返回新的树

// finMinNode 查找最小子节点
    var finMinNode = function(node) {
        if(node == null) return;
        while(node && node.left) {
            node = node.left;
        }
        return node;
    }

    // removeNode 移除递归 返回新的树
    var removeNode = function(node,value) {
        if(value < node.val) {
            // 向左查找:设置新的左子节点
            node.left = removeNode(node.left, value);
            // console.log(node.left)
            return node;
        } else if(value > node.val) {
            // 向右查找:设置新的右子节点
            node.right = removeNode(node.right, value);
            return node;
        } else {
            // value == node.val
            // 叶节点:叶节点替换为null,并返回
            if(node.left == null && node.right == null) {
                // console.log(node)
                node = null;
                return node;
            } 

            // 一个子节点:将node替换为子节点
            if(node.left == null && node.right) {
                return node.right;
            } else if(node.left && node.right == null) {
                return node.left;
            }

            // 两个子节点:查找到右树的最小子节点,替换node,并将右树最小子节点删除
            var aux = finMinNode(node.right); //获取右树的最小子节点
            node.val = aux.val;
            node.right = removeNode(node.right, aux.val);
            return node;
        }
    }
    // remove 移除
    this.remove = function(value) {
        // removeNode中删除后要创建新的树,所以要赋值给root
        root = removeNode(root,value);
    }

 使用:

var tree1 = new Tree();
tree1.insert(11)
tree1.insert(8)
tree1.insert(4)
tree1.insert(9)
tree1.insert(3)
tree1.insert(5)
tree1.insert(10)

// tree1.remove(3)
// tree1.remove(9)
tree1.remove(8)
console.log(tree1.getRoot());

 

四、整体代码

var Tree = function() {
    var root = null; 
    var Node = function(val) {
        this.val = val;
        this.left = null;
        this.right = null;
    }

    // insertNode 递归插入
    var insertNode = function(node, newNode) {
        if(newNode.val < node.val) {
            // 插入左边
            if(node.left == null) {
                node.left = newNode;
            } else {
                insertNode(node.left, newNode)
            }
        } else {
            // 插入右边
            if (node.right == null) {
                node.right = newNode;
            } else {
                insertNode(node.right, newNode)
            }
        }
    }

    // insert 插入节点
    this.insert = function(val) {
        var node = new Node(val);
        // 判断root
        if(root == null) {
            root = node;
        } else {
            insertNode(root, node);
        }
    }
    // getRoot 获取根节点
    this.getRoot = function() {
        return root;
    }

    // traverseNode
    var traverseNode = function(node, callback) {
        if(node == null) return;
        // callback(node.val); //  8 2 3 9 前序遍历
        traverseNode(node.left,callback);
        // callback(node.val); // 2 3 8 9
        traverseNode(node.right, callback);
        callback(node.val); // 3 2 9 8
    }
    // traverse 遍历树并执行自定义操作
    this.traverse = function(callback) {
        traverseNode(root,callback);
    }

    // finMinNode 查找最小子节点
    var finMinNode = function(node) {
        if(node == null) return;
        while(node && node.left) {
            node = node.left;
        }
        return node;
    }

    // removeNode 移除递归 返回新的树
    var removeNode = function(node,value) {
        if(value < node.val) {
            // 向左查找:设置新的左子节点
            node.left = removeNode(node.left, value);
            // console.log(node.left)
            return node;
        } else if(value > node.val) {
            // 向右查找:设置新的右子节点
            node.right = removeNode(node.right, value);
            return node;
        } else {
            // value == node.val
            // 叶节点:叶节点替换为null,并返回
            if(node.left == null && node.right == null) {
                // console.log(node)
                node = null;
                return node;
            } 

            // 一个子节点:将node替换为子节点
            if(node.left == null && node.right) {
                return node.right;
            } else if(node.left && node.right == null) {
                return node.left;
            }

            // 两个子节点:查找到右树的最小子节点,替换node,并将右树最小子节点删除
            var aux = finMinNode(node.right); //获取右树的最小子节点
            node.val = aux.val;
            node.right = removeNode(node.right, aux.val);
            return node;
        }
    }
    // remove 移除
    this.remove = function(value) {
        // removeNode中删除后要创建新的树,所以要赋值给root
        root = removeNode(root,value);
    }
}
var tree1 = new Tree();
tree1.insert(11)
tree1.insert(8)
tree1.insert(4)
tree1.insert(9)
tree1.insert(3)
tree1.insert(5)
tree1.insert(10)
console.log(tree1.getRoot());
// var print = function(val) {
//     console.log(val)
// }
// console.log(tree1.traverse(print));

// tree1.remove(3)
// tree1.remove(9)
tree1.remove(8)
console.log(tree1.getRoot());

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值