finish more details and ready to write erase
This commit is contained in:
133
map/src/map.hpp
133
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<RedBlackTreeNodeType *, bool> 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<RedBlackTreeNodeType *, bool>(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<RedBlackTreeNodeType *, bool>(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<RedBlackTreeNodeType *, bool>(this, false);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return std::pair<RedBlackTreeNodeType *, bool>(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, 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.
|
||||
@ -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 <class Key, class T, class Compare>
|
||||
Compare map<Key, T, Compare>::comparer = Compare();
|
||||
|
||||
} // namespace sjtu
|
||||
|
||||
|
Reference in New Issue
Block a user