-1

Let's suppose we have a RedBlack-Tree implementation which consists of 2 classes:

  • Tree - holds the pointer to the Node *root of the tree and defines all operations over the tree (Insert, Delete, etc)
  • Node - a data storage, which holds pointers to Node *parent, Node *left, Node *right nodes and std::string key.

The Tree::Insert() has the following implementation:

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

Now the task: every node has to store the time of its creation.

Limitations: the base tree implementation should be modified as less as possible and should contain details of specific extensions (so it should know nothing about the creation time property).

My thoughts: extending NodeWithTime : Node and adding unsigned int creation_time property.

Where I'm in stuck: how would we instantiate the node now?

Any proposals?

PS: it's neither a homework or a job task - I'm just learning c++ and data structures.

zerkms
  • 249,484
  • 69
  • 436
  • 539

1 Answers1

1

It's relatively simple. First, the Node struct:

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;
};

A quick helper 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
}

First, I fixed your crappy new and delete and replaced it with smart pointers. Then I also made your tree a template because who needs a tree that can only do one type? Then I swapped out your const T& with a T so that it might live with move-only types.

Then I just added a Time field and called RightNow() in the constructor. The exact TimeType and RightNow() you use depends on your needs and what exactly you mean by "time of it's creation". Are we talking about "6th July, 2013"? Or a very-high-resolution clock? In any case, these "creation time" details do not impact the tree.

Edit: Wait, you want to have one tree type where only some of the nodes know the creation time? Or just to alter the tree so that all the nodes know the creation time? I did #2, but for #1, you could indeed simply inherit from Node. To wit,

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
}
Puppy
  • 144,682
  • 38
  • 256
  • 465
  • 1
    Great answer, but feeling weird for reading how to build a rocket on the question about a skateboard :-) Now will have to go and read about things like `typename... Args` that I see for the first time :-S – zerkms Jul 06 '13 at 12:23
  • @zerkms: The answer *is* about building a skateboard. It's just that the skateboard you suggest will fall apart the instant you stand on it and was painted with lead paint. – Puppy Jul 06 '13 at 12:25
  • `if (IWantToStoreCreationTime)` --- that's what I wanted to avoid. The node should handle that not the tree. The tree should be unaware of what kind of data `Node` (or any its descendants) stores. – zerkms Jul 06 '13 at 12:25
  • I find both of these implementations less than ideal. The first forces a creation time on all users of the tree class. The second will have a `static_cast` somewhere if the user does something like search for a node and then request its creation time, because the pointers of the `NodeWithTime`s are just `Node`s. The only reasonable solution I've found is to use the [curiously recurring template pattern](http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) on the node class. – David Eisenstat Jul 06 '13 at 12:33
  • CRTPing the Node class won't do you any good at all. You still have the same problem- either you guarantee that all nodes store their time, or you have to check at run-time if a particular node does if you want to retrieve that information. If you make that choice at run-time, then the owner of the nodes- that is, the tree- has to make the choice. – Puppy Jul 06 '13 at 13:43
  • @DeadMG I thought it was obvious, but you need to template the tree as well. – David Eisenstat Jul 06 '13 at 20:13