【问题标题】:[Ask for some hints]Inserting a sorted array into a constructed BST【求一些提示】将排序后的数组插入到构造的BST中
【发布时间】:2021-01-21 19:44:37
【问题描述】:

我有一个家庭作业问题,想提出一个有效的算法,将具有 m 个元素的排序数组插入到具有 n 个元素的(n 个不平衡)二叉搜索树中,这样总运行时间是 O(m+n) 而不是m*O(n)。苦苦挣扎了很久,还是没有一个明确的问题方向,所以写这篇文章是想问问有没有可能的提示。

【问题讨论】:

    标签: arrays algorithm insert runtime binary-search-tree


    【解决方案1】:

    您可以使用以下算法:

    1. 对 BST 中的节点进行中序遍历,并保留对本次遍历中访问的上一个节点的引用。这个前一个节点以空值开始。保持以下不变量:要么当前节点没有左子节点,然后前一个节点为空或祖先,要么当前节点有一个左子节点,前一个节点是后代。

    2. 当排序数组中的下一个值小于当前节点时,则为该数组值插入一个新节点作为当前节点的左孩子(当它没有左孩子时)或作为当前节点的右孩子前一个节点(当当前节点有左孩子时)。使新创建的节点成为“上一个”节点。增加数组中的索引,并重复此步骤,直到排序后的数组中的下一个值不小于当前节点。

    3. 从中序遍历中获取下一对(前一个,当前)并重复步骤2,直到中序遍历完成或所有数组值都已插入

    4. 如果还有数组值,则将它们追加到中序遍历中找到的最后一个节点的右侧,始终向右加深...

    这是一个 JavaScript 实现:

    class Node {
        constructor(val) {
            this.val = val;
            this.next = null;
        }
        add(val) {
            if (val < this.val) {
                if (!this.left) this.left = new Node(val);
                else this.left.add(val);
            } else {
                if (!this.right) this.right = new Node(val);
                else this.right.add(val);
            }
        }
        * inorder() {  // recursive
            if (this.left) yield * this.left.inorder();
            yield this;
            if (this.right) yield * this.right.inorder();
        }
        addSorted(arr) {
            let i = 0; // index in arr
            let prev = null; // follows behind node
            for (let node of this.inorder()) {
                while (arr[i] < node.val) {
                    if (!node.left) prev = node.left = new Node(arr[i++]); 
                    else prev = prev.right = new Node(arr[i++]);
                    if (i >= arr.length) return;
                }
                prev = node;
            }
            while (i < arr.length) {
                prev = prev.right = new Node(arr[i++]);
            }
        }
    }
    
    // Demo
    // Initialise tree and print the inorder traversal
    let root = new Node(40);
    for (let i of [30, 70, 20, 35, 60, 80, 5, 55]) root.add(i);
    for (let node of root.inorder()) console.log(node.val);
    
    // Apply the algorithm for adding a sorted list of values
    root.addSorted([1, 2, 8, 22, 38, 39, 43, 50, 51, 59, 72, 100]);
    console.log("after having added sorted array:");
    for (let node of root.inorder()) console.log(node.val);

    【讨论】:

    • 感谢您的解释,我确实了解该算法的想法,但我担心运行时间是否为 O(n+m),因为每次插入新元素时都会调用 in-order walk ?
    • 有序步行继续从它原来的位置。我使用了一个迭代器。所以总共只有一个完整的树遍历
    猜你喜欢
    • 1970-01-01
    • 2019-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-04
    • 1970-01-01
    • 2018-03-22
    • 1970-01-01
    相关资源
    最近更新 更多