如何解决[询问一些提示]将已排序的数组插入构造的BST中
我有一个作业问题,想出一种有效的算法,将具有m个元素的排序数组插入具有n个元素的(n个不平衡)二叉搜索树中,这样总运行时间为O(m + n)而不是m * O(n)。由于我已经苦苦挣扎了很长时间,但是仍然没有明确的方向,我写这篇文章来询问是否可以给出提示。
解决方法
您可以使用以下算法:
-
对BST中的节点执行有序遍历,并保留对该遍历中访问过的先前节点的引用。上一个节点从null开始。保持以下不变式:当前节点没有左子节点,然后前一个节点为null或祖先,或者当前节点有左子节点,而前一个节点是后代。
-
当排序数组中的下一个值小于当前节点时,请为此数组值插入一个新节点作为当前节点的左子节点(如果没有左子节点)或右节点前一个节点的子节点(当当前节点有左子节点时)。将新创建的节点设为“上一个”节点。递增数组中的索引,然后重复此步骤,直到排序后的数组中的下一个值不小于当前节点。
-
从有序遍历中获取下一对(上一个,当前),并重复步骤2直到有序遍历完成或已插入所有数组值
-
如果仍然存在数组值,则将它们附加到顺序遍历中找到的最后一个节点的右侧,并始终向右加深...
这是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);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。