【问题标题】:Extending classes and instantiation扩展类和实例化
【发布时间】:2013-07-04 09:03:47
【问题描述】:

假设我们有一个由 2 个类组成的 RedBlack-Tree 实现:

  • Tree - 保存指向树的Node *root 的指针并定义树上的所有操作(InsertDelete 等)
  • Node - 一个数据存储,它保存指向Node *parentNode *leftNode *right 节点和std::string key 的指针。

Tree::Insert() 具有以下实现:

void Tree::Insert(const std::string &key)
{
    Node *z = new Node(key);
    // adding node logic
}

现在的任务:每个节点都必须存储它的创建时间。

限制:基树实现应尽可能少地修改,并应包含特定扩展的详细信息(因此它应该对创建时间属性一无所知)。

我的想法:扩展 NodeWithTime : Node 并添加 unsigned int creation_time 属性。

我陷入了困境:我们现在如何实例化节点?

有什么建议吗?

PS:这既不是家庭作业也不是工作任务——我只是在学习 c++ 和数据结构。

【问题讨论】:

  • “扩展”是 Java 术语。在 C++ 中,您从一个类派生

标签: c++ algorithm tree application-design red-black-tree


【解决方案1】:

比较简单。一、Node结构:

template<typename T> struct Node {
    Node(T t) : value(std::move(t)), time(RightNow()) {}
    T value;
    TimeType time;
    std::unique_ptr<Node> left;
    std::unique_ptr<Node> right;
};

快速帮手make_unique:

template<typename T, typename... Args> std::unique_ptr<T> make_unique(Args&&... args) {
    return std::unique_ptr<T>(new T(std::forward<Args>(args...)));
}
template<typename T> void Tree<T>::Insert(T key) {
    auto z = make_unique<Node<T>>(std::move(key));
    // insert
}

首先,我修复了你糟糕的 newdelete 并用智能指针替换了它。然后我还把你的树作为模板,因为谁需要只能做一种类型的树?然后我用T 替换了你的const T&amp;,这样它就可以与仅移动类型一起使用。

然后我只是添加了一个 Time 字段并在构造函数中调用了 RightNow()。您使用的确切 TimeType 和 RightNow() 取决于您的需求以及“创建时间”的确切含义。我们是在谈论“2013 年 7 月 6 日”吗?还是一个非常高分辨率的时钟?在任何情况下,这些“创建时间”细节都不会影响树。

编辑:等等,你想要一种只有部分节点知道创建时间的树类型?或者只是为了改变树以便所有节点知道创建时间?我做了 #2,但对于 #1,你确实可以简单地从 Node.js 继承。也就是说,

template<typename T> struct Node {
    Node(T t) : value(std::move(t)) {}
    T value;
    std::unique_ptr<Node> left;
    std::unique_ptr<Node> right;
};
template<typename T> struct NodeWithTime : Node<T> {
    TimeType time;
    NodeWithTime(T t) : Node(std::move(t)), time(RightNow()) {}
};
template<typename T> void Tree<T>::insert(T t) {
    std::unique_ptr<Node> nodeptr;
    if (IWantToStoreCreationTime)
        nodeptr = make_unique<NodeWithTime<T>>(std::move(t));
    else
        nodeptr = make_unique<Node>(std::move(t));
    // insert
}

【讨论】:

  • 很好的答案,但是在关于滑板的问题上阅读如何建造火箭感觉很奇怪:-) 现在必须去阅读我第一次看到的 typename... Args 之类的东西:-S
  • @zerkms:答案关于制作滑板。只是你推荐的滑板一站上去就散架了,涂了铅漆。
  • if (IWantToStoreCreationTime) --- 这就是我想要避免的。节点应该处理它而不是树。树应该不知道Node(或其任何后代)存储了什么样的数据。
  • 我发现这两种实现都不理想。第一个强制树类的所有用户创建时间。如果用户执行诸如搜索节点然后请求其创建时间之类的操作,则第二个将在某处有一个static_cast,因为NodeWithTime&lt;T&gt;s 的指针只是Node&lt;T&gt;s。我找到的唯一合理的解决方案是在节点类上使用curiously recurring template pattern
  • CRTPing Node 类对你没有任何好处。你仍然有同样的问题——要么保证所有节点都存储它们的时间,要么如果你想检索该信息,你必须在运行时检查特定节点是否存在。如果您在运行时做出选择,那么节点的所有者(即树)必须做出选择。
猜你喜欢
  • 2010-12-14
  • 2021-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-16
  • 2013-05-24
  • 2016-06-19
相关资源
最近更新 更多