From ed22884993445c0cea9bbc213629ee82e4fe0562 Mon Sep 17 00:00:00 2001 From: Gajanan Choudhary Date: Sun, 9 Aug 2020 01:53:45 -0500 Subject: [PATCH] Add templated Binary search tree with unit tests --- include/bst.h | 319 +++++++++++++++++++++++++++++++++++++ tests/CMakeLists.txt | 3 +- tests/test_bst.cpp | 370 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 691 insertions(+), 1 deletion(-) create mode 100644 include/bst.h create mode 100644 tests/test_bst.cpp diff --git a/include/bst.h b/include/bst.h new file mode 100644 index 0000000..e6815ce --- /dev/null +++ b/include/bst.h @@ -0,0 +1,319 @@ +#pragma once + +#include +#include"debugmacro.h" +#define BST BinarySearchTree + +/******************************************************************************/ +//! \brief Class defining a singly-linked binary search tree. +template +class BST { + public: + + /** Class methods. */ + + //! \brief Constructor for BST object. + BST() : root(nullptr) { + DEBUG_MSG("BST:: Parametrized C'tor called"); + } + + //! \brief Copy Constructor for BST object. + BST(const BST &other) : BST() { + DEBUG_MSG("BST:: Copy C'tor called"); + if (other.root){ + DEBUG_MSG("BST:: Copying the root node"); + //root = new BST::Node(other.root->left, other.root->right, other.root->data); + root = new Node(*(other.root)); + DEBUG_MSG("BST:: Finished copying the tree"); + } + else{ + DEBUG_MSG("BST:: other tree appears too be empty. Nothing to be copied."); + } + } + + //! \brief Move Constructor for BST object. + BST(BST &&other) : BST(){ + DEBUG_MSG("BST:: Move C'tor called"); + swap(*this, other); + DEBUG_MSG("BST:: Finished swapping"); + } + + //! \brief Destructor for BST object. + ~BST(){ + DEBUG_MSG("BST:: D'tor called"); + delete root; + } + + /** Overloaded operators for the class. */ + + //! \brief assignment operator. + BST & operator =(BST other){ + DEBUG_MSG("BST:: Assignment operator called"); + swap(*this, other); + return *this; + } + + /** Friend functions. */ + + //! \brief Displays the binary search tree. + template + friend std::ostream& operator<<(std::ostream& os, const BST &); + + //! \brief Displays the data in the Node. + template + friend std::ostream& operator<<(std::ostream&, const typename BST::Node *); + + //! \brief Swap function. + template + friend void swap(BST &, BST &); + + /**************************************************************************/ + private: + + //! \brief Struct defining a single node in a singly-linked binary search tree. + struct Node { + Node *left; + Node *right; + key_t key; + T data; + + /** Struct methods. */ + + //! \brief Parametrized Constructor. + Node(const key_t &k=key_t(), const T& d=T()):left(nullptr), right(nullptr), key(k), data(d) { + DEBUG_MSG("Node:: Parametrized c'tor I called"); + } + + //! \brief Parametrized Constructor. + Node(Node *l=nullptr, Node *r=nullptr, const key_t &k=key_t(), const T& d=T()):left(l), right(r), key(k), data(d) { + DEBUG_MSG("Node:: Parametrized c'tor II called"); + } + + //! \brief Parametrized Constructor. + Node(Node *l=nullptr, Node *r=nullptr, key_t&& k=key_t(), T&& d=T()):left(l), right(r), key(std::move(k)), data(std::move(d)) { + DEBUG_MSG("Node:: Parametrized c'tor III called"); + } + + //! \brief Copy Constructor. + Node(const Node &other) : left(nullptr), right(nullptr), key(other.key), data(other.data){ + DEBUG_MSG("Node:: Copying node"); + if (other.left!=nullptr) left = new Node(*(other.left)); + if (other.right!=nullptr) right = new Node(*(other.right)); + } + + //! \brief Move Constructor. + Node(const Node &&other) : Node(){ + DEBUG_MSG("Node:: Moving node"); + swap(*this, other); + } + + //! \brief Destructor. + ~Node(){ + DEBUG_MSG("Node:: D'tor called"); + delete left; left = nullptr; + delete right; right = nullptr; + } + + //! \brief Assignmet. + Node & operator=(const Node other){ + DEBUG_MSG("Node:: Combined assignment called"); + swap(*this, other); + return *this; + } + + //! \brief Data Getter function. + T & getdata() { + DEBUG_MSG("Node:: Getting data"); + return data; + } + //! \brief Key Getter function. + key_t & getkey() { + DEBUG_MSG("Node:: Getting key"); + return key; + } + //! \brief left getter function. + Node* getleft() { + DEBUG_MSG("Node:: Getting left"); + return left; + } + //! \brief right getter function. + Node* getright() { + DEBUG_MSG("Node:: Getting right"); + return right; + } + + Node* search(const key_t &k) { + DEBUG_MSG("Node:: Searching subtree for key "<key < k) return this->left->search(k); + else if (this->key > k) return this->right->search(k); + else return this; + } + return this; + } + + void insert(const key_t &k, const T&d) { + //assert(this!=nullptr); + if (k < this->key){ + if(this->left!=nullptr){ + DEBUG_MSG("Node:: Going left"); + return this->left->insert(k, d); + } + else{ + DEBUG_MSG("Node:: Inserting {key, data} = "<left = new Node(k, d); + } + } + else if (k > this->key){ + if(this->right!=nullptr){ + DEBUG_MSG("Node:: Going right"); + return this->right->insert(k, d); + } + else{ + DEBUG_MSG("Node:: Inserting {key, data} = "<right = new Node(k, d); + } + } + else{ + /* Key already exists. */ + DEBUG_MSG("Node:: Replacing data in existing key {key, data} = "<data = d; + } + } + + /** Friends. */ + + }; + + /**********************************************************************/ + /** BST variables */ + Node *root; + + public: + Node *getroot() { + DEBUG_MSG("BST:: Getting root"); + return root; + }; + + + //! \brief Binary search. + Node* search(const key_t &newkey) const { + DEBUG_MSG("BST:: Searching for node with key " << newkey); + return root->search(newkey); + } + + //! \brief Sorted insert. + void insert(const key_t &newkey=key_t(), const T &newdata=T()){ + DEBUG_MSG("BST:: Inserting node {key, data} = " << newkey << ", "<< newdata); + if (root==nullptr){ + DEBUG_MSG("BST:: Inserting ROOT node {key, data} = " << newkey << ", "<< newdata); + root = new Node(newkey, newdata); + } + else root->insert(newkey, newdata); + } + + //! \brief Remove node from the beginnging/root of the list object. + //void remove(); + + //! \brief rebalance the binary search tree. + //void rebalance(); + + //! \brief Operator[] + Node *operator[](const key_t &k){ + return search(k); + } + +}; + +/******************************************************************************/ +/******************************************************************************/ +/* * * * * * * * * * * * * * * * * * * NODE * * * * * * * * * * * * * * * * * */ +/******************************************************************************/ +/******************************************************************************/ + +/**********************************************************************/ +/** Friends. */ + +//! \brief Displays the data in the BST::Node -- in-order traversal. +template +std::ostream& operator<<(std::ostream& os, const typename BST::Node *node){ + /* In-order traversal */ + if (node!=nullptr){ + operator<< (os, node->left); + os << node->data << ", "; + operator<< (os, node->right); + } + return os; +} +//! \brief Displays the binary search tree. +template +std::ostream& operator<<(std::ostream& os, const BST& bst){ + os << "["; + operator<< (os, bst.root); + os << "]"; + return os; +} + + +//! \brief Swap function for Copy-and-Swap Idiom. +template +void swap(typename BST::Node &first, typename BST::Node &second){ + DEBUG_MSG("Swap called"); + std::swap(first.left, second.left); + std::swap(first.right, second.right); + std::swap(first.key, second.key); + std::swap(first.data, second.data); +} + +/******************************************************************************/ +/******************************************************************************/ +/* * * * * * * * * * * * * * * * * * * LIST * * * * * * * * * * * * * * * * * */ +/******************************************************************************/ +/******************************************************************************/ + +/**********************************************************************/ +/** Friend functions. */ + +//! \brief Swap function for Copy-and-Swap Idiom. +template +void swap(BST &first, BST &second){ + DEBUG_MSG("BST:: Swap called"); + using namespace std; + swap(first.root, second.root); +} + + +/******************************************************************************/ +////! \brief Remove node from the beginnging/root of the list object. +//template +//void BST::remove(){ +// DEBUG_MSG("Node:: Removing a node at front of list"); +// if (root==nullptr) throw std::runtime_error("Error! Attempted node removal from an empty list"); +// if (root==tail){ /* Single node in the binary search tree */ +// delete tail; +// root = nullptr; +// tail = nullptr; +// } +// else{ +// auto tmp = root; +// root = root->left; +// delete tmp; +// } +//} + +////! \brief Rebalance the binary search tree. +//template +//void BST::rebalance(){ +// DEBUG_MSG("BST:: Reversing the binary search tree"); +// if (root!=nullptr){ +// decltype(root) prev = nullptr; +// while (root->left!=nullptr){ +// auto tmp = root->left; +// root->left = prev; +// prev = root; +// root = tmp; +// } +// root->left = prev; +// } +//} + diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b3c543a..f4cfa2e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,14 +2,15 @@ cmake_minimum_required(VERSION 3.6) # List all files containing tests. list(APPEND tests_sources + test_bst.cpp test_allsort.cpp test_list.cpp test_copy_and_swap_idiom.cpp test_vector.cpp - test_main.cpp ) list(REMOVE_DUPLICATES tests_sources) +list(APPEND tests_sources test_main.cpp) # Always include test_main.cpp list(APPEND lib_depends ${LIBRARY_NAME} doctest) set(TEST_MAIN unit_tests) # Default name for test executable (change if you wish). diff --git a/tests/test_bst.cpp b/tests/test_bst.cpp new file mode 100644 index 0000000..48f0486 --- /dev/null +++ b/tests/test_bst.cpp @@ -0,0 +1,370 @@ +#include "doctest.h" +#include "bst.h" +using namespace std; + +TEST_CASE("Empty BST") { + DEBUG_MSG(endl); + BST u; + CHECK(u.getroot() == nullptr); + DEBUG_MSG("Printing BST: "<< u); + SUBCASE("Copy C'tor") { + BST v = u; + CHECK(v.getroot() == nullptr); + } + SUBCASE("Copy Assignment") { + BST v; + v = u; + CHECK(v.getroot() == nullptr); + } + SUBCASE("Move C'tor") { + BST v = std::move(u); + CHECK(v.getroot() == nullptr); + } + SUBCASE("Move Assignment") { + BST v; + v = std::move(u); + CHECK(v.getroot() == nullptr); + } + SUBCASE("Self Copy Assignment") { + u = u; + } + SUBCASE("Self Move Assignment") { + u = std::move(u); + } + //SUBCASE("Rebalance") { + // u.rebalance(); + //} + CHECK(u.getroot() == nullptr); +} + +TEST_CASE("Single-noded BST") { + DEBUG_MSG(endl); + BST u; + SUBCASE("Insert new node without any arguments."){ + SUBCASE("Insert."){ + u.insert(); + } + SUBCASE("Insert."){ + u.insert(); + } + } + //SUBCASE("Rebalance") { + // u.insert(); + // u.rebalance(); + //} + CHECK(u.getroot()->getkey() == int()); + CHECK(u.getroot()->getdata() == int()); + CHECK(u.getroot()->getleft() == nullptr); + CHECK(u.getroot()->getright() == nullptr); +} + +TEST_CASE("Single-noded BST") { + DEBUG_MSG(endl); + BST u; + u.insert(1,5); + CHECK(u.getroot()->getkey() == 1); + CHECK(u.getroot()->getdata() == 5); + CHECK(u.getroot()->getleft() == nullptr); + CHECK(u.getroot()->getright() == nullptr); + DEBUG_MSG("Printing BST: "<< u); + + SUBCASE("Copy C'tor") { + BST v = u; + CHECK(v.getroot() != u.getroot()); + CHECK(v.getroot()->getkey() == 1); + CHECK(v.getroot()->getdata() == 5); + CHECK(v.getroot()->getleft() == nullptr); + CHECK(v.getroot()->getright() == nullptr); + } + SUBCASE("Copy Assignment") { + BST v; + v = u; + CHECK(v.getroot() != u.getroot()); + CHECK(v.getroot()->getkey() == 1); + CHECK(v.getroot()->getdata() == 5); + CHECK(v.getroot()->getleft() == nullptr); + CHECK(v.getroot()->getright() == nullptr); + } + SUBCASE("Self Copy Assignment") { + u = u; + } + SUBCASE("Self Move Assignment") { + u = std::move(u); + } + //SUBCASE("Rebalance") { + // u.rebalance(); + //} + CHECK(u.getroot() != nullptr); + CHECK(u.getroot()->getdata() == 5); + CHECK(u.getroot()->getleft() == nullptr); + CHECK(u.getroot()->getright() == nullptr); + + SUBCASE("Move C'tor") { + BST v = std::move(u); + CHECK(v.getroot() != u.getroot()); + CHECK(v.getroot()->getdata() == 5); + CHECK(v.getroot()->getleft() == nullptr); + CHECK(v.getroot()->getright() == nullptr); + CHECK(u.getroot() == nullptr); // Make sure it moved + } + SUBCASE("Move Assignment") { + BST v; + v = std::move(u); + CHECK(v.getroot() != u.getroot()); + CHECK(v.getroot()->getdata() == 5); + CHECK(v.getroot()->getleft() == nullptr); + CHECK(v.getroot()->getright() == nullptr); + CHECK(u.getroot() == nullptr); // Make sure it moved + } +} + +//TEST_CASE("BST Operations - BST") { +// DEBUG_MSG(endl); +// BST u; +// SUBCASE("Exception check - Popping an empty binary search tree"){ +// REQUIRE_THROWS_WITH_AS(u.remove(), +// "Error! Attempted node removal from an empty binary search tree", +// const std::runtime_error &); +// } +// +// SUBCASE("insert x 4, remove x 4") { +// int arr[]={141, 12, 342, 4521}; +// for (int i=0; i<4; i++){ +// u.insert(arr[i]); +// auto tmp=u.getroot(); +// int j = 0; +// while(tmp){ +// CHECK(tmp->getdata()==arr[i-j]); +// tmp=tmp->next; +// j++; +// } +// DEBUG_MSG("Printing BST: "<< u); +// } +// for (int i=0; i<4; i++){ +// u.remove(); +// auto tmp=u.getroot(); +// int j = 0; +// while(tmp){ +// CHECK(tmp->getdata()==arr[3-j]); +// tmp=tmp->next; +// j++; +// } +// DEBUG_MSG("Printing BST: "<< u); +// } +// } +// SUBCASE("insert, insert, insert") { +// int arr[]={1352, 165, 125}; +// int ans[]={arr[2], arr[0], arr[1]}; +// u.insert(arr[0]); +// u.insert(arr[1]); +// u.insert(arr[2]); +// int j=0; +// auto tmp=u.getroot(); +// while(tmp){ +// CHECK(tmp->getdata()==ans[j]); +// tmp=tmp->next; +// j++; +// } +// DEBUG_MSG("Printing BST: "<< u); +// } +//} + +TEST_CASE("Multiple-noded BST") { + DEBUG_MSG(endl); + BST u; + u.insert(2,5); + u.insert(1,1); + u.insert(3,25); + DEBUG_MSG("Printing BST: "<< u); + CHECK(u.getroot()->getkey() == 2); + CHECK(u.getroot()->getdata() == 5); + CHECK(u.getroot()->getleft() != nullptr); + CHECK(u.getroot()->getright() != nullptr); + CHECK(u.getroot()->getleft()->getkey() == 1); + CHECK(u.getroot()->getleft()->getdata() == 1); + CHECK(u.getroot()->getright()->getkey() == 3); + CHECK(u.getroot()->getright()->getdata() == 25); + CHECK(u.getroot()->getleft()->getleft() == nullptr); + CHECK(u.getroot()->getleft()->getright() == nullptr); + CHECK(u.getroot()->getright()->getleft() == nullptr); + CHECK(u.getroot()->getright()->getright() == nullptr); + SUBCASE("Overwrite BST by copy assignment") { + BST v; + v.insert(2140,2140); + v.insert(7,7); + u = v; + CHECK(u.getroot()!=nullptr); + CHECK(u.getroot()->getdata() == 2140); + CHECK(u.getroot()->getleft()->getdata() == 7); + CHECK(u.getroot()->getleft()->getleft() == nullptr); + CHECK(v.getroot()!=nullptr); + CHECK(v.getroot()->getdata() == 2140); + CHECK(v.getroot()->getleft()->getdata() == 7); + CHECK(v.getroot()->getright() == nullptr); + CHECK(v.getroot()->getleft()->getright() == nullptr); + CHECK(v.getroot()->getleft()->getleft() == nullptr); + DEBUG_MSG("Printing overwritten Binary Search Tree: "<< u); + /* Make sure the binary search trees are different and copied. */ + CHECK(u.getroot()!=v.getroot()); + CHECK(u.getroot()->getleft()!=v.getroot()->getleft()); + CHECK((u.getroot()+1)!=(v.getroot()+1)); // Tail + } + SUBCASE("Overwrite BST by move assignment") { + BST v; + v.insert(915,915); + v.insert(5,5); + v.insert(1405, 1429); + v.insert(9,9); + v.insert(92405, 92135); + v.insert(51905, 51930); + u = std::move(v); + CHECK(v.getroot()==nullptr); + CHECK(u.getroot()!=nullptr); + CHECK(u.getroot()->getdata() == 915); + CHECK(u.getroot()->getleft()->getdata() == 5); + CHECK(u.getroot()->getright()->getdata() == 1429); + CHECK(u.getroot()->getright()->getright()->getdata() == 92135); + CHECK(u.getroot()->getright()->getright()->getleft()->getdata() == 51930); + DEBUG_MSG("Printing overwritten Binary Search Tree: "<< u); + /* Make sure the binary search trees are different. */ + CHECK(u.getroot()!=v.getroot()); + CHECK((u.getroot()+1)!=(v.getroot()+1)); // Tail + } + //SUBCASE("Rebalance the binary search tree"){ + // u.rebalance(); + // DEBUG_MSG("Printing rebalanced Binary Search Tree: "<< u); + // CHECK(u.getroot()->getdata() == 5); + // CHECK(u.getroot()->getleft()->getdata() == 1); + // CHECK(u.getroot()->getleft()->getleft()->getdata() == 25); + // CHECK(u.getroot()->getleft()->getleft()->getleft() == nullptr); + //} +} + +TEST_CASE("Multiple-noded BST") { + DEBUG_MSG(endl); + BST u; + //u.insert("b", "b"); + //u.insert("a", "a"); + //u.insert("z", "z"); + u.insert("Templates", "Templates"); + u.insert("are", "are"); + u.insert("beautiful!", "beautiful!"); + DEBUG_MSG("Printing BST: "<< u); + CHECK(u.getroot()->getdata() == "Templates"); + CHECK(u.getroot()->getright()->getdata() == "are"); + CHECK(u.getroot()->getright()->getright()->getdata() == "beautiful!"); + CHECK(u.getroot()->getleft() == nullptr); + CHECK(u.getroot()->getright()->getleft() == nullptr); + CHECK(u.getroot()->getright()->getright()->getleft() == nullptr); + CHECK(u.getroot()->getright()->getright()->getright() == nullptr); + SUBCASE("Overwrite BST by copy assignment") { + BST v; + v.insert("OOP", "OOP"); + u = std::move(v); + DEBUG_MSG("Printing overwritten Binary Search Tree: "<< u); + } + SUBCASE("Overwrite BST by move assignment") { + BST v; + v.insert("world", "world"); + v.insert("o", "o"); + v.insert("l", "l"); + v.insert("l", "l"); + v.insert("e", "e"); + v.insert("H", "H"); + u = std::move(v); + DEBUG_MSG("Printing overwritten Binary Search Tree: "<< u); + } +} + +TEST_CASE("Complex Multiple-noded BST>") { + DEBUG_MSG(endl); + + BST sentence1; + sentence1.insert("Hello", "Hello"); + sentence1.insert("world!", "world!"); + CHECK(sentence1.getroot()->getkey() == "Hello"); + CHECK(sentence1.getroot()->getdata() == "Hello"); + CHECK(sentence1.getroot()->getright()->getkey() == "world!"); + CHECK(sentence1.getroot()->getright()->getdata() == "world!"); + + decltype(sentence1) sentence2; + sentence2.insert("OOP", "OOP"); + sentence2.insert("is", "is"); + sentence2.insert("difficult!", "difficult!"); + CHECK(sentence2.getroot()->getkey() == "OOP"); + CHECK(sentence2.getroot()->getdata() == "OOP"); + CHECK(sentence2.getroot()->getright()->getkey() == "is"); + CHECK(sentence2.getroot()->getright()->getdata() == "is"); + CHECK(sentence2.getroot()->getright()->getleft()->getkey() == "difficult!"); + CHECK(sentence2.getroot()->getright()->getleft()->getdata() == "difficult!"); + + decltype(sentence1) sentence3; + sentence3.insert("Templates", "Templates"); + sentence3.insert("are", "are"); + sentence3.insert("beautiful!", "beautiful!"); + + BST u; + u.insert(2,sentence1); + u.insert(1,sentence2); + u.insert(3,sentence3); + + DEBUG_MSG("Printing BST: "<< sentence1); + DEBUG_MSG("Printing BST: "<< sentence2); + DEBUG_MSG("Printing BST: "<< sentence3); + DEBUG_MSG("Printing BST: "<< u); + auto *tmp = &(u.getroot()->getdata()); + CHECK(tmp->getroot()->getkey() == "Hello"); + CHECK(tmp->getroot()->getdata() == "Hello"); + CHECK(tmp->getroot()->getright()->getkey() == "world!"); + CHECK(tmp->getroot()->getright()->getdata() == "world!"); + + tmp = &(u.getroot()->getleft()->getdata()); + CHECK(tmp->getroot()->getdata() == "OOP"); + CHECK(tmp->getroot()->getright()->getdata() == "is"); + CHECK(tmp->getroot()->getright()->getleft()->getdata() == "difficult!"); + + tmp = &(u.getroot()->getright()->getdata()); + CHECK(tmp->getroot()->getdata() == "Templates"); + CHECK(tmp->getroot()->getright()->getdata() == "are"); + CHECK(tmp->getroot()->getright()->getright()->getdata() == "beautiful!"); + + //SUBCASE("Rebalance binary-search-tree-of-binary-search-trees."){ + // u.rebalance(); + // DEBUG_MSG("Printing rebalanced Binary Search Tree: "<< u); + // auto *tmp = &(u.getroot()->getdata()); + // CHECK(tmp->getroot()->getdata() == "Templates"); + // CHECK(tmp->getroot()->getleft()->getdata() == "are"); + // CHECK(tmp->getroot()->getleft()->getleft()->getdata() == "beautiful!"); + // + // tmp = &(u.getroot()->getleft()->getdata()); + // CHECK(tmp->getroot()->getdata() == "OOP"); + // CHECK(tmp->getroot()->getleft()->getdata() == "is"); + // CHECK(tmp->getroot()->getleft()->getleft()->getdata() == "difficult!"); + // + // tmp = &(u.getroot()->getleft()->getleft()->getdata()); + // CHECK(tmp->getroot()->getdata() == "Hello"); + // CHECK(tmp->getroot()->getleft()->getdata() == "world!"); + // SUBCASE("Rebalance binary-search-trees inside binary-search-tree-of-binary-search-trees."){ + // auto *tmp1 = &(u.getroot()->getdata()); + // tmp1->rebalance(); + // DEBUG_MSG("Printing rebalanced Binary Search Tree: "<< u); + // CHECK(tmp1->getroot()->getdata() == "beautiful!"); + // CHECK(tmp1->getroot()->getleft()->getdata() == "are"); + // CHECK(tmp1->getroot()->getleft()->getleft()->getdata() == "Templates"); + + // tmp1 = &(u.getroot()->getleft()->getdata()); + // tmp1->rebalance(); + // DEBUG_MSG("Printing rebalanced Binary Search Tree: "<< u); + // CHECK(tmp1->getroot()->getdata() == "difficult!"); + // CHECK(tmp1->getroot()->getleft()->getdata() == "is"); + // CHECK(tmp1->getroot()->getleft()->getleft()->getdata() == "OOP"); + + // tmp1 = &(u.getroot()->getleft()->getleft()->getdata()); + // tmp1->rebalance(); + // DEBUG_MSG("Printing rebalanced Binary Search Tree: "<< u); + // CHECK(tmp1->getroot()->getdata() == "world!"); + // CHECK(tmp1->getroot()->getleft()->getdata() == "Hello"); + // } + //} +} +