Skip to main content
Rollback to Revision 4
Source Link
Mast
  • 13.5k
  • 12
  • 54
  • 119

First Attempt of Edit:

#ifndef BinaryTree_h
#define BinaryTree_h

#include <iostream>

template <class T>
class BinaryTree {
private:
    struct TreeNode {
        T data;
        std::unique_ptr<TreeNode> left = nullptr;
        std::unique_ptr<TreeNode> right = nullptr;
        TreeNode(T x): data(x){}
    };
    std::unique_ptr<TreeNode> root = nullptr;
    
    // This is used to free the memory
    void deleteTree(std::unique_ptr<TreeNode> &node) {
        if(node.get() == nullptr) {
            return;
        }
        deleteTree(node.get()->left);
        deleteTree(node.get()->right);
        delete node.get();
    }
    
    // This is used for the copy constructor
    void copyTree(std::unique_ptr<TreeNode> &thisRoot, std::unique_ptr<TreeNode> &sourceRoot) {
        if(sourceRoot.get() == nullptr) {
            thisRoot.get() = nullptr;
        }
        else {
            thisRoot.get() = new TreeNode{sourceRoot->data};
            copyTree(thisRoot->left, thisRoot->left);
            copyTree(thisRoot->right, thisRoot->right);
        }
    }
    
    // These functions are for creating the nodes inside the tree
    void insertPrivate(std::unique_ptr<TreeNode> &root, const T &theData);
    void insertPrivate(std::unique_ptr<TreeNode> &root, T &&theData);
    
    // Traversal functions for printing the nodes
    void inorderTraversal(std::unique_ptr<TreeNode> &root);
    void pretorderTraversal(std::unique_ptr<TreeNode> &root);
    void postorderTraversal(std::unique_ptr<TreeNode> &root);
    
public:
    // Constructors
    BinaryTree() = default;                                                       // empty constructor
    BinaryTree(BinaryTree const &other){copyTree(root, other.root);}              // copy constructor
    
    // Rule of 5
    BinaryTree(BinaryTree &&move) noexcept;                                       // move constuctor
    BinaryTree& operator=(BinaryTree &&move) noexcept;                            // move assignment operator
    ~BinaryTree();                                                                // destructor
    
    // Overload operators
    BinaryTree& operator=(BinaryTree const &rhs);
    
    // Member functions
    void insert(const T &theData);
    void insert(T &&theData);
    
    void printInorder();
    void printPreorder();
    void printPostorder();

    void swap(BinaryTree& other) noexcept;
    
};



template <class T>
BinaryTree<T>::BinaryTree(BinaryTree &&move) noexcept {
    move.swap(*this);
}

template <class T>
BinaryTree<T>& BinaryTree<T>::operator=(BinaryTree &&move) noexcept {
    move.swap(*this);
    return *this;
}

template <class T>
BinaryTree<T>::~BinaryTree() {
    deleteTree(root);
}

template <class T>
BinaryTree<T>& BinaryTree<T>::operator=(BinaryTree const &rhs) {
    BinaryTree copy(rhs);
    swap(copy);
    return *this;
}

template <class T>
void BinaryTree<T>::insertPrivate(std::unique_ptr<TreeNode> &root, const T &theData) {
    if(root.get() == nullptr) {
        root.get()->data = theData;
        return;
    }
    else if(theData < root.get()->data) {
        insertPrivate(root.get()->left, theData);
    }
    else {
        insertPrivate(root.get()->right, theData);
    }
}

template <class T>
void BinaryTree<T>::insertPrivate(std::unique_ptr<TreeNode> &root, T &&theData) {
    std::cout << "Using with move" << std::endl;
    if(root.get() == nullptr) {
        root.get() = std::move(theData);
        return;
    }
    else if(theData < root.get()->data) {
        insertPrivate(root.get()->left, std::move(theData));
    }
    else {
        insertPrivate(root.get()->right, std::move(theData));
    }
}

template <class T>
void BinaryTree<T>::insert(const T &theData) {
    insertPrivate(root, theData);
}

template <class T>
void BinaryTree<T>::insert(T &&theData) {
    insertPrivate(root, theData);
}

template <class T>
void BinaryTree<T>::inorderTraversal(std::unique_ptr<TreeNode> &root)  {
    // The items in the left subtree are printed first, followed
    // by the item in the root node, followed by the items in
    // the right subtree.
    if(root.get() != nullptr) {
        inorderTraversal(root.get()->left);
        std::cout << root.get()->data << " ";
        inorderTraversal(root.get()->right);
    }
}

template <class T>
void BinaryTree<T>::pretorderTraversal(std::unique_ptr<TreeNode> &root)  {
    // Print all the items in the tree to which root points.
    // The item in the root is printed first, followed by the
    // items in the left subtree and then the items in the
    // right subtree.
    if(root.get() != nullptr) {
        std::cout << root.get()->data << " ";
        pretorderTraversal(root.get()->left);
        pretorderTraversal(root.get()->right);
    }
}

template <class T>
void BinaryTree<T>::postorderTraversal(std::unique_ptr<TreeNode> &root)  {
    // Print all the items in the tree to which root points.
    // The items in the left subtree are printed first, followed
    // by the items in the right subtree and then the item in the
    // root node.
    if(root.get() != nullptr) {
        postorderTraversal(root.get()->left);
        postorderTraversal(root.get()->right);
        std::cout << root.get()->data << " ";
    }
}

template <class T>
void BinaryTree<T>::printInorder() {
    inorderTraversal(root);
}

template <class T>
void BinaryTree<T>::printPreorder() {
    pretorderTraversal(root);
}

template <class T>
void BinaryTree<T>::printPostorder() {
    postorderTraversal(root);
}

template <class T>
void BinaryTree<T>::swap(BinaryTree &other) noexcept {
    using std::swap;
    swap(root, other.root);
}

#endif /* BinaryTree_h */

First Attempt of Edit:

#ifndef BinaryTree_h
#define BinaryTree_h

#include <iostream>

template <class T>
class BinaryTree {
private:
    struct TreeNode {
        T data;
        std::unique_ptr<TreeNode> left = nullptr;
        std::unique_ptr<TreeNode> right = nullptr;
        TreeNode(T x): data(x){}
    };
    std::unique_ptr<TreeNode> root = nullptr;
    
    // This is used to free the memory
    void deleteTree(std::unique_ptr<TreeNode> &node) {
        if(node.get() == nullptr) {
            return;
        }
        deleteTree(node.get()->left);
        deleteTree(node.get()->right);
        delete node.get();
    }
    
    // This is used for the copy constructor
    void copyTree(std::unique_ptr<TreeNode> &thisRoot, std::unique_ptr<TreeNode> &sourceRoot) {
        if(sourceRoot.get() == nullptr) {
            thisRoot.get() = nullptr;
        }
        else {
            thisRoot.get() = new TreeNode{sourceRoot->data};
            copyTree(thisRoot->left, thisRoot->left);
            copyTree(thisRoot->right, thisRoot->right);
        }
    }
    
    // These functions are for creating the nodes inside the tree
    void insertPrivate(std::unique_ptr<TreeNode> &root, const T &theData);
    void insertPrivate(std::unique_ptr<TreeNode> &root, T &&theData);
    
    // Traversal functions for printing the nodes
    void inorderTraversal(std::unique_ptr<TreeNode> &root);
    void pretorderTraversal(std::unique_ptr<TreeNode> &root);
    void postorderTraversal(std::unique_ptr<TreeNode> &root);
    
public:
    // Constructors
    BinaryTree() = default;                                                       // empty constructor
    BinaryTree(BinaryTree const &other){copyTree(root, other.root);}              // copy constructor
    
    // Rule of 5
    BinaryTree(BinaryTree &&move) noexcept;                                       // move constuctor
    BinaryTree& operator=(BinaryTree &&move) noexcept;                            // move assignment operator
    ~BinaryTree();                                                                // destructor
    
    // Overload operators
    BinaryTree& operator=(BinaryTree const &rhs);
    
    // Member functions
    void insert(const T &theData);
    void insert(T &&theData);
    
    void printInorder();
    void printPreorder();
    void printPostorder();

    void swap(BinaryTree& other) noexcept;
    
};



template <class T>
BinaryTree<T>::BinaryTree(BinaryTree &&move) noexcept {
    move.swap(*this);
}

template <class T>
BinaryTree<T>& BinaryTree<T>::operator=(BinaryTree &&move) noexcept {
    move.swap(*this);
    return *this;
}

template <class T>
BinaryTree<T>::~BinaryTree() {
    deleteTree(root);
}

template <class T>
BinaryTree<T>& BinaryTree<T>::operator=(BinaryTree const &rhs) {
    BinaryTree copy(rhs);
    swap(copy);
    return *this;
}

template <class T>
void BinaryTree<T>::insertPrivate(std::unique_ptr<TreeNode> &root, const T &theData) {
    if(root.get() == nullptr) {
        root.get()->data = theData;
        return;
    }
    else if(theData < root.get()->data) {
        insertPrivate(root.get()->left, theData);
    }
    else {
        insertPrivate(root.get()->right, theData);
    }
}

template <class T>
void BinaryTree<T>::insertPrivate(std::unique_ptr<TreeNode> &root, T &&theData) {
    std::cout << "Using with move" << std::endl;
    if(root.get() == nullptr) {
        root.get() = std::move(theData);
        return;
    }
    else if(theData < root.get()->data) {
        insertPrivate(root.get()->left, std::move(theData));
    }
    else {
        insertPrivate(root.get()->right, std::move(theData));
    }
}

template <class T>
void BinaryTree<T>::insert(const T &theData) {
    insertPrivate(root, theData);
}

template <class T>
void BinaryTree<T>::insert(T &&theData) {
    insertPrivate(root, theData);
}

template <class T>
void BinaryTree<T>::inorderTraversal(std::unique_ptr<TreeNode> &root)  {
    // The items in the left subtree are printed first, followed
    // by the item in the root node, followed by the items in
    // the right subtree.
    if(root.get() != nullptr) {
        inorderTraversal(root.get()->left);
        std::cout << root.get()->data << " ";
        inorderTraversal(root.get()->right);
    }
}

template <class T>
void BinaryTree<T>::pretorderTraversal(std::unique_ptr<TreeNode> &root)  {
    // Print all the items in the tree to which root points.
    // The item in the root is printed first, followed by the
    // items in the left subtree and then the items in the
    // right subtree.
    if(root.get() != nullptr) {
        std::cout << root.get()->data << " ";
        pretorderTraversal(root.get()->left);
        pretorderTraversal(root.get()->right);
    }
}

template <class T>
void BinaryTree<T>::postorderTraversal(std::unique_ptr<TreeNode> &root)  {
    // Print all the items in the tree to which root points.
    // The items in the left subtree are printed first, followed
    // by the items in the right subtree and then the item in the
    // root node.
    if(root.get() != nullptr) {
        postorderTraversal(root.get()->left);
        postorderTraversal(root.get()->right);
        std::cout << root.get()->data << " ";
    }
}

template <class T>
void BinaryTree<T>::printInorder() {
    inorderTraversal(root);
}

template <class T>
void BinaryTree<T>::printPreorder() {
    pretorderTraversal(root);
}

template <class T>
void BinaryTree<T>::printPostorder() {
    postorderTraversal(root);
}

template <class T>
void BinaryTree<T>::swap(BinaryTree &other) noexcept {
    using std::swap;
    swap(root, other.root);
}

#endif /* BinaryTree_h */
added 6653 characters in body
Source Link
Snorrlaxxx
  • 793
  • 4
  • 13

First Attempt of Edit:

#ifndef BinaryTree_h
#define BinaryTree_h

#include <iostream>

template <class T>
class BinaryTree {
private:
    struct TreeNode {
        T data;
        std::unique_ptr<TreeNode> left = nullptr;
        std::unique_ptr<TreeNode> right = nullptr;
        TreeNode(T x): data(x){}
    };
    std::unique_ptr<TreeNode> root = nullptr;
    
    // This is used to free the memory
    void deleteTree(std::unique_ptr<TreeNode> &node) {
        if(node.get() == nullptr) {
            return;
        }
        deleteTree(node.get()->left);
        deleteTree(node.get()->right);
        delete node.get();
    }
    
    // This is used for the copy constructor
    void copyTree(std::unique_ptr<TreeNode> &thisRoot, std::unique_ptr<TreeNode> &sourceRoot) {
        if(sourceRoot.get() == nullptr) {
            thisRoot.get() = nullptr;
        }
        else {
            thisRoot.get() = new TreeNode{sourceRoot->data};
            copyTree(thisRoot->left, thisRoot->left);
            copyTree(thisRoot->right, thisRoot->right);
        }
    }
    
    // These functions are for creating the nodes inside the tree
    void insertPrivate(std::unique_ptr<TreeNode> &root, const T &theData);
    void insertPrivate(std::unique_ptr<TreeNode> &root, T &&theData);
    
    // Traversal functions for printing the nodes
    void inorderTraversal(std::unique_ptr<TreeNode> &root);
    void pretorderTraversal(std::unique_ptr<TreeNode> &root);
    void postorderTraversal(std::unique_ptr<TreeNode> &root);
    
public:
    // Constructors
    BinaryTree() = default;                                                       // empty constructor
    BinaryTree(BinaryTree const &other){copyTree(root, other.root);}              // copy constructor
    
    // Rule of 5
    BinaryTree(BinaryTree &&move) noexcept;                                       // move constuctor
    BinaryTree& operator=(BinaryTree &&move) noexcept;                            // move assignment operator
    ~BinaryTree();                                                                // destructor
    
    // Overload operators
    BinaryTree& operator=(BinaryTree const &rhs);
    
    // Member functions
    void insert(const T &theData);
    void insert(T &&theData);
    
    void printInorder();
    void printPreorder();
    void printPostorder();

    void swap(BinaryTree& other) noexcept;
    
};



template <class T>
BinaryTree<T>::BinaryTree(BinaryTree &&move) noexcept {
    move.swap(*this);
}

template <class T>
BinaryTree<T>& BinaryTree<T>::operator=(BinaryTree &&move) noexcept {
    move.swap(*this);
    return *this;
}

template <class T>
BinaryTree<T>::~BinaryTree() {
    deleteTree(root);
}

template <class T>
BinaryTree<T>& BinaryTree<T>::operator=(BinaryTree const &rhs) {
    BinaryTree copy(rhs);
    swap(copy);
    return *this;
}

template <class T>
void BinaryTree<T>::insertPrivate(std::unique_ptr<TreeNode> &root, const T &theData) {
    if(root.get() == nullptr) {
        root.get()->data = theData;
        return;
    }
    else if(theData < root.get()->data) {
        insertPrivate(root.get()->left, theData);
    }
    else {
        insertPrivate(root.get()->right, theData);
    }
}

template <class T>
void BinaryTree<T>::insertPrivate(std::unique_ptr<TreeNode> &root, T &&theData) {
    std::cout << "Using with move" << std::endl;
    if(root.get() == nullptr) {
        root.get() = std::move(theData);
        return;
    }
    else if(theData < root.get()->data) {
        insertPrivate(root.get()->left, std::move(theData));
    }
    else {
        insertPrivate(root.get()->right, std::move(theData));
    }
}

template <class T>
void BinaryTree<T>::insert(const T &theData) {
    insertPrivate(root, theData);
}

template <class T>
void BinaryTree<T>::insert(T &&theData) {
    insertPrivate(root, theData);
}

template <class T>
void BinaryTree<T>::inorderTraversal(std::unique_ptr<TreeNode> &root)  {
    // The items in the left subtree are printed first, followed
    // by the item in the root node, followed by the items in
    // the right subtree.
    if(root.get() != nullptr) {
        inorderTraversal(root.get()->left);
        std::cout << root.get()->data << " ";
        inorderTraversal(root.get()->right);
    }
}

template <class T>
void BinaryTree<T>::pretorderTraversal(std::unique_ptr<TreeNode> &root)  {
    // Print all the items in the tree to which root points.
    // The item in the root is printed first, followed by the
    // items in the left subtree and then the items in the
    // right subtree.
    if(root.get() != nullptr) {
        std::cout << root.get()->data << " ";
        pretorderTraversal(root.get()->left);
        pretorderTraversal(root.get()->right);
    }
}

template <class T>
void BinaryTree<T>::postorderTraversal(std::unique_ptr<TreeNode> &root)  {
    // Print all the items in the tree to which root points.
    // The items in the left subtree are printed first, followed
    // by the items in the right subtree and then the item in the
    // root node.
    if(root.get() != nullptr) {
        postorderTraversal(root.get()->left);
        postorderTraversal(root.get()->right);
        std::cout << root.get()->data << " ";
    }
}

template <class T>
void BinaryTree<T>::printInorder() {
    inorderTraversal(root);
}

template <class T>
void BinaryTree<T>::printPreorder() {
    pretorderTraversal(root);
}

template <class T>
void BinaryTree<T>::printPostorder() {
    postorderTraversal(root);
}

template <class T>
void BinaryTree<T>::swap(BinaryTree &other) noexcept {
    using std::swap;
    swap(root, other.root);
}

#endif /* BinaryTree_h */

First Attempt of Edit:

#ifndef BinaryTree_h
#define BinaryTree_h

#include <iostream>

template <class T>
class BinaryTree {
private:
    struct TreeNode {
        T data;
        std::unique_ptr<TreeNode> left = nullptr;
        std::unique_ptr<TreeNode> right = nullptr;
        TreeNode(T x): data(x){}
    };
    std::unique_ptr<TreeNode> root = nullptr;
    
    // This is used to free the memory
    void deleteTree(std::unique_ptr<TreeNode> &node) {
        if(node.get() == nullptr) {
            return;
        }
        deleteTree(node.get()->left);
        deleteTree(node.get()->right);
        delete node.get();
    }
    
    // This is used for the copy constructor
    void copyTree(std::unique_ptr<TreeNode> &thisRoot, std::unique_ptr<TreeNode> &sourceRoot) {
        if(sourceRoot.get() == nullptr) {
            thisRoot.get() = nullptr;
        }
        else {
            thisRoot.get() = new TreeNode{sourceRoot->data};
            copyTree(thisRoot->left, thisRoot->left);
            copyTree(thisRoot->right, thisRoot->right);
        }
    }
    
    // These functions are for creating the nodes inside the tree
    void insertPrivate(std::unique_ptr<TreeNode> &root, const T &theData);
    void insertPrivate(std::unique_ptr<TreeNode> &root, T &&theData);
    
    // Traversal functions for printing the nodes
    void inorderTraversal(std::unique_ptr<TreeNode> &root);
    void pretorderTraversal(std::unique_ptr<TreeNode> &root);
    void postorderTraversal(std::unique_ptr<TreeNode> &root);
    
public:
    // Constructors
    BinaryTree() = default;                                                       // empty constructor
    BinaryTree(BinaryTree const &other){copyTree(root, other.root);}              // copy constructor
    
    // Rule of 5
    BinaryTree(BinaryTree &&move) noexcept;                                       // move constuctor
    BinaryTree& operator=(BinaryTree &&move) noexcept;                            // move assignment operator
    ~BinaryTree();                                                                // destructor
    
    // Overload operators
    BinaryTree& operator=(BinaryTree const &rhs);
    
    // Member functions
    void insert(const T &theData);
    void insert(T &&theData);
    
    void printInorder();
    void printPreorder();
    void printPostorder();

    void swap(BinaryTree& other) noexcept;
    
};



template <class T>
BinaryTree<T>::BinaryTree(BinaryTree &&move) noexcept {
    move.swap(*this);
}

template <class T>
BinaryTree<T>& BinaryTree<T>::operator=(BinaryTree &&move) noexcept {
    move.swap(*this);
    return *this;
}

template <class T>
BinaryTree<T>::~BinaryTree() {
    deleteTree(root);
}

template <class T>
BinaryTree<T>& BinaryTree<T>::operator=(BinaryTree const &rhs) {
    BinaryTree copy(rhs);
    swap(copy);
    return *this;
}

template <class T>
void BinaryTree<T>::insertPrivate(std::unique_ptr<TreeNode> &root, const T &theData) {
    if(root.get() == nullptr) {
        root.get()->data = theData;
        return;
    }
    else if(theData < root.get()->data) {
        insertPrivate(root.get()->left, theData);
    }
    else {
        insertPrivate(root.get()->right, theData);
    }
}

template <class T>
void BinaryTree<T>::insertPrivate(std::unique_ptr<TreeNode> &root, T &&theData) {
    std::cout << "Using with move" << std::endl;
    if(root.get() == nullptr) {
        root.get() = std::move(theData);
        return;
    }
    else if(theData < root.get()->data) {
        insertPrivate(root.get()->left, std::move(theData));
    }
    else {
        insertPrivate(root.get()->right, std::move(theData));
    }
}

template <class T>
void BinaryTree<T>::insert(const T &theData) {
    insertPrivate(root, theData);
}

template <class T>
void BinaryTree<T>::insert(T &&theData) {
    insertPrivate(root, theData);
}

template <class T>
void BinaryTree<T>::inorderTraversal(std::unique_ptr<TreeNode> &root)  {
    // The items in the left subtree are printed first, followed
    // by the item in the root node, followed by the items in
    // the right subtree.
    if(root.get() != nullptr) {
        inorderTraversal(root.get()->left);
        std::cout << root.get()->data << " ";
        inorderTraversal(root.get()->right);
    }
}

template <class T>
void BinaryTree<T>::pretorderTraversal(std::unique_ptr<TreeNode> &root)  {
    // Print all the items in the tree to which root points.
    // The item in the root is printed first, followed by the
    // items in the left subtree and then the items in the
    // right subtree.
    if(root.get() != nullptr) {
        std::cout << root.get()->data << " ";
        pretorderTraversal(root.get()->left);
        pretorderTraversal(root.get()->right);
    }
}

template <class T>
void BinaryTree<T>::postorderTraversal(std::unique_ptr<TreeNode> &root)  {
    // Print all the items in the tree to which root points.
    // The items in the left subtree are printed first, followed
    // by the items in the right subtree and then the item in the
    // root node.
    if(root.get() != nullptr) {
        postorderTraversal(root.get()->left);
        postorderTraversal(root.get()->right);
        std::cout << root.get()->data << " ";
    }
}

template <class T>
void BinaryTree<T>::printInorder() {
    inorderTraversal(root);
}

template <class T>
void BinaryTree<T>::printPreorder() {
    pretorderTraversal(root);
}

template <class T>
void BinaryTree<T>::printPostorder() {
    postorderTraversal(root);
}

template <class T>
void BinaryTree<T>::swap(BinaryTree &other) noexcept {
    using std::swap;
    swap(root, other.root);
}

#endif /* BinaryTree_h */
edited tags; edited title
Link
hoffmale
  • 6.5k
  • 17
  • 41

Generic Binary Tree using Linked List in C++

edited title
Link
Snorrlaxxx
  • 793
  • 4
  • 13
Loading
added 20 characters in body
Source Link
Snorrlaxxx
  • 793
  • 4
  • 13
Loading
Source Link
Snorrlaxxx
  • 793
  • 4
  • 13
Loading