1

I have a binary search tree implementation where each node of the tree has this structure.

struct node {
        T data;
        std::unique_ptr<node> left, right;
        node(T data): data(data), left(nullptr), right(nullptr) {}
    };

I have implemented a findmin routine that returns the minimum data(left most node's data), given the root of the tree. At present, I have implemented it recursively.

template<typename T>
T Btree<T>::_findmin(std::unique_ptr<node>& curr)
{
    if (curr && curr->left == nullptr)
        return curr->data;
    return _findmin(curr->left);    
}

This works but I would like to implement it iteratively. For a normal pointer, we can assign and then keep traversing the leftmost node curr = curr->left , but such an assignment won't work for unique_ptr.

Is there a way to implement it iteratively?

bornfree
  • 2,308
  • 1
  • 23
  • 33
  • 4
    unique_ptr transfers ownership. You can still have a native pointer to node for iteration: _findmin(const node* curr) instead of _findmin(std::unique_ptr). Use unique_ptr::get() to attain a non-owning pointer. – Maikel May 07 '19 at 05:57

1 Answers1

6

The problem with your current function is that it takes a reference. We can't directly transform it to a loop because you can't reseat a reference (= make it point somewhere else).

However, we can do it with a pointer! We just have to add * every time we use it.

template<typename T>
T Btree<T>::_findmin(std::unique_ptr<node> &root)
{
    std::unique_ptr<node> *curr = &root;
    while (true) {
        if (*curr && (*curr)->left == nullptr)
            return (*curr)->data;
        curr = &(*curr)->left;
    }
}

And there you have it: An iterative version of your function, bugs and all.

We can get rid of one level of indirection by taking advantage of one of unique_ptr's methods, get():

template<typename T>
T Btree<T>::_findmin(std::unique_ptr<node> &root)
{
    node *curr = root.get();
    while (true) {
        if (curr && curr->left == nullptr)
            return curr->data;
        curr = curr->left.get();
    }
}

Instead of operating on top of the smart pointer wrappers, we simply get the contents and use the raw underlying pointers.

melpomene
  • 84,125
  • 8
  • 85
  • 148