# Week 9 - Binary Trees Team Members: Member one Andreas Andreou Member two Iasonas Ilias Kapetanidis Date: day month 2023 | | Activities**** Make sure to have the activities signed off regularly to ensure progress is tracked. Download the provided project and open it in CLion. ### Activity 1: Maintaining order in arrays and linked lists - reprise Record your answer here | | Array | Linked List | | ------------------ | ------ | ----------- | | value insertion | O(n) | O(n) | | value removal | O(n) | O(log(n)) | | membership testing | O(n) | O(n) | ### Activity 2: Recognizing BSTs The first tree is not correct because of the value 71 is not greater than the root of the tree. The second tree is wrong because of the value 84 it should have been bigger than 85 ### Activity 3: Searching for values ```clike bool bintree::contains(int value) const { // TODO (Activity 3) - find out if the tree contains the value // return true if the value is in the tree, false otherwise (void) value; if (m_root == nullptr) { return false; // valuei not found in the tree tree is empty } const bintree_node* current = m_root; while (current != nullptr) { if (current->value() == value) { return true; // cvalue found in the curent node } else if (value < current->value()) { current = current->left(); // in the left } else { current = current->right(); // in the right } } return false; // not found in the tree } ``` ### Activity 4: Inserting values ```clike bool bintree::insert(int value) { if (m_root == nullptr) { // Let the sentinel node point to the root m_sentinel.m_left = m_root = new bintree_node{value}; m_count = 1; return true; } else { // the tree already contains some nodes // TODO (Activity 4) - insert the value into the tree // move through the tree from the root to the node where the new node should be inserted // If the value is already in the tree, return false, otherwise insert a new bintree_node // at the right place, increment the count, and return true // The tree already contains some nodes bintree_node* current = const_cast<bintree_node*>(m_root); while (true) { if (value == current->value()) { return false; // Value is already in the tree, return false } else if (value < current->value()) { if (current->left() == nullptr) { current->m_left = new bintree_node{value}; m_count=m_count+1; return true; // Value inserted successfully, return true } else { current = const_cast<bintree_node*>(current->left()); // Move to the left subtree } } else { if (current->right() == nullptr) { current->m_right = new bintree_node{value}; m_count=m_count+1; return true; // Value inserted successfully, return true } else { current = const_cast<bintree_node*>(current->right()); // Move to the right subtree }} }} return false; } ``` ### Activity 5: Removing leafs ```clike void bintree::remove_leaf(bintree_node* node, bintree_node* parent) { if (!parent->is_child(node)) throw std::invalid_argument("parent is not the parent of the node"); if (parent == nullptr) { // Removing the root node m_root = nullptr; m_sentinel.m_left = nullptr; } else { parent->replace_child(node, nullptr); } delete node; m_count--; } void bintree::remove_half_node(bintree_node* node, bintree_node* parent) { if (!parent->is_child(node)) throw std::invalid_argument("parent is not the parent of the node"); bintree_node* child = nullptr; if (node->has_left_child()) { child = const_cast<bintree_node*>(node->left()); } else if (node->has_right_child()) { child = const_cast<bintree_node*>(node->right()); } if (parent == nullptr) { // Removing the root node m_root = child; m_sentinel.m_left = child; } else { parent->replace_child(node, child); } delete node; m_count--; } ``` ### Activity 6: Moving values around •All values in the root’s left subtree are less than or equal to the root’s value. • All values in the root’s right subtree are greater than or equal to the root’s value. • The left and right subtree are both sorted. First tree Left A < D A< B C< B First tree Right D>A E>F G>E On the first tree is G Second Tree Left A< F A>B A< C C>D C< E Second Right F>G F< J G< H On the second tree is J or H ### Activity 7: Finding the smallest and greatest values ```clike int value1(const bintree_node* root) { while (root->has_left_node()) { root = root->left(); } return root->value(); } ``` ```clike int value3(const bintree_node* root) { while (root->has_right_node()) { root = root->right(); } while (root->has_left_node()) { root = root->left(); } return root->value(); } ``` Value one searches for the smallest.It goes through the left side of the tree Value three searches for the biggest.It goes through the right side ### Activity 8: Removing full nodes ```clike void bintree::remove_full_node(bintree_node *node) { bintree_node* successor = const_cast<bintree_node*>(node->right()); while (successor->has_left_child()) { successor = const_cast<bintree_node*>(successor->left()); } // Replace the value of the node with the value of the successor node->m_value = successor->value(); // Remove the successor node if (successor->is_leaf()) { remove_leaf(successor, nullptr); } else { remove_half_node(successor, nullptr); } } ``` ### Activity 9: Cleaning up ```clike void bintree::destruct_subtree(bintree_node* root) { // TODO (Activity 9) - destruct the subtree rooted at root if (root == nullptr) return; destruct_subtree(const_cast<bintree_node*>(root->left())); destruct_subtree(const_cast<bintree_node*>(root->right())); delete root; } ``` ```clike bool bintree::remove(int value) { bintree_node* parent = nullptr; bintree_node* current = m_root; // Search for the node with the given value while (current != nullptr) { if (value == current->value()) { // Node found, perform the removal based on its type if (current->is_leaf()) { remove_leaf(current, parent); } else if (current->is_full()) { remove_full_node(current); } else { remove_half_node(current, parent); } return true; // Node removed successfully } else if (value < current->value()) { parent = current; current = const_cast<bintree_node*>(current->left()); } else { parent = current; current = const_cast<bintree_node*>(current->right()); } } return false; // Node not found in the tree } ``` ### Activity 10: (Un)balanced trees ```clike bintree bst; std::ifstream file1("numbers1.txt"); std::ifstream file2("numbers2.txt"); std::ifstream file3("numbers3.txt"); int number; while (file1 >> number) { bst.insert(number); } while (file2 >> number) { bst.insert(number); } while (file3 >> number) { bst.insert(number); } // Export BST to .dot file std::ofstream dotFile("bst.dot"); bintree_writer::write_dot(bst, dotFile); ``` ### Activity 11: Time complexity Operation Time complexity (if balanced) Time complexity (if unbalanced) Lookup O(log n) O(n) Insert O(log n) O(n) Remove O(log n) O(n) Looking back What we've learnt Formulate at least one lesson learned. What were the surprises Fill in... What problems we've encountered Fill in... What was or still is unclear Fill in... How did the group perform? How was the collaboration? What were the reasons for hick-ups? What worked well? What can be improved next time?