- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
引用 Wikipedia :
It is perfectly acceptable to use a traditional binary tree data structure to implement a binary heap. There is an issue with finding the adjacent element on the last level on the binary heap when adding an element which can be resolved algorithmically...
@Yse: is your question "How do I find the last element of a binary heap"?
Is there some context in which you're asking this question? (i.e., is there some concrete problem you're trying to solve?)
It seems most understandable to me to just use a normal binary tree structure (using a pRoot and Node defined as [data, pLeftChild, pRightChild]) and add two additional pointers (pInsertionNode and pLastNode). pInsertionNode and pLastNode will both be updated during the insertion and deletion subroutines to keep them current when the data within the structure changes. This gives O(1) access to both insertion point and last node of the structure.
How about performing a depth-first search...
最佳答案
基本上,引用的语句是指解决在堆中插入和删除数据元素的位置的问题。为了保持二叉堆的“形状属性”,堆的最低层必须始终从左到右填充,不留空节点。为了保持二叉堆的平均 O(1) 插入和删除时间,您必须能够确定下一次插入的位置以及用于删除根节点的最低级别上最后一个节点的位置,两者都在恒定的时间内。
对于存储在数组中的二进制堆(其隐式的、压缩的数据结构,如维基百科条目中所述),这很容易。只需在数组末尾插入最新的数据成员,然后将其“冒泡”到位(遵循堆规则)。或者用数组“冒泡”中的最后一个元素替换根以进行删除。对于数组存储中的堆,堆中元素的数量是一个隐式指针,指向要插入下一个数据元素的位置以及查找最后一个用于删除的元素的位置。
对于存储在树结构中的二叉堆,这个信息没有那么明显,但是因为是完全二叉树,所以可以计算出来。例如,在具有 4 个元素的完整二叉树中,插入点将始终是根节点左 child 的右 child 。用于删除的节点将始终是根节点的左 child 的左 child 。对于任何给定的任意树大小,树将始终具有特定形状,并具有明确定义的插入和删除点。因为树是一个“完全二叉树”,对于任何给定的大小都有特定的结构,所以很可能在 O(1) 时间内计算插入/删除的位置。然而,问题是即使您知道它在结构上的位置,您也不知道该节点在内存中的位置。因此,您必须遍历树才能到达给定的节点,该节点是一个 O(log n) 过程,使所有插入和删除操作都至少为 O(log n),打破了通常所需的 O(1) 行为。由于注意到的遍历问题,任何搜索(“深度优先”或其他搜索)也将至少为 O(log n),并且由于半排序堆的随机性,通常为 O(n)。
诀窍是通过扩充数据结构(“线程化”树,如维基百科文章中所述)或使用额外的指针,能够在恒定时间内计算和引用这些插入/删除点。
在我看来最容易理解的实现是只使用普通的简单二叉树结构(使用定义为 [data, pParent, pLeftChild, pRightChild] 的 pRoot 和 Node)和添加两个额外的指针(pInsert 和 pLastNode)。 pInsert 和 pLastNode 都将在插入和删除子例程期间更新,以在结构中的数据更改时保持它们最新。此实现使 O(1) 访问结构的插入点和最后一个节点,并且应该允许在插入和删除中保留整体 O(1) 行为。实现的成本是插入/删除子例程中的两个额外指针和一些次要的额外代码(又名,最小)。
编辑 : 为 O(1) insert() 添加伪代码
这是插入子例程的伪代码,平均为 O(1):
define Node = [T data, *pParent, *pLeft, *pRight]
void insert(T data)
{
do_insertion( data ); // do insertion, update count of data items in tree
# assume: pInsert points node location of the tree that where insertion just took place
# (aka, either shuffle only data during the insertion or keep pInsert updated during the bubble process)
int N = this->CountOfDataItems + 1; # note: CountOfDataItems will always be > 0 (and pRoot != null) after an insertion
p = new Node( <null>, null, null, null); // new empty node for the next insertion
# update pInsert (three cases to handle)
if ( int(log2(N)) == log2(N) )
{# #1 - N is an exact power of two
# O(log2(N))
# tree is currently a full complete binary tree ("perfect")
# ... must start a new lower level
# traverse from pRoot down tree thru each pLeft until empty pLeft is found for insertion
pInsert = pRoot;
while (pInsert->pLeft != null) { pInsert = pInsert->pLeft; } # log2(N) iterations
p->pParent = pInsert;
pInsert->pLeft = p;
}
else if ( isEven(N) )
{# #2 - N is even (and NOT a power of 2)
# O(1)
p->pParent = pInsert->pParent;
pInsert->pParent->pRight = p;
}
else
{# #3 - N is odd
# O(1)
p->pParent = pInsert->pParent->pParent->pRight;
pInsert->pParent->pParent->pRight->pLeft = p;
}
pInsert = p;
// update pLastNode
// ... [similar process]
}
关于algorithm - 查找二叉堆的最后一个元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/500057/
这个问题在这里已经有了答案: “return” and “try-catch-finally” block evaluation in scala (2 个回答) 7年前关闭。 为什么method1返
我有一个动态列表,需要选择最后一项之前的项目。 drag your favorites here var lastLiId = $(".album
我想为每个线程执行特定操作,因此,我认为tearDown Thread Group 不起作用。 是否有任何替代方法可以仅在线程的最后一次迭代时运行“仅一次 Controller ”? 谢谢。 最佳答案
在我的书中它使用了这样的东西: for($ARGV[0]) { Expression && do { print "..."; last; }; ... } for 循环不完整吗?另外,do 的意义何
我想为每个线程执行特定操作,因此,我认为tearDown Thread Group 不起作用。 是否有任何替代方法可以仅在线程的最后一次迭代时运行“仅一次 Controller ”? 谢谢。 最佳答案
有没有可能 finally 不会被调用但应用程序仍在运行? 我在那里释放信号量 finally { _semParallelUpdates.Re
我收藏了 对齐的元素,以便它们形成两列。使用 nth-last-child 的组合和 nth-child(even) - 或任何其他选择器 - 是否可以将样式应用于以下两者之一:a)最后两个(假设
我正在阅读 Jon Skeet 的 C# in Depth . 在第 156 页,他有一个示例, list 5.13“使用多个委托(delegate)捕获多个变量实例化”。 List list = n
我在 AM4:AM1000 范围内有一个数据列表(从上到下有间隙),它总是被添加到其中,我想在其中查找和总结最后 4 个结果。但我只想找到与单独列相对应的结果,范围 AL4:AL1000 等于单元格
我最近编写了一个运行良好的 PowerShell 脚本 - 然而,我现在想升级该脚本并添加一些错误检查/处理 - 但我似乎被第一个障碍难住了。为什么下面的代码不起作用? try { Remove-
这个问题在这里已经有了答案: Why does "a == x or y or z" always evaluate to True? How can I compare "a" to all of
使用 Django 中这样的模型,如何检索 30 天的条目并计算当天添加的条目数。 class Entry(models.Model): ... entered = models.Da
我有以下代码。 public static void main(String[] args) { // TODO Auto-generated method stub
这个问题在这里已经有了答案: Why does "a == x or y or z" always evaluate to True? How can I compare "a" to all of
这个问题已经有答案了: Multiple returns: Which one sets the final return value? (7 个回答) 已关闭 8 年前。 我正在经历几个在工作面试中
$ cat n2.txt apn,date 3704-156,11/04/2019 3704-156,11/22/2019 5515-004,10/23/2019 3732-231,10/07/201
我可以在 C/C++ 中设置/禁用普通数组最后几个元素的读(或写)访问权限吗?由于我无法使用其他进程的内存,我怀疑这是可能的,但如何实现呢?我用谷歌搜索但找不到。 如果可以,怎样做? 因为我想尝试这样
我想使用在这里找到的虚拟键盘组件 http://www.codeproject.com/KB/miscctrl/touchscreenkeyboard.aspx就像 Windows 中的屏幕键盘 (O
我正在运行一个 while 循环来获取每个对话的最新消息,但是我收到了错误 [18-Feb-2012 21:14:59] PHP Warning: mysql_fetch_array(): supp
这个问题在这里已经有了答案: How to get the last day of the month? (44 个答案) 关闭 8 年前。 这是我在这里的第一篇文章,所以如果我做错了请告诉我...
我是一名优秀的程序员,十分优秀!