From a9ced246db6c9ca64aaf03980114d2efd17bbdb1 Mon Sep 17 00:00:00 2001 From: Jidong Xiao Date: Fri, 21 Mar 2025 01:10:02 -0400 Subject: [PATCH] adding the almost completed ds set --- lectures/19_trees_II/ds_set.h | 131 +++++++++++++++++++++++++++ lectures/19_trees_II/ds_set_main.cpp | 31 +++++++ 2 files changed, 162 insertions(+) create mode 100644 lectures/19_trees_II/ds_set.h create mode 100644 lectures/19_trees_II/ds_set_main.cpp diff --git a/lectures/19_trees_II/ds_set.h b/lectures/19_trees_II/ds_set.h new file mode 100644 index 0000000..fca846f --- /dev/null +++ b/lectures/19_trees_II/ds_set.h @@ -0,0 +1,131 @@ +#include // for std::pair + +template +class TreeNode { +public: + T key; + TreeNode* left; + TreeNode* right; + // one way to allow implementation of iterator increment & decrement + TreeNode* parent; + // constructor + TreeNode(const T& k) { + key = k; + left = NULL; + right = NULL; + } +}; + +// ------------------------------------------------------------------- +// TREE NODE ITERATOR CLASS +template +class tree_iterator { +public: + tree_iterator() : ptr_(NULL) {} + tree_iterator(TreeNode* p) : ptr_(p) {} + tree_iterator(const tree_iterator& old) : ptr_(old.ptr_) {} + ~tree_iterator() {} + tree_iterator& operator=(const tree_iterator& old) { ptr_ = old.ptr_; return *this; } + // operator* gives constant access to the value at the pointer + const T& operator*() const { return ptr_->key; } + // comparison operators are straightforward + bool operator== (const tree_iterator& rgt) { return ptr_ == rgt.ptr_; } + bool operator!= (const tree_iterator& rgt) { return ptr_ != rgt.ptr_; } + // increment & decrement operators + tree_iterator & operator++() { + // if i have right subtree, find left most element of those + if (ptr_->right != NULL) { + ptr_ = ptr_->right; + while (ptr_->left != NULL) { + ptr_ = ptr_->left; + } + } else { + // keep going up as long as I'm my parent's right child + while (ptr_->parent && ptr_->parent->right == ptr_) { + ptr_ = ptr_->parent; + } + // go up one more time + ptr_ = ptr_->parent; + } + return *this; + } + tree_iterator operator++(int) { tree_iterator temp(*this); ++(*this); return temp; } + tree_iterator & operator--() { /* implementation omitted */ } + tree_iterator operator--(int) { tree_iterator temp(*this); --(*this); return temp; } + +private: + // representation + TreeNode* ptr_; +}; + +// internally it's a binary search tree +template +class ds_set { +public: + ds_set(){ + root = NULL; + m_size = 0; + } + typedef tree_iterator iterator; + int size() { return m_size; } + iterator find(const T& key){ + return find(key, root); + } + std::pair insert(const T& key){ + std::pair temp; + temp = insert(key, root, NULL); + if(temp.second == true){ + ++m_size; + } + return temp; + } + // ITERATORS + tree_iterator begin() const { + if (!root) return tree_iterator(NULL); + TreeNode* p = root; + while (p->left) { + p = p->left; + } + return tree_iterator(p); + } + tree_iterator end() const { return tree_iterator(NULL); } +private: + TreeNode* root; + int m_size; + iterator find(const T& key, TreeNode* root); + // as there are multiple templated classes involved, writing this function outside of the class definition may be too complicated. + std::pair insert(const T& key, TreeNode*& node, TreeNode* parent) { + // base case + if (node == nullptr) { + node = new TreeNode(key); + node->parent = parent; + return { iterator(node), true }; + } + if (key < node->key) { + return insert(key, node->left, node); + } else if (key > node->key) { + return insert(key, node->right, node); + } else { + // key already exists + return { iterator(node), false }; + } + } +}; + +template +typename ds_set::iterator ds_set::find(const T& key, TreeNode* root){ + // base case (if root doesn't even exist) + if(root == NULL){ + return end(); + } + + // general case + if(key < root->key){ + return find(key, root->left); + }else if(key > root->key){ + return find(key, root->right); + }else{ + return tree_iterator(root); + } +} + diff --git a/lectures/19_trees_II/ds_set_main.cpp b/lectures/19_trees_II/ds_set_main.cpp new file mode 100644 index 0000000..4e76ef0 --- /dev/null +++ b/lectures/19_trees_II/ds_set_main.cpp @@ -0,0 +1,31 @@ +#include +#include "ds_set.h" + +int main() { + // create a set of integers + ds_set numbers; + + // insert some values into the set + numbers.insert(10); + numbers.insert(5); + numbers.insert(20); + numbers.insert(15); + numbers.insert(5); // Duplicate value (won't be inserted) + + // print the elements of the set + std::cout << "The elements in the set are:" << std::endl; + for(ds_set::iterator itr = numbers.begin(); itr != numbers.end(); ++itr){ + std::cout << *itr << " "; + } + std::cout << std::endl; + + // check if a specific value exists in the set + int value = 15; + if (numbers.find(value) != numbers.end()) { + std::cout << value << " is found in the set." << std::endl; + } else { + std::cout << value << " is not found in the set." << std::endl; + } + + return 0; +}