diff --git a/map/src/map.hpp b/map/src/map.hpp index 4357ced..f2504e2 100644 --- a/map/src/map.hpp +++ b/map/src/map.hpp @@ -115,7 +115,7 @@ class map { return; } RedBlackTreeNodeType *uncle = GetUncle(); - RedBlackTreeColorType *grand_parent = GetGrandParent(); + RedBlackTreeNodeType *grand_parent = GetGrandParent(); if (uncle != nullptr && uncle->color == RedBlackTreeColorType::RED) { // Case 4 parent->color = RedBlackTreeColorType::BLACK; @@ -157,17 +157,19 @@ class map { * @param val The value to be inserted. * @param allow_replacement Whether to allow replacement if the key already exists. * - * @return Whether the insertion is successful. + * @return Whether the insertion is successful and where the insertion is. * * @note Note that tree_root is a reference to the root of the tree. This function will modify the tree_root if * necessary. */ - bool Insert(RedBlackTreeNodeType *&tree_root, const value_type &val, bool allow_replacement) { + std::pair Insert(RedBlackTreeNodeType *&tree_root, const value_type &val, + bool allow_replacement) { if (comparer(val.first, this->val.first)) { if (left == nullptr) { left = new RedBlackTreeNodeType(val, nullptr, nullptr, this, RedBlackTreeColorType::RED); left->parent = this; left->InsertFixUp(tree_root); + return std::pair(left, true); } else { return left->Insert(tree_root, val, allow_replacement); } @@ -176,16 +178,17 @@ class map { right = new RedBlackTreeNodeType(val, nullptr, nullptr, this, RedBlackTreeColorType::RED); right->parent = this; right->InsertFixUp(tree_root); + return std::pair(right, true); } else { return right->Insert(tree_root, val, allow_replacement); } } else { if (allow_replacement) { - this->val = val; - return true; + this->val.second = val.second; + return std::pair(this, false); } } - return false; + return std::pair(this, false); } /** * @brief The definition of ReleaseAll. @@ -200,9 +203,27 @@ class map { delete left; delete right; } + RedBlackTreeNodeType *Find(const decltype(val.first) &key) { + if (comparer(key, val.first)) { + if (left == nullptr) return nullptr; + return left->Find(key); + } else if (comparer(val.first, key)) { + if (right == nullptr) return nullptr; + return right->Find(key); + } else { + return this; + } + } }; size_t node_count; RedBlackTreeNodeType *tree_root; + void CopyFrom(RedBlackTreeNodeType *&target, const RedBlackTreeNodeType *source) { + if (source == nullptr) return; + target = new RedBlackTreeNodeType(source->val, nullptr, nullptr, nullptr, source->color); + CopyFrom(target->left, source->left); + CopyFrom(target->right, source->right); + target->SetChildrensParent(); + } public: /** @@ -222,6 +243,7 @@ class map { map *domain; public: + friend const_iterator; iterator() : raw_pointer(nullptr), domain(nullptr) {} iterator(const iterator &other) : raw_pointer(other.raw_pointer), domain(other.domain) {} iterator(RedBlackTreeNodeType *raw_pointer, map *domain) : raw_pointer(raw_pointer), domain(domain) {} @@ -304,6 +326,7 @@ class map { const map *domain; public: + friend iterator; const_iterator() : raw_pointer(nullptr), domain(nullptr) {} const_iterator(const const_iterator &other) : raw_pointer(other.raw_pointer), domain(other.domain) {} const_iterator(const iterator &other) : raw_pointer(other.raw_pointer), domain(other.domain) {} @@ -375,46 +398,90 @@ class map { value_type *operator->() const noexcept { return &raw_pointer->val; } }; map() : node_count(0), tree_root(nullptr) {} - // TODO copy constructor - map(const map &other) {} + map(const map &other) { + node_count = other.node_count; + CopyFrom(tree_root, other.tree_root); + } + map(map &&other) { + node_count = other.node_count; + tree_root = other.tree_root; + other.node_count = 0; + other.tree_root = nullptr; + } /** * TODO assignment operator */ - map &operator=(const map &other) {} + map &operator=(const map &other) { + if (this == &other) return *this; + if (tree_root) tree_root->ReleaseAll(); + delete tree_root; + node_count = other.node_count; + CopyFrom(tree_root, other.tree_root); + } + map &operator=(map &&other) { + if (this == &other) return *this; + if (tree_root) tree_root->ReleaseAll(); + delete tree_root; + node_count = other.node_count; + tree_root = other.tree_root; + other.node_count = 0; + other.tree_root = nullptr; + } ~map() { if (tree_root) tree_root->ReleaseAll(); delete tree_root; } /** - * TODO * access specified element with bounds checking * Returns a reference to the mapped value of the element with key equivalent to key. * If no such element exists, an exception of type `index_out_of_bound' */ - T &at(const Key &key) {} - const T &at(const Key &key) const {} + T &at(const Key &key) { + RedBlackTreeNodeType *result = tree_root->Find(key); + if (result == nullptr) throw index_out_of_bound(); + return result->val.second; + } + const T &at(const Key &key) const { + RedBlackTreeNodeType *result = tree_root->Find(key); + if (result == nullptr) throw index_out_of_bound(); + return result->val.second; + } /** * TODO * access specified element * Returns a reference to the value that is mapped to a key equivalent to key, * performing an insertion if such key does not already exist. */ - T &operator[](const Key &key) {} + T &operator[](const Key &key) { + auto result = tree_root->Insert(tree_root, value_type(key, T()), false); + if (result.second) ++node_count; + return result.first->val.second; + } /** * behave like at() throw index_out_of_bound if such key does not exist. */ - const T &operator[](const Key &key) const {} + const T &operator[](const Key &key) const { return at(key); } /** * return a iterator to the beginning */ - iterator begin() {} - const_iterator cbegin() const {} + iterator begin() { + if (tree_root == nullptr) return iterator(nullptr, this); + RedBlackTreeNodeType *tmp = tree_root; + while (tmp->left != nullptr) tmp = tmp->left; + return iterator(tmp, this); + } + const_iterator cbegin() const { + if (tree_root == nullptr) return const_iterator(nullptr, this); + RedBlackTreeNodeType *tmp = tree_root; + while (tmp->left != nullptr) tmp = tmp->left; + return const_iterator(tmp, this); + } /** * return a iterator to the end * in fact, it returns past-the-end. */ - iterator end() {} - const_iterator cend() const {} + iterator end() { return iterator(nullptr, this); } + const_iterator cend() const { return const_iterator(nullptr, this); } /** * checks whether the container is empty * return true if empty, otherwise false. @@ -427,7 +494,12 @@ class map { /** * clears the contents */ - void clear() {} + void clear() { + if (tree_root) tree_root->ReleaseAll(); + delete tree_root; + tree_root = nullptr; + node_count = 0; + } /** * insert an element. * return a pair, the first of the pair is @@ -438,8 +510,11 @@ class map { if (tree_root == nullptr) { tree_root = new RedBlackTreeNodeType(value, nullptr, nullptr, nullptr, RedBlackTreeNodeType::BLACK); node_count = 1; - return pair(iterator(tree_root), true); + return pair(iterator(tree_root, this), true); } + auto result = tree_root->Insert(tree_root, value, false); + if (result.second) ++node_count; + return pair(iterator(result.first, this), result.second); } /** * erase the element at pos. @@ -454,16 +529,28 @@ class map { * since this container does not allow duplicates. * The default method of check the equivalence is !(a < b || b > a) */ - size_t count(const Key &key) const {} + size_t count(const Key &key) const { + if (tree_root == nullptr) return 0; + return tree_root->Find(key) == nullptr ? 0 : 1; + } /** * Finds an element with key equivalent to key. * key value of the element to search for. * Iterator to an element with key equivalent to key. * If no such element is found, past-the-end (see end()) iterator is returned. */ - iterator find(const Key &key) {} - const_iterator find(const Key &key) const {} + iterator find(const Key &key) { + if (tree_root == nullptr) return end(); + return iterator(tree_root->Find(key), this); + } + const_iterator find(const Key &key) const { + if (tree_root == nullptr) return cend(); + return const_iterator(tree_root->Find(key), this); + } }; +// Define the static member comparer. +template +Compare map::comparer = Compare(); } // namespace sjtu