二叉搜索树

很久没有认真思考算法了,这两天看了小伙伴的《学习JavaScript数据结构与算法》一书。看到了二叉搜索树一节,感觉又回到了大学时代。下面把书中的代码手敲一下(凭记忆,有改动),分为两个文件BinarySearchTree.js和test.js。用node test.js运行就行了。我要坚持在算法的路上越走越远!!!

// BinarySearchTree.js
// 二叉搜索树

const COMPARE = {
    LESS_THAN: -1,
    EQUAL: 0,
    BIGGER_THAN: 1
};

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

function defaultCompareFn(a, b) {
    if (a < b) {
        return COMPARE.LESS_THAN;
    }

    if (a > b) {
        return COMPARE.BIGGER_THAN;
    }


    return COMPARE.EQUAL;
};


function BinarySearchTree(compareFn = defaultCompareFn) {
    this.compareFn = compareFn;
    this.root = null;
};

/**
 * 插入
 * @param {*} val 
 */
BinarySearchTree.prototype.insert = function(val) {
    // 如果是空树,直接创建根节点
    if (!this.root) {
        this.root = new Node(val);
    } else { // 否则
        this._insert(this.root, val);
    }
};

BinarySearchTree.prototype._insert = function(node, val) {
    if (this.compareFn(val, node.val) === COMPARE.LESS_THAN) {
        if (!node.left) {
            node.left = new Node(val);
        } else {
            this._insert(node.left, val);
        }
    } else {
        if (!node.right) {
            node.right = new Node(val);
        } else {
            this._insert(node.right, val);
        }
    }
};

BinarySearchTree.prototype.remove = function(val) {
    this.root = this._remove(this.root, val);
};

BinarySearchTree.prototype._remove = function(node, val) {
    if (!node) {
        return null;
    }

    if (this.compareFn(val, node.val) === COMPARE.LESS_THAN) { // 小于
        node.left = this._remove(node.left, val);
        return node;
    } else if (this.compareFn(val, node.val) === COMPARE.BIGGER_THAN) { // 大于
        node.right = this._remove(node.right, val);
        return node;
    } else {
        // 叶子节点
        if (!node.left && !node.right) {
            return null;
        }

        if (!node.left) { // 左子树空
            return node.right;
        }

        if (!node.right) { // 右子树空
            return node.left;
        }

        // 两个子树都不空
        // 把右子树中最小节点提上来
        const minNode = this.min(node.right);
        node.val = minNode.val;
        node.right = this._remove(node.right, val);
        return node;
    }
};

BinarySearchTree.prototype.min = function(node) {
    let cur = node || this.root;
    while(cur && cur.left) {
        cur = cur.left;
    }

    return cur;
};

BinarySearchTree.prototype.max = function(node) {
    let cur = node || this.root;
    while(cur && cur.right) {
        cur = cur.right;
    }

    return cur;
};

BinarySearchTree.prototype.search = function(val) {
    return this._search(this.root, val);    
};

BinarySearchTree.prototype._search = function(node, val) {
    if (!node) {
        return false;
    }
    if (this.compareFn(val, node.val) === COMPARE.LESS_THAN) {
        return this._search(node.left, val);
    } else if (this.compareFn(val, node.val) === COMPARE.BIGGER_THAN) {
        return this._search(node.right, val);
    } else {
        return true;
    }
};

BinarySearchTree.prototype.inOrderTraverse = function(callback) {
    this._inOrderTraverse(this.root, callback);
};

BinarySearchTree.prototype._inOrderTraverse = function(node, callback) {
    if (node) {
        this._inOrderTraverse(node.left, callback);
        callback(node);
        this._inOrderTraverse(node.right, callback);
    }
};

BinarySearchTree.prototype.preOrderTraverse = function(callback) {
    this._preOrderTraverse(this.root, callback);
};

BinarySearchTree.prototype._preOrderTraverse = function(node, callback) {
    if (node) {
        callback(node);
        this._preOrderTraverse(node.left, callback);
        this._preOrderTraverse(node.right, callback);
    }
};

BinarySearchTree.prototype.postOrderTraverse = function(callback) {
    this._postOrderTraverse(this.root, callback);
};

BinarySearchTree.prototype._postOrderTraverse = function(node, callback) {
    if (node) {
        this._postOrderTraverse(node.left, callback);
        this._postOrderTraverse(node.right, callback);
        callback(node);
    }
};

module.exports = BinarySearchTree;

// test.js
// test.js
const BinarySearchTree = require('./BinarySearchTree.js');

const arr = [4, 99, 44, 3, 55];
const tree = new BinarySearchTree();

// 1. 插入,构建二叉搜索树
arr.forEach(item => {
    tree.insert(item);
});
console.log('二叉搜索树:');
console.log(JSON.stringify(tree));

// 2. 中序遍历
console.log('中序遍历');
tree.inOrderTraverse(item => {
    // 结果就是从小到大遍历
    console.log(item.val);
});

// 3. 先序遍历
console.log('先序遍历');
tree.preOrderTraverse(item => {
    // 结果就是从上到下
    console.log(item.val);
});

// 4. 中序遍历
console.log('后序遍历');
tree.postOrderTraverse(item => {
    // 结果就是从下到上遍历,保证访问中间节点时子节点已经访问过了,用于自底向上汇总
    console.log(item.val);
});

// 5. 最大
console.log('最大节点:', tree.max());

// 6. 最小
console.log('最大节点:', tree.min());

// 7 8
console.log('99是否存在:', tree.search(99));
console.log('100是否存在:', tree.search(100));

// 9. 移除44
tree.remove(44);
console.log('移除44后结果:');
console.log(JSON.stringify(tree));

// 10. 移除不存在的22
console.log('移除22后结果:');
console.log(JSON.stringify(tree));


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值