通过 POSIX tdelete() 访问节点数据
POSIX 二叉树函数 的联机帮助页包括以下语句:
tdelete()
返回指向已删除项目的父级的指针,如果未找到该项目,则返回NULL
。
tdelete()
释放树中节点所需的内存。用户 负责释放相应数据的内存。
这意味着无法通过 tdelete() 调用访问给定键的节点数据。需要调用 tfind()
(而不是 tsearch()
以免添加给定的键),销毁节点数据,然后调用 < code>tdelete() 使用相同的键从二叉树中删除节点。
我的解释正确吗?有什么办法可以解决我认为这种方法的局限性吗?
- 如果键是堆分配的,则在删除节点之前无法释放它(或使其对正在使用的比较函数无用)。这需要调用 tfind() 获取指向数据的指针,调用 tdelete() 删除节点,然后销毁从 tfind() 检索到的数据调用。
- 需要两次查找才能删除节点并销毁其包含的数据。
The manpage for the POSIX binary tree functions includes the following statements:
tdelete()
returns a pointer to the parent of the item deleted, orNULL
if the item was not found.
tdelete()
frees the memory required for the node in the tree. The user
is responsible for freeing the memory for the corresponding data.
This means that there is no way to get access to a node's data for a given key from a tdelete()
call. One would be required to call tfind()
(rather than tsearch()
so as not to add the given key), perform destruction of the node's data, and then call tdelete()
with the same key to remove the node from the binary tree.
Have I interpreted this correctly? Is there some way around what I perceive to be limitations with this approach?
- If the key is heap-allocated, it can't be freed (or made useless to the comparison function in use) before the node is deleted. This requires calling
tfind()
to obtain a pointer to the data,tdelete()
to remove the node, and then destroying the data retrieved from thetfind()
call. - Two lookups are required to delete a node and destroy it's enclosed data.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
马特,我认为你的解释是正确的。对于单独删除元素来说,这似乎是不可避免的。 (但无论如何,对于 \Omega \log N 成本的操作来说,它只是 2 的一个因素;)
我很长一段时间没有使用这些函数,但通过旧代码,看起来你可以避免部分开销,如果你通过使用两次
twalk
调用一次性销毁树(如果这是您的情况):N
通过适当调用
twalk
为您的树N
的数组指向树项的指针
twalk
填充此数组穿过树
数组并首先对每个树节点
删除其数据,然后删除节点
如果您确实需要这样的东西,
您可以在我们的库中找到这些调用的线程安全 C++ 封装 parXXL 在目录
par/sys
中。Matt, I think that your interpretation is correct. For individual deletion of elements this seems unavoidable. (But anyhow it is only a factor of 2 for an operation of \Omega \log N cost ;)
Long time that I didn't use these function, but looking through old code it looks that you can avoid part of the overhead if you destroy the tree all at once (if this is your case) by using two calls of
twalk
:N
of elements inyour tree with an appropriate call to
twalk
N
ofpointers to tree items
twalk
through the tree
array and for each tree node first
delete its data and then the node
itself
If your really need such a thing you can find a thread safe C++ encapsulation of these calls in our library parXXL in the directory
par/sys
.我以前从未使用过这组功能,但你似乎是正确的。但是,我会尝试使用从 tfind() 返回的指针作为 tdelete() 的 rootp 参数。这将使第二次搜索基本上成为无操作。 AFAICT,数据结构允许将任何节点视为根,因此您可以找到该节点,然后从以您找到的节点为根的子树中删除它。
I've never used this set of functions before, but you appear to be correct. However, I would try using the pointer returned from
tfind()
as therootp
argument totdelete()
. This should make the second search essentially a no-op. AFAICT, the data structure allows any node to be treated as a root so you would find the node and then delete it from the subtree rooted at the node that you found.和 D.Shawley 一样,我以前从未使用过这些函数,所以我编写了一个泄漏内存的小测试程序。
运行它输出
显然“二叉树内部”的值是指向数据的指针的副本。副本由
函数管理,数据应由程序管理。内存
0xcb8030
应该通过调用tdelete()
来释放,相应的0xcb8010
(elem值为0)应该由程序释放(以及之前丢失的0xcb8060
)。Like D.Shawley, I have never used these function before, so I wrote a little test program that leaks memory.
Running it outputs
Apparently the values "inside the binary tree" are copies of pointers to the data. The copies are managed by the
<search.h>
functions and the data should be managed by the program.The memory
0xcb8030
should be freed by a call totdelete()
, the corresponding0xcb8010
(elem with value 0) should be freed by the program (as well as the previously lost0xcb8060
).