js 实现二叉树

用 js 实现的二叉树数据结构,完成 先/中/后 序遍历、查找最 大/小 值、查找特定值以及删除节点(虽然没太理解)的操作。

// 节点对象
class Node {
    constructor(data) {
        this.root = this;
        this.data = data;
        this.left = null;
        this.right = null;
    }
}

// 二叉树
class BST {
    constructor() {
        this.root = null;
    }

    // 插入节点
    insert(data) {
        let newNode = new Node(data);
        let insertNode = (node, newNode) => {
            if (newNode.data < node.data) {
                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)
                }
            }
        };

        if (!this.root) {
            this.root = newNode;
        } else {
            insertNode(this.root, newNode)
        }
    }

    /* 中序遍历 => 
        1.访问左子树(先访问左子树中的左子树,再访问左子树中的右子树); 
        2.访问根
        3.访问右子树(先访问右子树中的左子树,再访问右子树中的右子树)

        可以起到排序作用
    */
    inOrder() {
        let backs = [];
        let inOrderNode = (node, callback) => {
            if (node !== null) {
                inOrderNode(node.left, callback);
                backs.push(callback(node.data));
                inOrderNode(node.right, callback);
            }
        }

        let callback = function(v) {
            return v
        }
        inOrderNode(this.root, callback);
        return backs
    }

    // 前序遍历 => 1.访问根节点; 2.访问左子树; 3.访问右子树
    preOrder() {
        let backs = [];
        let preOrderNode = (node, callback) => {
            if (node !== null) {
                backs.push(callback(node.data));
                preOrderNode(node.left, callback);
                preOrderNode(node.right, callback);
            }
        }
        let callback = function(v) {
            return v
        }
        preOrderNode(this.root, callback);
        return backs
    }

    /* 后序遍历 =>
        1.访问左子树。(先访问左子树中的左子树,再访问左子树中的右子树)
        2.访问右子树。(先访问右子树中的左子树,再访问右子树中的右子树)
        3.访问根
    */
    postOrder(){
        let backs = [];
        const postOrderNode = (node,callback) => {
            if(node !== null){
                postOrderNode(node.left,callback);
                postOrderNode(node.right,callback);
                backs.push(callback(node.data))
            }
        };

        let callback = function(v) {
            return v
        }
        postOrderNode(this.root,callback);
        return backs
    }

    // 查找最小值
    getMin(node) {
        let minNode = node => {
            return node ? (node.left ? minNode(node.left) : node) : null
        }

        return minNode(node || this.root)
    }

    // 查找最大值
    getMax(node) {
        let maxNode = node => {
            return node ? (node.right ? maxNode(node.right) : node) : null
        }

        return maxNode(node || this.root)
    }

    // 查找特定值
    find(data) {
        let findNode = (node, data) => {
            if (node == null) return false
            if (node.data === data) return node;
            return findNode((data < node.data) ? node.left : node.right, data);
        }

        return findNode(this.root, data);
    }

    // 删除节点
    // 返回新的二叉树?
    remove(data) {
        let removeNode = (node, data) => {
            if (node === null) return null;
            if (node.data === data) {
                if (node.left === null && node.right === null) return null
                if (node.left === null) return node.right;
                if (node.right === null) return node.left;
                if (node.left !== null && node.right !== null) {
                    let _node = this.getMin(node.right);
                    node.data = _node.data;
                    node.right = removeNode(node.right, data);
                    return node
                }
            } else if (data < node.data) {
                node.left = removeNode(node.left, data);
                return node;
            } else {
                node.right = removeNode(node.right, data);
                return node;
            }
        }

        return removeNode(this.root, data)
    }
}

/***********************************/
// some operation
let datas = [11,7,5,3,6,9,8,10,20,14,12,25,18];
let bst = new BST();
datas.forEach(data => {
    bst.insert(data)
})

console.log(bst.getMax())
console.log(bst.getMin())

 

另一个实例:

class BNode {
    constructor(val) {
        this.value = val;
        this.left = null;
        this.right = null;
    }
}

class BinaryTree {
    constructor() {
        this.root = null;
        this.values = new Array();
    }

    /**
     * insert 插入节点
     * @param {[ type ]} val [description]
     * @return {[ void ]}  [description]
     */
    insert(val) {
        this.values.push(val);
        let node = new BNode(val);
        if (!this.root) {
            this.root = node;
        } else {
            this._insertNode(this.root, node);
        }
    }

    /**
     * _insertNode 递归插入节点
     * @param  {[ BinaryNode ]} node    [父节点]
	 * @param  {[ BinaryNode ]} newNode [新子节点]
     */
    _insertNode(node, newNode) {
        if (newNode.value < node.value) {
            if (node.left === null ){
                node.left = newNode;
            } else {
                this._insertNode(node.left, newNode);
            }
        } else {
            if (node.right === null) {
                node.right = newNode;
            } else {
                this._insertNode(node.right, newNode);
            }
        }
    }

    /**
	 * [inOrderTraverse 中序遍历]
	 * @return {[ Array ]} [description]
     */
    inOrderTraverse() {
        let result = new Array();
        this._inOrderTraverseNode(this.root, node => {
            result.push(node.value);
        })
        return result;
    }

    /**
	 * [_inOrderTraverseNode 中序遍历递归]
	 * @param  {[ BinaryNode ]}   node     [当前节点]
	 * @param  { Function } callback [回调函数]
	 * @return {[ void ]}            [description]
     */
    _inOrderTraverseNode(node, callback) {
        if (node) {
            this._inOrderTraverseNode(node.left, callback);
            callback(node);
            this._inOrderTraverseNode(node.right, callback);
        }
    }

    /**
	 * [preOrderTraverse 先序遍历]
	 * @return {[ Array ]} [description]
     */
    preOrderTraverse() {
        let result = new Array();
        this._preOrderTraverseNode(this.root, node => {
            result.push(node.value);
        })
        return result;
    }

    /**
	 * [_preOrderTraverseNode 先序遍历递归]
	 * @param  {[ BinaryNode ]}   node     [当前节点]
	 * @param  { Function } callback [回调函数]
	 * @return {[ Void ]}            [description]
     */
    _preOrderTraverseNode(node, callback) {
        if (node) {
            callback(node);
            this._preOrderTraverseNode(node.left, callback);
            this._preOrderTraverseNode(node.right, callback);
        }
    }

    /**
	 * [postOrderTraverse 后序遍历]
	 * @return {[Array]} [description]
     */
    postOrderTraverse() {
        let result = new Array();
        this._postOrderTraverseNode(this.root, node => {
            result.push(node.value);
        })
        return result;
    }

    /**
	 * [_postOrderTraverseNode 后序遍历递归]
	 * @param  {[BinaryNode]}   node     [当前节点]
	 * @param  {Function} callback [回调函数]
	 * @return {[type]}            [description]
     */
    _postOrderTraverseNode(node, callback) {
        if (node) {
            this._postOrderTraverseNode(node.left, callback);
            this._postOrderTraverseNode(node.right, callback);
            callback(node);
        }
    }

    /**
	 * [remove 移除指定值]
	 * @param  {[*]} val [目标值]
	 * @return {[ Void ]}     [description]
     */
    remove(val) {
        this.root = this._removeNode(this.root, val);
    }

    /**
	 * [_removeNode 移除节点递归]
	 * @param  {[BinaryNode]} node [当前节点]
	 * @param  {[*]} val  [要移的除节点值]
	 * @return {[BinaryNode]}      [当前节点]
     */
    _removeNode(node, val) {
        if (node === null) return null;
        
        // 递归寻找目标节点
        if (val < node.value) {
            this._removeNode(node.left, val);
            return node;
        }

        if (val > node.value) {
            this._removeNode(node.right, val);
            return node;
        }

        // 找到目标节点
        if (val === node.value) {
            // 是叶子节点 (left\right没有节点)
            if (node.left === null && node.right === null) {
                // 赋值 null, 表示删除
                node = null;
                return node;
            }

            // 只有一个子节点
            if (node.left === null) {
                node = node.right;
                return node;
            }
            if (node.right === null) {
                node = node.left;
                return node;
            }

            // 左右子节点都有
            let min_node = this._findMinNode(node);
            node.value = min_node.value;
            node.right = this._removeNode(node.right, min_node.value);
            return node;
        }
    }

    /**
	 * [_findMinNode 查找最小节点]
	 * @param  {[BinaryNode]} node [当前节点]
	 * @return {[BinaryNode]}      [最小的节点]
     */
    _findMinNode(node) {
        while(node && node.left) {
            node = node.left;
        } 
        return node;
    }

    /**
	 * [search 检索]
	 * @param  {[ * ]} val [被检索值]
	 * @return {[ Boolean ]}     [表示是否存在]
     */
    search(val) {
        let values = this.inOrderTraverse();
        return values.includes(val);
    }

    /**
	 * [min 返回最小值]
	 * @return {[ type ]} 最小值
     */
    min() {
        let values = this.inOrderTraverse();
        return values[0]
    }

    /**
	 * [max 返回最小值]
	 * @return {[ type ]} 最大值
     */
    max() {
        let values = this.inOrderTraverse();
        return values[values.length - 1]
    }

    /**
	 * [isEmpty 是否为空二叉树]
	 * @return {Boolean}
     */

    isEmpty() {
        return this.root === null;
    }

    /**
	 * [breadthFirstSearch 广度优先遍历]
	 * @return {[Array]} [遍历后结果]
	 */
	breadthFirstSearch() {
		let result = new Array();
		let content = new Array();
		let current_node = null;
		content.push(this.root);
		while(content.length) {
			current_node = content.shift();
			result.push(current_node.value);
			if (current_node.right) {
				content.push(current_node.right);
			}
			if (current_node.left) {
				content.push(current_node.left);
			}
		}
		return result;
	}
}

 

posted @ 2019-02-13 09:13  shiweiqianju  阅读(2715)  评论(0编辑  收藏  举报