finish more details and ready to write erase

This commit is contained in:
2024-03-26 02:49:30 +00:00
parent c585b59f7a
commit 347cfcf8e9

View File

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