Binary Search Tree implementation with unique pointers












0












$begingroup$


I have implemented a binary search tree using templates and unique_ptr in C++ 11. At present, only insertion and deletion are implemented. Please provide your feedback for improvements.



#include <iostream>
#include <memory>


template<typename T>
class Btree {
public:
void insert(T data)
{
_insert(root, data);
}
void traverse(void (*func)(T data))
{
_traverse(root, func);
}
void del(T data)
{
_del(root, data);
}
private:
struct node {
T data;
std::unique_ptr<node> left, right;
node(T data): data(data), left(nullptr), right(nullptr) {}
};

std::unique_ptr<node> root;
void _insert(std::unique_ptr<node>& curr, T data);
void _del(std::unique_ptr<node>& curr, T data);
void _traverse(std::unique_ptr<node>& curr, void (*func)(T data));
T _findmin(std::unique_ptr<node> &curr);
};

template<typename T>
void Btree<T>::_insert(std::unique_ptr<node>& curr, T data)
{
if (curr == nullptr) {
curr.reset(new node(data));
return;
}

if (data < curr->data)
_insert(curr->left, data);
else
_insert(curr->right, data);
}
template<typename T>
T Btree<T>::_findmin(std::unique_ptr<node>& curr)
{
if (curr && curr->left == nullptr)
return curr->data;
return _findmin(curr->left);
}
template<typename T>
void Btree<T>::_del(std::unique_ptr<node>& curr, T data)
{
if (curr == nullptr)
return;
if (data < curr->data)
_del(curr->left, data);
else if (data > curr->data)
_del(curr->right, data);
else {
// if one child is nullptr or both child are nullptr
if (curr->left == nullptr) {
auto &p = curr->right;
curr.reset(p.release());
}
else if (curr->right == nullptr) {
auto &p = curr->left;
curr.reset(p.release());
}
//if child is non leaf node
else {
T temp = _findmin(curr->right);
curr->data = temp;
_del(curr->right, temp);
}
}
}
template<typename T>
void Btree<T>::_traverse(std::unique_ptr<node>& curr, void (*func)(T data))
{
if (curr == nullptr)
return;
_traverse(curr->left, func);
func(curr->data);
_traverse(curr->right, func);
}









share|improve this question











$endgroup$

















    0












    $begingroup$


    I have implemented a binary search tree using templates and unique_ptr in C++ 11. At present, only insertion and deletion are implemented. Please provide your feedback for improvements.



    #include <iostream>
    #include <memory>


    template<typename T>
    class Btree {
    public:
    void insert(T data)
    {
    _insert(root, data);
    }
    void traverse(void (*func)(T data))
    {
    _traverse(root, func);
    }
    void del(T data)
    {
    _del(root, data);
    }
    private:
    struct node {
    T data;
    std::unique_ptr<node> left, right;
    node(T data): data(data), left(nullptr), right(nullptr) {}
    };

    std::unique_ptr<node> root;
    void _insert(std::unique_ptr<node>& curr, T data);
    void _del(std::unique_ptr<node>& curr, T data);
    void _traverse(std::unique_ptr<node>& curr, void (*func)(T data));
    T _findmin(std::unique_ptr<node> &curr);
    };

    template<typename T>
    void Btree<T>::_insert(std::unique_ptr<node>& curr, T data)
    {
    if (curr == nullptr) {
    curr.reset(new node(data));
    return;
    }

    if (data < curr->data)
    _insert(curr->left, data);
    else
    _insert(curr->right, data);
    }
    template<typename T>
    T Btree<T>::_findmin(std::unique_ptr<node>& curr)
    {
    if (curr && curr->left == nullptr)
    return curr->data;
    return _findmin(curr->left);
    }
    template<typename T>
    void Btree<T>::_del(std::unique_ptr<node>& curr, T data)
    {
    if (curr == nullptr)
    return;
    if (data < curr->data)
    _del(curr->left, data);
    else if (data > curr->data)
    _del(curr->right, data);
    else {
    // if one child is nullptr or both child are nullptr
    if (curr->left == nullptr) {
    auto &p = curr->right;
    curr.reset(p.release());
    }
    else if (curr->right == nullptr) {
    auto &p = curr->left;
    curr.reset(p.release());
    }
    //if child is non leaf node
    else {
    T temp = _findmin(curr->right);
    curr->data = temp;
    _del(curr->right, temp);
    }
    }
    }
    template<typename T>
    void Btree<T>::_traverse(std::unique_ptr<node>& curr, void (*func)(T data))
    {
    if (curr == nullptr)
    return;
    _traverse(curr->left, func);
    func(curr->data);
    _traverse(curr->right, func);
    }









    share|improve this question











    $endgroup$















      0












      0








      0





      $begingroup$


      I have implemented a binary search tree using templates and unique_ptr in C++ 11. At present, only insertion and deletion are implemented. Please provide your feedback for improvements.



      #include <iostream>
      #include <memory>


      template<typename T>
      class Btree {
      public:
      void insert(T data)
      {
      _insert(root, data);
      }
      void traverse(void (*func)(T data))
      {
      _traverse(root, func);
      }
      void del(T data)
      {
      _del(root, data);
      }
      private:
      struct node {
      T data;
      std::unique_ptr<node> left, right;
      node(T data): data(data), left(nullptr), right(nullptr) {}
      };

      std::unique_ptr<node> root;
      void _insert(std::unique_ptr<node>& curr, T data);
      void _del(std::unique_ptr<node>& curr, T data);
      void _traverse(std::unique_ptr<node>& curr, void (*func)(T data));
      T _findmin(std::unique_ptr<node> &curr);
      };

      template<typename T>
      void Btree<T>::_insert(std::unique_ptr<node>& curr, T data)
      {
      if (curr == nullptr) {
      curr.reset(new node(data));
      return;
      }

      if (data < curr->data)
      _insert(curr->left, data);
      else
      _insert(curr->right, data);
      }
      template<typename T>
      T Btree<T>::_findmin(std::unique_ptr<node>& curr)
      {
      if (curr && curr->left == nullptr)
      return curr->data;
      return _findmin(curr->left);
      }
      template<typename T>
      void Btree<T>::_del(std::unique_ptr<node>& curr, T data)
      {
      if (curr == nullptr)
      return;
      if (data < curr->data)
      _del(curr->left, data);
      else if (data > curr->data)
      _del(curr->right, data);
      else {
      // if one child is nullptr or both child are nullptr
      if (curr->left == nullptr) {
      auto &p = curr->right;
      curr.reset(p.release());
      }
      else if (curr->right == nullptr) {
      auto &p = curr->left;
      curr.reset(p.release());
      }
      //if child is non leaf node
      else {
      T temp = _findmin(curr->right);
      curr->data = temp;
      _del(curr->right, temp);
      }
      }
      }
      template<typename T>
      void Btree<T>::_traverse(std::unique_ptr<node>& curr, void (*func)(T data))
      {
      if (curr == nullptr)
      return;
      _traverse(curr->left, func);
      func(curr->data);
      _traverse(curr->right, func);
      }









      share|improve this question











      $endgroup$




      I have implemented a binary search tree using templates and unique_ptr in C++ 11. At present, only insertion and deletion are implemented. Please provide your feedback for improvements.



      #include <iostream>
      #include <memory>


      template<typename T>
      class Btree {
      public:
      void insert(T data)
      {
      _insert(root, data);
      }
      void traverse(void (*func)(T data))
      {
      _traverse(root, func);
      }
      void del(T data)
      {
      _del(root, data);
      }
      private:
      struct node {
      T data;
      std::unique_ptr<node> left, right;
      node(T data): data(data), left(nullptr), right(nullptr) {}
      };

      std::unique_ptr<node> root;
      void _insert(std::unique_ptr<node>& curr, T data);
      void _del(std::unique_ptr<node>& curr, T data);
      void _traverse(std::unique_ptr<node>& curr, void (*func)(T data));
      T _findmin(std::unique_ptr<node> &curr);
      };

      template<typename T>
      void Btree<T>::_insert(std::unique_ptr<node>& curr, T data)
      {
      if (curr == nullptr) {
      curr.reset(new node(data));
      return;
      }

      if (data < curr->data)
      _insert(curr->left, data);
      else
      _insert(curr->right, data);
      }
      template<typename T>
      T Btree<T>::_findmin(std::unique_ptr<node>& curr)
      {
      if (curr && curr->left == nullptr)
      return curr->data;
      return _findmin(curr->left);
      }
      template<typename T>
      void Btree<T>::_del(std::unique_ptr<node>& curr, T data)
      {
      if (curr == nullptr)
      return;
      if (data < curr->data)
      _del(curr->left, data);
      else if (data > curr->data)
      _del(curr->right, data);
      else {
      // if one child is nullptr or both child are nullptr
      if (curr->left == nullptr) {
      auto &p = curr->right;
      curr.reset(p.release());
      }
      else if (curr->right == nullptr) {
      auto &p = curr->left;
      curr.reset(p.release());
      }
      //if child is non leaf node
      else {
      T temp = _findmin(curr->right);
      curr->data = temp;
      _del(curr->right, temp);
      }
      }
      }
      template<typename T>
      void Btree<T>::_traverse(std::unique_ptr<node>& curr, void (*func)(T data))
      {
      if (curr == nullptr)
      return;
      _traverse(curr->left, func);
      func(curr->data);
      _traverse(curr->right, func);
      }






      c++ object-oriented c++11 pointers






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 2 hours ago









      1201ProgramAlarm

      3,2932923




      3,2932923










      asked 2 hours ago









      bornfreebornfree

      1623




      1623






















          1 Answer
          1






          active

          oldest

          votes


















          0












          $begingroup$

          Since insert gets its data by value, you're making multiple copies of that data as you navigate down the tree to find where to add the new node. Passing the parameter by const T& (so you only make one copy) would avoid these copies, a benefit for types that are expensive to copy. Another possibility is to use T && to move the data, but this will change the original value being passed in which may be undesirable.



          The value passed to the function called by _traverse is also copied. Depending on your needs, this could also use a const T &, or overloads of _traverse that take func with a reference could be provided. The downside to providing access to the data via a reference is that it can allow that data to be altered.



          If _insert takes curr as a pointer (std::unique_ptr<node>* curr) then you can use a loop rather than recursion. This also applies to _findmin and _del.






          share|improve this answer









          $endgroup$













            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "196"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214882%2fbinary-search-tree-implementation-with-unique-pointers%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0












            $begingroup$

            Since insert gets its data by value, you're making multiple copies of that data as you navigate down the tree to find where to add the new node. Passing the parameter by const T& (so you only make one copy) would avoid these copies, a benefit for types that are expensive to copy. Another possibility is to use T && to move the data, but this will change the original value being passed in which may be undesirable.



            The value passed to the function called by _traverse is also copied. Depending on your needs, this could also use a const T &, or overloads of _traverse that take func with a reference could be provided. The downside to providing access to the data via a reference is that it can allow that data to be altered.



            If _insert takes curr as a pointer (std::unique_ptr<node>* curr) then you can use a loop rather than recursion. This also applies to _findmin and _del.






            share|improve this answer









            $endgroup$


















              0












              $begingroup$

              Since insert gets its data by value, you're making multiple copies of that data as you navigate down the tree to find where to add the new node. Passing the parameter by const T& (so you only make one copy) would avoid these copies, a benefit for types that are expensive to copy. Another possibility is to use T && to move the data, but this will change the original value being passed in which may be undesirable.



              The value passed to the function called by _traverse is also copied. Depending on your needs, this could also use a const T &, or overloads of _traverse that take func with a reference could be provided. The downside to providing access to the data via a reference is that it can allow that data to be altered.



              If _insert takes curr as a pointer (std::unique_ptr<node>* curr) then you can use a loop rather than recursion. This also applies to _findmin and _del.






              share|improve this answer









              $endgroup$
















                0












                0








                0





                $begingroup$

                Since insert gets its data by value, you're making multiple copies of that data as you navigate down the tree to find where to add the new node. Passing the parameter by const T& (so you only make one copy) would avoid these copies, a benefit for types that are expensive to copy. Another possibility is to use T && to move the data, but this will change the original value being passed in which may be undesirable.



                The value passed to the function called by _traverse is also copied. Depending on your needs, this could also use a const T &, or overloads of _traverse that take func with a reference could be provided. The downside to providing access to the data via a reference is that it can allow that data to be altered.



                If _insert takes curr as a pointer (std::unique_ptr<node>* curr) then you can use a loop rather than recursion. This also applies to _findmin and _del.






                share|improve this answer









                $endgroup$



                Since insert gets its data by value, you're making multiple copies of that data as you navigate down the tree to find where to add the new node. Passing the parameter by const T& (so you only make one copy) would avoid these copies, a benefit for types that are expensive to copy. Another possibility is to use T && to move the data, but this will change the original value being passed in which may be undesirable.



                The value passed to the function called by _traverse is also copied. Depending on your needs, this could also use a const T &, or overloads of _traverse that take func with a reference could be provided. The downside to providing access to the data via a reference is that it can allow that data to be altered.



                If _insert takes curr as a pointer (std::unique_ptr<node>* curr) then you can use a loop rather than recursion. This also applies to _findmin and _del.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered 1 hour ago









                1201ProgramAlarm1201ProgramAlarm

                3,2932923




                3,2932923






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f214882%2fbinary-search-tree-implementation-with-unique-pointers%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    How to reconfigure Docker Trusted Registry 2.x.x to use CEPH FS mount instead of NFS and other traditional...

                    is 'sed' thread safe

                    How to make a Squid Proxy server?