【问题标题】:Design of API's for data structures and algorithms数据结构和算法的API设计
【发布时间】:2014-07-24 22:32:29
【问题描述】:

我最近实现了二叉搜索树、链表等作为学习练习。 II 实现了几个 API,如插入、删除等。 例如,插入节点 API 看起来像

 void insertNode(Node** root, Node* node)

应用程序将为要插入的节点分配内存。即节点并分配值/键并传递给此函数。

1) 我的问题是这是否是正确的方法?还是应用程序只需要将值/键传递给 insertNode 函数,然后这个函数分配内存?

  i.e void insertNode(Node** root, int key)
      {
            malloc for node here
      }

2) 什么是好的设计实践——应用程序处理分配内存和空闲还是这个 API 库?

谢谢

【问题讨论】:

  • 为什么 root 是一个节点**?你修改根目录吗?
  • 这个想法是在根目录中添加新节点并从中删除。所以这种方式根被修改。所以我想传递一个参考。

标签: c binary-search-tree


【解决方案1】:

一般原则:

  1. 分配内存的人也应该有责任将其删除。
  2. 让客户的工作尽可能简单
  3. 考虑线程安全

所以,不要让客户端分配由树管理的内存。但是,我们需要仔细考虑 find 或 search 应该返回什么。

您可以查看示例代码以了解其他人对收集 API 采取的政策。对于example

在传递过程中,您的根目录不需要双指针。

如果某人的 root 指向一个对象 { left -> ..., right -> ...} 那么如果你将 root 作为 Node* 传递,你的代码就可以编写

 root->left = newValue;

您正在修改 root 指向的内容,而不是 root 本身。通过传递双指针,您可以完全重新定位结构,因为有人可以写:

 *root = completelyNewTree

我怀疑你的意图。

现在对于插入,我建议传入新值,但让集合分配空间并复制它。该集合现在可以完全控制它所保存的数据,并且它返回的任何内容都应该被复制。我们不希望客户端直接弄乱树(线程安全)。

这意味着对于查找的结果,调用者必须预先分配一个缓冲区,或者我们必须清楚地记录该集合正在返回调用者必须删除的已分配副本。

是的,使用任何垃圾收集语言都要容易得多

【讨论】:

  • 从你发送的代码来看,API实际上是根据键值分配和释放的。
  • 在插入时调用 node_make() 并将调用者的数据复制到分配的结构中。我认为与我上面所说的没有任何矛盾。
猜你喜欢
  • 1970-01-01
  • 2022-01-20
  • 1970-01-01
  • 2012-01-25
  • 1970-01-01
  • 1970-01-01
  • 2022-06-20
  • 1970-01-01
  • 2013-02-13
相关资源
最近更新 更多