JS AVL樹(數據結構)- 筆記

Code: 

/**
 * AVL 樹
 * @class
 */
class AVLTree {
    /**
     * @type {TreeNode}
     */
    #root;

    /**
     * @constructor
     */
    constructor() {
        this.#root = null;
    }

    /**
     * 獲取節點高度
     * @param {TreeNode} node 
     */
    height(node) {
        // 空節點高度爲-1
        return node === null ? -1 : node.height;
    }

    /**
     * 更新節點高度
     * @param {TreeNode} node 
     */
    #updateHeight(node) {
        // 當前節點的高度等於最高子樹的高度 + 1
        node.height = Math.max(this.height(node.left), this.height(node.right)) + 1;
    }

    /**
     * 獲取平衡因子
     * @param {TreeNode} node 
     * @returns 
     */
    getBalanceFactor(node) {
        // 空節點平衡因子爲 0 
        if (node === null) {
            return 0;
        }
        // 節點平衡因子 = 左子樹高度 - 右子樹高度
        return this.height(node.left) - this.height(node.right);
    }

    /**
     * 右旋
     * @param {TreeNode} node 
     */
    #rightRotate(node) {
        const child = node.left;
        const grandChild = child.right;
        child.right = node;
        node.left = grandChild;
        this.#updateHeight(node);
        this.#updateHeight(child);

        return child;
    }

    /**
     * 左旋
     * @param {TreeNode} node 
     */
    #leftRotate(node) {
        const child = node.right;
        const grandChild = child.left;
        child.left = node;
        node.right = grandChild;
        this.#updateHeight(node);
        this.#updateHeight(child);

        return child;
    }

    /**
     * 旋轉節點使其平衡
     * @param {TreeNode} node 
     */
    #rotate(node) {
        const factor = this.getBalanceFactor(node);
        // 左偏
        if (factor > 1) {
            // 直接右旋
            if (this.getBalanceFactor(node.left) >= 0) {
                return this.#rightRotate(node);
            }
            // 先左旋後右旋
            node.left = this.#leftRotate(node.left);
            return this.#rightRotate(node);
        }
        // 右偏
        if (factor < -1) {
            // 直接左旋
            if (this.getBalanceFactor(node.right) <= 0) {
                return this.#leftRotate(node.right);
            }
            // 先右旋後左旋
            node.right = this.#rightRotate(node.right);
            return this.#leftRotate(node);
        }

        return node;
    }

    /**
     * 輔助節點的插入
     * @param {TreeNode} node 
     * @param {number} val 
     */
    #insertHelper(node, val) {
        if (node === null) {
            return new TreeNode(val);
        }
        if (val === node.val) {
            return node;
        }
        if (val < node.val) {
            node.left = this.#insertHelper(node.left, val);
        }
        else if (val > node.val) {
            node.right = this.#insertHelper(node.right, val);
        }
        this.#updateHeight(node);
        node = this.#rotate(node);

        return node;
    }

    /**
     * 插入節點
     * @param {number} val 
     */
    insert(val) {
        this.#root = this.#insertHelper(this.#root, val);
    }

    /**
     * 輔助節點的刪除
     * @param {TreeNode} node 
     * @param {number} val 
     */
    #removeHelper(node, val) {
        if (node === null) {
            return null;
        }
        if (val < node.val) {
            node.left = this.#removeHelper(node.left, val);
        }
        else if (val > node.val) {
            node.right = this.#removeHelper(node.right, val);
        }
        else {
            if (node.left === null || node.right === null) {
                const child = node.left === null ? node.right : node.left;
                if (child === null) {
                    return null;
                }
                node = child;
            }
            else {
                let tmp = node.right;
                while(tmp.left !== null) {
                    tmp = tmp.left;
                }
                node.right = this.#removeHelper(node.right, tmp.val);
                node.val = tmp.val;
            }
        }
        this.#updateHeight(node);
        node = this.#rotate(node);

        return node;
    }

    /**
     * 刪除節點
     * @param {number} val 
     */
    remove(val) {
        this.#root = this.#removeHelper(this.#root, val);
    }

    /**
     * 查找節點
     * @param {number} val 
     * @returns 
     */
    search(val) {
        let cur = this.#root;
        while (cur !== null) {
            if (cur.val < val) {
                cur = cur.right;
            }
            else if (cur.val > val) {
                cur = cur.left;
            }
            else {
                break;
            }
        }

        return cur;
    }
}

/**
 * 樹節點
 * @class
 */
class TreeNode {
    val;
    left;
    right;
    height;
    constructor(val, left, right) {
        this.val = val === undefined ? 0 : val;
        this.left = left === undefined ? left : null;
        this.right = right === undefined ? right : null;
        this.height = height === undefined ? 0 : height;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章