aboutsummaryrefslogtreecommitdiffstats
path: root/meowpp/dsa/SplayTree.h
diff options
context:
space:
mode:
Diffstat (limited to 'meowpp/dsa/SplayTree.h')
-rw-r--r--meowpp/dsa/SplayTree.h1366
1 files changed, 1141 insertions, 225 deletions
diff --git a/meowpp/dsa/SplayTree.h b/meowpp/dsa/SplayTree.h
index da451b0..5e9fb3c 100644
--- a/meowpp/dsa/SplayTree.h
+++ b/meowpp/dsa/SplayTree.h
@@ -2,234 +2,1150 @@
#define dsa_SplayTree_h__
#include <cstdlib>
-
#include <utility>
-namespace meow{
- //#
- //#=== meow:: *SplayTree<Key, Value>* (C++ class)
- //#==== Description
- //# `SplayTree` 是一種神乎其技的資料結構, 維護一堆 Key->Value . 並且支援
- //# 一些 `std::map` 難以快速實踐的操作, 如 `split` , `merge` , `keyOffset`
- //#
- //#==== Template Class Operators Request
- //#[options="header",width="70%",cols="1>m,1<,3<s,5<,3<,15<",grid="rows"]
- //#|=====================================================================
- //#|Const?|Typename| Operator| Parameters | Return_Type| Description
- //#|const |Key |operator+|(Key `k`) | Key | 相加
- //#|const |Key |operator<|(Key `k`) | bool | 大小比較
- //#| |Key |'Key' |(int `n`) | | 建構子, `n` 永遠是0
- //#| |Value | 'Value' |( ) | | 建構子
- //#|=====================================================================
- //#
- template<class Key, class Value>
- class SplayTree{
- private:
- struct Node{
- Key _key;
- Key _keyOffset;
- Value _value;
- size_t _size;
- Node* _parent;
- Node* _child[2];
- //
- Node(Key const& __key, Value const& __value);
- //
- void keyOffset(Key const& __delta);
- void syncDown() const;
- void syncUp () const;
- };
- //
- Node* _root;
- //
- void connect(Node const* __parent, size_t __left_right,
- Node const* __child) const;
- Node const* splay (Node const* __node) const;
- //
- void clear(Node* __node);
- Node* dup(Node* __node);
- //
- Node const* findKey (Node const* __node, Key const& __key ) const;
- Node const* findMinMax(Node const* __node, bool __minimum) const;
- Node const* findOrder (Node const* __node, size_t __order ) const;
- //
- void split(Node* __root, Node** __left, Node** __right);
- Node* merge( Node* __left, Node* __right);
- public:
- //#==== Custom Type Definitions
- //#
- //# * `Element` -> 用來當作回傳資料的媒介
- //# ** 重定義 `operator->()` 到 `std::pair<Key const&, Value&>*`
- //# ** 重定義 `operator*()` 到 `std::pair<Key const&, Value&>&`
- //# ** 有 `operator==` , `operator!=`, `operator=` 可用
- //# ** 可以直接用 `(*e).second = some_value` 來改變SplayTree中的資料
- //#
- class Element{
- private:
- typedef std::pair<Key const&, Value&> Entry;
- Entry* _entry;
- Node * _node;
- //
- void reset(Node* __node);
- public:
- Element();
- Element(Node* __node);
- Element(Element const& __iterator2);
- ~Element();
- //
- Element& operator=(Element const& __e2);
- //
- Entry* operator->();
- Entry& operator *();
- //
- bool operator==(Element const& __e2) const;
- bool operator!=(Element const& __e2) const;
- };
- //
- SplayTree();
- SplayTree(SplayTree const& __tree2);
- ~SplayTree();
- SplayTree& operator=(SplayTree const& __tree2);
- //
- //#==== Support Methods
- //#
- //# * N <- `this` 中擁有的資料數
- //# * M <- `tree2` 中擁有的資料數
- //#
- //#[options="header",width="100%",cols="1>m,3>s,7<,3<,3^,20<",grid="rows"]
- //#|=====================================================================
- //#|Const?|Name | Parameters | Return_Type| Time_Complexity| Description
-
-
- //#||moveTo|(SplayTree* `tree2`)|void|O(M)
- //#|將 `this` 的資料複寫到 `tree2` 上面, 同時清空自己,
- //# 時間複雜度中的M是 `tree2` 所擁有的資料數
- void moveTo(SplayTree* __tree2);
-
-
- //#|const|lowerBound|(Key const& `k`)|Element|O(logN)
- //#|找出第一個(最小的) Element且 `k` <= 它的 Key, 並且回傳之.
- //# 找不到的話回傳 `this->end()`
- Element lowerBound(Key const& __key) const;
-
-
- //#|const|lowerBound|(Key const& `k`)|Element|O(logN)
- //#|找出第一個(最小的) Element且 `k` < 它的 Key, 並且回傳之.
- //# 找不到的話回傳 `this->end()`
- Element upperBound(Key const& __key) const;
-
-
- //#|const|lowerBound|(Key const& `k`)|Element|O(logN)
- //#|找出第一個(最小的) Element且 `k` >= 它的 Key, 並且回傳之.
- //# 找不到的話回傳 `this->end()`
- Element rLowerBound(Key const& __key) const;
-
-
- //#|const|lowerBound|(Key const& `k`)|Element|O(logN)
- //#|找出第一個(最小的) Element且 `k` > 它的 Key, 並且回傳之.
- //# 找不到的話回傳 `this->end()`
- Element rUpperBound(Key const& __key) const;
-
-
- //#|const|find|(Key const& `k`)|Element|O(logN)
- //#|找出 Key= `k` 的Elemenet 並回傳. 找不到的話回傳 `this->end()`
- Element find (Key const& __key) const;
-
-
- //#|const|order|(size_t `ord`)|Element|O(logN)
- //#|將Elements依照Key由小到大排序, 回傳第 `ord` 個Element (由0算起).
- //# 其中如果 `ord` > N - 1, 則會回傳 `this->last()`
- Element order(size_t __order) const;
-
-
- //#|const|first|(size_t `ord`)|Element|O(logN)
- //#|回傳Key最小的Element, 如果SplayTree為空, 則回傳 `this->end()`
- Element first() const;
-
-
- //#|const|last|(size_t `ord`)|Element|O(logN)
- //#|回傳Key最大的Element, 如果SplayTree為空, 則回傳 `this->end()`
- Element last() const;
-
-
- //#|const|end|()|Element|O(1)
- //#|回傳一個指向NULL的Element, 以供 `find` , `order` , `first`
- //# , `last` 等判斷是否有找到相對應的Element
- Element end() const;
-
-
- //#|const|size|()|size_t|O(1)| 回傳資料數
- size_t size() const;
-
-
- //#|const|size|()|bool|O(1)| 回傳是否為空
- bool empty() const;
-
-
- //#||clear|()|void|O(N)| 清空資料
- void clear();
-
-
- //#||insert|(Key const& `key`,\Value const& `value`)|bool|O(logN)
- //#|檢查是否已有Element的Key 為 `key`, 若有則回傳 `false` , 否則將
- //# 一個 (Key -> Value) = (`key` -> `value`)的Element加入, 並回傳 `true`
- //# 將所有Element的Key同加上 `delta`
- bool insert(Key const& __key, Value const& __value);
-
-
- //#||erase|(Key const& `key`)|bool|O(logN)
- //#|檢查是否已有Element的Key 為 `key`, 若有則刪除之, 並回傳 `true`,
- //# 否則則回傳 `false`
- bool erase(Key const& __key);
-
-
- //#||keyOffset|(Key const& `delta`)|void|O(1)
- //#|將所有Element的Key同加上 `delta`
- void keyOffset(Key const& __delta);
-
-
- //#||operator[]|(Key const& `key`)|Value&|O(logN)
- //#|檢查是否已有Element的Key 為 `key`, 若有則回傳相對應的Value的Reference
- //# 否則先執行 `insert(key, Value())` 再回傳相對應的Reference
- Value& operator[](Key const& __key);
-
-
- //#||splitOut|(Key const& `upper_bound`,\SplayTree* `tree2`)|void
- //#|O(logN) + O(M)
- //#|將 `tree2` 清空, 再將所有Key > `upper_bound` 的Element都丟到 `tree2`
- void splitOut(Key const& __upper_bound, SplayTree* __right);
-
-
- //#||mergeAfter|(SplayTree* `tree2`)|void|O(logN) + O(logM)
- //#|檢查是否 `this` 中的 Key 都小於 `tree2` 中的Key, 是的話把 `tree2`
- //# 中的 Element 都搬到 `this` , 同時清空 `tree2` , 回傳 `true`. 否則
- //# 回傳 `false`
- bool mergeAfter(SplayTree* __tree2);
-
-
- //#||merge|(SplayTree* `tree2`)|void|O(logN) + O(logM)
- //#|檢查是否 `this` 中的 Key 都小於 `tree2` 中的Key 或者
- //# 是否 `this` 中的 Key 都大於 `tree2` 中的Key, 是的話把 `tree2`
- //# 中的 Element 都搬到 `this` , 同時清空 `tree2` , 回傳 `true`. 否則
- //# 回傳 `false`
- bool merge(SplayTree* __tree2);
-
-
- //#|=====================================================================
+#include "../math/utility.h"
+
+namespace meow {
+
+/*!
+ * @brief
+ *
+ * 是一種神乎其技的資料結構, 維護一堆 Key->Value . 並且支援
+ * 一些 \c std::map 難以快速實踐的操作, 如 \c split , \c merge , \c keyOffset
+ *
+ * Template Class Operators Request
+ * --------------------------------
+ *
+ * |const?|Typename|Operator | Parameters |Return Type | Description |
+ * |-----:|:------:|----------:|:-------------|:----------:|:------------------|
+ * |const |Key |operator+ |(Key \c k) | Key |相加 |
+ * |const |Key |operator< |(Key \c k) | bool |大小比較 |
+ * | |Key |operator= |(Key \c k) | Key |copy oper |
+ * | |Key |Key |(int \c n) | |構子,\c n 永遠是0 |
+ * | |Value | Value |( ) | |建構子 |
+ *
+ * @note:
+ * -假設現在有兩個SplayTree `A` 和 `B`, 則:
+ * -執行 `B.moveTo(&A)` 後 `B` 會變成空的, `A` 原本擁有的資料也會覆蓋掉
+ * -行 `A.merge(&B)` 或 `A.mergeAfter(&B)` 後
+ * 如果檢查發現確實可以merge, 則之後 `B` 會變成空的
+ *
+ * @author cat_leopard
+ */
+template<class Key, class Value>
+class SplayTree {
+private:
+ struct Node {
+ Key key_;
+ Key keyOffset_;
+ Value value_;
+ size_t size_;
+ Node* parent_;
+ Node* child_[2];
+
+ Node(Key const& key, Value const& value):
+ key_(key), keyOffset_(0), value_(value) {
+ size_ = 1;
+ parent_ = NULL;
+ child_[0] = NULL;
+ child_[1] = NULL;
+ }
+ //
+ void keyOffset(Key const& delta) {
+ key_ = key_ + delta;
+ keyOffset_ = keyOffset_ + delta;
+ }
+ void syncDown() const {
+ for (size_t i = 0; i < 2; i++) {
+ if (child_[i] == NULL) continue;
+ child_[i]->keyOffset(keyOffset_);
+ }
+ ((Node*)this)->keyOffset_ = Key(0);
+ }
+ void syncUp() const {
+ ((Node*)this)->size_ = 1;
+ for (size_t i = 0; i < 2; i++) {
+ if (child_[i] == NULL) continue;
+ ((Node*)this)->size_ += child_[i]->size_;
+ }
+ }
};
- //#
- //#[NOTE]
- //#========================================
- //# * 假設現在有兩個SplayTree `A` 和 `B`, 則:
- //# ** 執行 `B.moveTo(&A)` 後 `B` 會變成空的, `A` 原本擁有的資料也會覆蓋掉
- //# ** 執行 `A.merge(&B)` 或 `A.mergeAfter(&B)` 後
- //# 如果檢查發現確實可以merge, 則之後 `B` 會變成空的
- //#========================================
- //#
- //# '''
- //#
-}
-#include "SplayTree.hpp"
+ Node* root_;
+
+ //! @brief 指定左子or右子, 連接parent<--->child
+ void connect(Node const* parent, size_t left_right, Node const* child) const {
+ Node* p = (Node*)parent;
+ Node* c = (Node*)child;
+ if (p != NULL) p->child_[left_right] = c;
+ if (c != NULL) c->parent_ = p;
+ }
+
+ //! @brief 一路往上轉
+ Node const* splay(Node const* node) const {
+ if (node != NULL && node->parent_ != NULL) {
+ for (const Node *g_grand, *grand, *parent, *child = node; ; ) {
+ g_grand = (grand = parent = child->parent_)->parent_;
+ size_t pc = (parent->child_[0] == child ? 0 : 1);
+ connect(parent, pc, child->child_[!pc]);
+ connect(child , !pc, parent);
+ if (g_grand != NULL) {
+ g_grand = (grand = g_grand)->parent_;
+ size_t gp = (grand->child_[0] == parent ? 0 : 1);
+ Node const* who = (pc == gp ? parent : child);
+ connect(grand, gp, who->child_[!gp]);
+ connect(who , !gp, grand);
+ grand->syncUp();
+ }
+ parent->syncUp();
+ child ->syncUp();
+ if (g_grand == NULL) {
+ connect(NULL, 0, child);
+ break;
+ }
+ connect(g_grand, (g_grand->child_[0] == grand ? 0 : 1), child);
+ }
+ }
+ return (((SplayTree*)this)->root_ = (Node*)node);
+ }
+
+ void clear(Node* node) {
+ if (node == NULL) return ;
+ clear(node->child_[0]);
+ clear(node->child_[1]);
+ delete node;
+ }
+
+ Node* dup(Node* node2) {
+ if (node2 == NULL) return NULL;
+ node2->syncDown();
+ Node* node = new Node(node2->key_, node2->value_);
+ connect(node, 0, dup(node2->child_[0]));
+ connect(node, 1, dup(node2->child_[1]));
+ node->syncUp();
+ return node;
+ }
+
+ Node const* findKey(Node const* node, Key const& key) const {
+ Node const* ret = node;
+ while (node != NULL) {
+ node->syncDown();
+ ret = node;
+ if (!(key < node->key_)) {
+ if (!(node->key_< key)) break;
+ node = node->child_[1];
+ }
+ else {
+ node = node->child_[0];
+ }
+ }
+ return ret;
+ }
+ Node const* findMinMax(Node const* node, bool minimum) const {
+ Node const* ret = node;
+ for (int i = minimum ? 0 : 1; node != NULL; node = node->child_[i]) {
+ node->syncDown();
+ ret = node;
+ }
+ return ret;
+ }
+ Node const* findOrder(Node const* node, size_t order) const {
+ Node const* ret = node;
+ while (node != NULL) {
+ node->syncDown();
+ ret = node;
+ size_t ord = 1 + (node->child_[0] == NULL ? 0 : node->child_[0]->size_);
+ if (ord == order) return ret;
+ else if(ord < order){ node = node->child_[1]; order -= ord; }
+ else { node = node->child_[0]; }
+ }
+ return ret;
+ }
+
+ void split(Node* root, Node** left, Node** right) {
+ if (root == NULL) { *left = NULL; *right = NULL; return ; }
+ root->syncDown();
+ *left = root;
+ *right = root->child_[1];
+ if (*right != NULL) {
+ (*left )->child_[1] = NULL;
+ (*right)->parent_ = NULL;
+ (*left )->syncUp();
+ }
+ }
+ Node* merge(Node* left, Node* right) {
+ if (left == NULL) return right;
+ if (right == NULL) return left ;
+ left->syncDown();
+ connect(left, 1, right);
+ left->syncUp();
+ return left;
+ }
+public:
+ /*!
+ * @brief 類似 \c stl 的 \c iterator ,不過這邊叫做\c Element
+ *
+ * 用來當作回傳資料的媒介
+ */
+ class Element{
+ private:
+ typedef std::pair<Key const&, Value&> Entry;
+ Entry* entry_;
+ Node * node_;
+ //
+ void reset(Node* node) {
+ node_ = node;
+ delete entry_;
+ entry_ = (node == NULL ? NULL : new Entry(node->key_, node->value_));
+ }
+ public:
+ Element(): entry_(NULL), node_(NULL) {
+ }
+ Element(Node* node): entry_(NULL), node_(NULL) {
+ reset(node);
+ }
+ Element(Element const& element2): entry_(NULL), node_(NULL) {
+ reset(element2.node_);
+ }
+ ~Element(){
+ delete entry_;
+ }
+
+ //! @brief 複製資料
+ Element& copyFrom(Element const& e) {
+ reset(e.node_);
+ return *this;
+ }
+
+ //! @brief 比對兩者是否為指向同一個Entry
+ bool same(Element const& e2) const {
+ return (node_ == e2.node_);
+ }
+
+ //! @brief same as copyFrom
+ Element& operator=(Element const& e2) {
+ return copyFrom(e2);
+ }
+
+ //! @brief 重導至\c std::pair<Key \c const&,\c Value&>*
+ Entry* operator->() {
+ return entry_;
+ }
+
+ //! @brief 重導至\c std::pair<Key \c const&,\c Value&>&
+ Entry& operator*() {
+ return *entry_;
+ }
+
+ //! @brief same as \c same(e2)
+ bool operator==(Element const& e2) const{
+ return same(e2);
+ }
+
+ //! @brief same as \c !same(e2)
+ bool operator!=(Element const& e2) const{
+ return !same(e2);
+ }
+ };
+
+ //! @brief constructor
+ SplayTree(): root_(NULL) {
+ }
+
+ //! @brief constructor, 複製資料
+ SplayTree(SplayTree const& tree2):
+ root_(dup((Node*)(tree2.root_))) {
+ }
+
+ //! @brief destructor
+ ~SplayTree(){
+ clear(root_);
+ }
+
+ /*!
+ * @brief 複製資料
+ */
+ SplayTree& copyFrom(SplayTree const& tree2) {
+ clear(root_);
+ root_ = dup((Node*)(tree2.root_));
+ return *this;
+ }
+
+ /*!
+ * @brief 將資料都丟到 \c tree2 身上, 並且清空自己
+ */
+ void moveTo(SplayTree* tree2) {
+ tree2->clear();
+ tree2->root_ = root_;
+ root_ = NULL;
+ }
+
+ /*!
+ * @brief 找出第一個(最小的) Element且 \c k <= 它的 Key, 並且回傳之.
+ *
+ * 找不到的話回傳 \c this->end()
+ */
+ Element lowerBound(Key const& key) const {
+ splay(findKey(root_, key));
+ if (root_ == NULL || !(root_->key_ < key)) return Element(root_);
+ if (root_->child_[1] == NULL) return Element(NULL);
+ splay(findMinMax(root_->child_[1], true));
+ return Element(root_);
+ }
+
+ /*!
+ * @brief 找出第一個(最小的) Element且 \c k < 它的 Key, 並且回傳之.
+ *
+ * 找不到的話回傳 \c this->end()
+ */
+ Element upperBound(Key const& key) const {
+ splay(findKey(root_, key));
+ if (root_ == NULL || key < root_->key_) return Element(root_);
+ if (root_->child_[1] == NULL) return Element(NULL);
+ splay(findMinMax(root_->child_[1], true));
+ return Element(root_);
+ }
+
+ /*!
+ * @brief 找出第一個(最小的) Element且 \c k >= 它的 Key, 並且回傳之.
+ *
+ * 找不到的話回傳 \c this->end()
+ */
+ Element rLowerBound(Key const& key) const {
+ splay(findKey(root_, key));
+ if (root_ == NULL || !(key < root_->key_)) return Element(root_);
+ if (root_->child_[0] == NULL) return Element(NULL);
+ splay(findMinMax(root_->child_[0], false));
+ return Element(root_);
+ }
+
+ /*!
+ * @brief 找出第一個(最小的) Element且 \c k > 它的 Key, 並且回傳之.
+ *
+ * 找不到的話回傳 \c this->end()
+ */
+ Element rUpperBound(Key const& key) const {
+ splay(findKey(root_, key));
+ if (root_ == NULL || root_->key_ < key) return Element(root_);
+ if (root_->child_[0] == NULL) return Element(NULL);
+ splay(findMinMax(root_->child_[0], false));
+ return Element(root_);
+ }
+
+ /*!
+ * @brief 找出 Key= \c k 的Elemenet 並回傳. 找不到的話回傳 \c this->end()
+ */
+ Element find(Key const& key) const {
+ splay(findKey(root_, key));
+ if (root_ != NULL && !(key < root_->key_) && !(root_->key_ < key)) {
+ return Element(root_);
+ }
+ return Element(NULL);
+ }
+
+ /*!
+ * @brief 將Elements依照Key由小到大排序, 回傳第 \c ord 個Element (由0算起).
+ *
+ * 其中如果 \c ord>N-1, 則會回傳 \c this->last()
+ */
+ Element order(size_t order) const {
+ if (root_ == NULL || order >= root_->size_) return Element(NULL);
+ splay(findOrder(root_, order + 1));
+ return Element(root_);
+ }
+
+ /*!
+ * @brief 回傳Key最小的Element, 如果SplayTree為空, 則回傳 \c this->end()
+ */
+ Element first() const {
+ splay(findMinMax(root_, true));
+ return Element(root_);
+ }
+
+ /*!
+ * @brief 回傳Key最大的Element, 如果SplayTree為空, 則回傳 \c this->end()
+ */
+ Element last() const {
+ splay(findMinMax(root_, false));
+ return Element(root_);
+ }
+
+ /*!
+ * @brief 回傳一個指向NULL的Element,
+ *
+ * 以供 \c find ,\c order ,\c first ,\c last 等判斷是否有找到相對應的Element
+ */
+ Element end() const {
+ return Element(NULL);
+ }
+
+ /*!
+ * @brief 回傳資料個數
+ */
+ size_t size() const {
+ return (root_ == NULL ? 0 : root_->size_);
+ }
+
+ /*!
+ * @brief 回傳是否為空
+ */
+ bool empty() const{
+ return (size() == 0);
+ }
+
+ /*!
+ * @brief 清空
+ */
+ void clear() {
+ clear(root_);
+ root_ = NULL;
+ }
+
+ /*!
+ * @brief 插入一組\c (Key ---> \c Value)
+ *
+ * 檢查是否已有Element的Key 為 \c key, 若有則回傳 \c false , 否則將
+ * 一個 (Key -> Value) = (\c key -> \c value)的Element加入, 並回傳 \c true
+ */
+ bool insert(Key const& key, Value const& value) {
+ if (root_ == NULL) {
+ root_ = new Node(key, value);
+ }
+ else {
+ Node* parent = (Node*)findKey(root_, key);
+ if (!(parent->key_ < key) && !(key < parent->key_)) {
+ splay(parent);
+ return false;
+ }
+ Node* new_node = new Node(key, value);
+ connect(parent, (parent->key_ < key ? 1 : 0), new_node);
+ parent->syncUp();
+ splay(new_node);
+ }
+ return true;
+ }
+
+ /*!
+ * @brief 刪除一組資料
+ *
+ * 檢查是否已有Element的Key 為 \c key, 若有則刪除之, 並回傳 \c true,
+ * 否則則回傳 \c false
+ */
+ bool erase(Key const& key) {
+ if (root_ == NULL) return false;
+ Node* body = (Node*)findKey(root_, key);
+ if (body->key_ < key || key < body->key_) {
+ splay(body);
+ return false;
+ }
+ Node* ghost;
+ if (body->child_[1] == NULL) {
+ ghost = body->child_[0];
+ if (ghost != NULL) ghost->syncDown();
+ }
+ else {
+ ghost = (Node*)findMinMax(body->child_[1], true);
+ connect(ghost, 0, body->child_[0]);
+ if (ghost != body->child_[1]) {
+ connect(ghost->parent_, 0, ghost->child_[1]);
+ connect(ghost, 1, body->child_[1]);
+ for (Node* a = ghost->parent_; a != ghost; a = a->parent_)
+ a->syncUp();
+ }
+ ghost->syncUp();
+ }
+ Node* parent = body->parent_;
+ connect(parent, parent != NULL && parent->child_[0] == body ? 0 : 1, ghost);
+ delete body;
+ splay(ghost != NULL ? ghost : parent);
+ return true;
+ }
+
+ /*!
+ * @brief 將所有Element的Key同加上 \c delta
+ */
+ void keyOffset(Key const& delta) {
+ if (root_ != NULL) {
+ root_->keyOffset(delta);
+ }
+ }
+
+ /*!
+ * @brief 將\c tree2 清空, 再將所有Key > \c upper_bound 的Element都丟過去
+ */
+ void splitOut(Key const& upper_bound, SplayTree* right) {
+ right->clear();
+ if (rLowerBound(upper_bound) != end()) {
+ split(root_, &root_, &(right->root_));
+ }
+ else {
+ right->root_ = root_;
+ root_ = NULL;
+ }
+ }
+
+ /*!
+ * @brief 合併
+ *
+ * 檢查是否自己中的 Key 都小於 \c tree2 中的Key, 是的話把 \c tree2`
+ * 中的 Element 都搬到自己這, 同時清空 \c tree2 , 否則回傳 \c false
+ */
+ bool mergeAfter(SplayTree* tree2) {
+ if (root_ == NULL || tree2->root_ == NULL ||
+ last()->first < tree2->first()->first) {
+ root_ = merge(root_, tree2->root_);
+ tree2->root_ = NULL;
+ return true;
+ }
+ return false;
+ }
+
+ /*!
+ * @brief 合併
+ *
+ * 檢查是否自己中的 Key 都小於 \c tree2 中的Key, 或是完全相反,
+ * 是的話把 \c tree2`中的 Element 都搬到自己這,
+ * 同時清空 \c tree2 , 否則回傳 \c false
+ */
+ bool merge(SplayTree* tree2) {
+ if (root_ == NULL || tree2->root_ == NULL ||
+ last()->first < tree2->first()->first) {
+ root_ = merge(root_, tree2->root_);
+ }
+ else if(tree2->last()->first < first()->first) {
+ root_ = merge(tree2->root_, root_);
+ }
+ else {
+ return false;
+ }
+ tree2->root_ = NULL;
+ return true;
+ }
+
+ /*!
+ * @brief 就像\c stl::map::operator[]
+ *
+ * 會先檢查是否已有Element的Key 為 \c key, 若有則回傳相對應的Value的Reference
+ * 否則先執行 \c insert(key,Value()) 再回傳相對應的Reference
+ */
+ Value& operator[](Key const& key) {
+ if (find(key) == end()) insert(key, Value());
+ return root_->value_;
+ }
+
+ //! @brief same as \c copyFrom(tree2)
+ SplayTree& operator=(SplayTree const& tree2) {
+ return copyFrom(tree2);
+ }
+};
+
+/*!
+ * @brief
+ *
+ * 基本上跟SplayTree一樣, 不過這邊結合線段樹, 多了區間操作
+ * (線段樹相關operator定義請見 \c SegmentTree )
+ *
+ * Template Class Operators Request
+ * --------------------------------
+ *
+ * |const?|Typename|Operator | Parameters |Return Type | Description |
+ * |-----:|:------:|----------:|:-------------|:----------:|:------------------|
+ * |const |Key |operator+ |(Key \c k) | Key |相加 |
+ * |const |Key |operator< |(Key \c k) | bool |大小比較 |
+ * | |Key |operator= |(Key \c k) | Key |copy oper |
+ * | |Key |Key |(int \c n) | |構子,\c n 永遠是0 |
+ * | |Value | Value |( ) | |建構子 |
+ *
+ * @note:
+ * -假設現在有兩個SplayTree `A` 和 `B`, 則:
+ * -執行 `B.moveTo(&A)` 後 `B` 會變成空的, `A` 原本擁有的資料也會覆蓋掉
+ * -行 `A.merge(&B)` 或 `A.mergeAfter(&B)` 後
+ * 如果檢查發現確實可以merge, 則之後 `B` 會變成空的
+ *
+ * @author cat_leopard
+ */
+template<class Key, class Value>
+class SplayTree_Range {
+private:
+ struct Node {
+ Value valueOffset_;
+ Value range_;
+ Key key_;
+ Key keyOffset_;
+ Value value_;
+ bool same_;
+ size_t size_;
+ Node* parent_;
+ Node* child_[2];
+
+ Node(Key const& key, Value const& value):
+ valueOffset_(0), range_(value),
+ key_(key), keyOffset_(0), value_(value) {
+ same_ = false;
+ size_ = 1;
+ parent_ = NULL;
+ child_[0] = NULL;
+ child_[1] = NULL;
+ }
+ //
+ void keyOffset(Key const& delta) {
+ key_ = key_ + delta;
+ keyOffset_ = keyOffset_ + delta;
+ }
+ void valueUpdate(Value const& delta, bool over) {
+ if(over) {
+ value_ = delta * size_;
+ valueOffset_ = delta;
+ range_ = delta * size_;
+ same_ = true;
+ }
+ else {
+ value_ = value_ + delta * size_;
+ valueOffset_ = valueOffset_ + delta;
+ range_ = range_ + delta * size_;
+ }
+ }
+ void syncDown() const {
+ for (size_t i = 0; i < 2; i++) {
+ if (child_[i] == NULL) continue;
+ child_[i]->keyOffset(keyOffset_);
+ child_[i]->valueUpdate(valueOffset_, same_);
+ }
+ ((Node*)this)->keyOffset_ = Key(0);
+ ((Node*)this)->valueOffset_ = Value(0);
+ ((Node*)this)->same_ = false;
+ }
+ void syncUp() const {
+ ((Node*)this)->size_ = 1;
+ Value* v[3] = {&(((Node*)this)->value_), NULL, NULL};
+ size_t vct = 1;
+ for (size_t i = 0; i < 2; i++) {
+ if (child_[i] == NULL) continue;
+ ((Node*)this)->size_ += child_[i]->size_;
+ v[vct++] = &(child_[i]->range_);
+ }
+ if (vct == 1) ((Node*)this)->range_ = (*v[0]);
+ else if(vct == 2) ((Node*)this)->range_ = (*v[0]) | (*v[1]);
+ else ((Node*)this)->range_ = (*v[0]) | (*v[1]) | (*v[2]);
+ }
+ };
+
+ Node* root_;
+
+ //! @brief 指定左子or右子, 連接parent<--->child
+ void connect(Node const* parent, size_t left_right, Node const* child) const {
+ Node* p = (Node*)parent;
+ Node* c = (Node*)child;
+ if (p != NULL) p->child_[left_right] = c;
+ if (c != NULL) c->parent_ = p;
+ }
+
+ //! @brief 一路往上轉
+ Node const* splay(Node const* node) const {
+ if (node != NULL && node->parent_ != NULL) {
+ for (const Node *g_grand, *grand, *parent, *child = node; ; ) {
+ g_grand = (grand = parent = child->parent_)->parent_;
+ size_t pc = (parent->child_[0] == child ? 0 : 1);
+ connect(parent, pc, child->child_[!pc]);
+ connect(child , !pc, parent);
+ if (g_grand != NULL) {
+ g_grand = (grand = g_grand)->parent_;
+ size_t gp = (grand->child_[0] == parent ? 0 : 1);
+ Node const* who = (pc == gp ? parent : child);
+ connect(grand, gp, who->child_[!gp]);
+ connect(who , !gp, grand);
+ grand->syncUp();
+ }
+ parent->syncUp();
+ child ->syncUp();
+ if (g_grand == NULL) {
+ connect(NULL, 0, child);
+ break;
+ }
+ connect(g_grand, (g_grand->child_[0] == grand ? 0 : 1), child);
+ }
+ }
+ return (((SplayTree_Range*)this)->root_ = (Node*)node);
+ }
+
+ void clear(Node* node) {
+ if (node == NULL) return ;
+ clear(node->child_[0]);
+ clear(node->child_[1]);
+ delete node;
+ }
+
+ Node* dup(Node* node2) {
+ if (node2 == NULL) return NULL;
+ node2->syncDown();
+ Node* node = new Node(node2->key_, node2->value_);
+ connect(node, 0, dup(node2->child_[0]));
+ connect(node, 1, dup(node2->child_[1]));
+ node->syncUp();
+ return node;
+ }
+
+ Node const* findKey(Node const* node, Key const& key) const {
+ Node const* ret = node;
+ while (node != NULL) {
+ node->syncDown();
+ ret = node;
+ if (!(key < node->key_)) {
+ if (!(node->key_< key)) break;
+ node = node->child_[1];
+ }
+ else {
+ node = node->child_[0];
+ }
+ }
+ return ret;
+ }
+ Node const* findMinMax(Node const* node, bool minimum) const {
+ Node const* ret = node;
+ for (int i = minimum ? 0 : 1; node != NULL; node = node->child_[i]) {
+ node->syncDown();
+ ret = node;
+ }
+ return ret;
+ }
+ Node const* findOrder(Node const* node, size_t order) const {
+ Node const* ret = node;
+ while (node != NULL) {
+ node->syncDown();
+ ret = node;
+ size_t ord = 1 + (node->child_[0] == NULL ? 0 : node->child_[0]->size_);
+ if (ord == order) return ret;
+ else if(ord < order){ node = node->child_[1]; order -= ord; }
+ else { node = node->child_[0]; }
+ }
+ return ret;
+ }
+
+ void split(Node* root, Node** left, Node** right) {
+ if (root == NULL) { *left = NULL; *right = NULL; return ; }
+ root->syncDown();
+ *left = root;
+ *right = root->child_[1];
+ if (*right != NULL) {
+ (*left )->child_[1] = NULL;
+ (*right)->parent_ = NULL;
+ (*left )->syncUp();
+ }
+ }
+ Node* merge(Node* left, Node* right) {
+ if (left == NULL) return right;
+ if (right == NULL) return left ;
+ left->syncDown();
+ connect(left, 1, right);
+ left->syncUp();
+ return left;
+ }
+public:
+ /*!
+ * @brief 類似 \c stl 的 \c iterator ,不過這邊叫做\c Element
+ *
+ * 用來當作回傳資料的媒介
+ */
+ class Element{
+ private:
+ typedef std::pair<Key const&, Value&> Entry;
+ Entry* entry_;
+ Node * node_;
+ //
+ void reset(Node* node) {
+ node_ = node;
+ delete entry_;
+ entry_ = (node == NULL ? NULL : new Entry(node->key_, node->value_));
+ }
+ public:
+ Element(): entry_(NULL), node_(NULL) {
+ }
+ Element(Node* node): entry_(NULL), node_(NULL) {
+ reset(node);
+ }
+ Element(Element const& element2): entry_(NULL), node_(NULL) {
+ reset(element2.node_);
+ }
+ ~Element(){
+ delete entry_;
+ }
+
+ //! @brief 複製資料
+ Element& copyFrom(Element const& e) {
+ reset(e.node_);
+ return *this;
+ }
+
+ //! @brief 比對兩者是否為指向同一個Entry
+ bool same(Element const& e2) const {
+ return (node_ == e2.node_);
+ }
+
+ //! @brief same as copyFrom
+ Element& operator=(Element const& e2) {
+ return copyFrom(e2);
+ }
+
+ //! @brief 重導至\c std::pair<Key \c const&,\c Value&>*
+ Entry* operator->() {
+ return entry_;
+ }
+
+ //! @brief 重導至\c std::pair<Key \c const&,\c Value&>&
+ Entry& operator*() {
+ return *entry_;
+ }
+
+ //! @brief same as \c same(e2)
+ bool operator==(Element const& e2) const{
+ return same(e2);
+ }
+
+ //! @brief same as \c !same(e2)
+ bool operator!=(Element const& e2) const{
+ return !same(e2);
+ }
+ };
+
+ //! @brief constructor
+ SplayTree_Range(): root_(NULL) {
+ }
+
+ //! @brief constructor, 複製資料
+ SplayTree_Range(SplayTree_Range const& tree2):
+ root_(dup((Node*)(tree2.root_))) {
+ }
+
+ //! @brief destructor
+ ~SplayTree_Range() {
+ clear(root_);
+ }
+
+ /*!
+ * @brief 複製資料
+ */
+ SplayTree_Range& copyFrom(SplayTree_Range const& tree2) {
+ clear(root_);
+ root_ = dup((Node*)(tree2.root_));
+ return *this;
+ }
+
+ /*!
+ * @brief 將資料都丟到 \c tree2 身上, 並且清空自己
+ */
+ void moveTo(SplayTree_Range* tree2) {
+ tree2->clear();
+ tree2->root_ = root_;
+ root_ = NULL;
+ }
+
+ /*!
+ * @brief 找出第一個(最小的) Element且 \c k <= 它的 Key, 並且回傳之.
+ *
+ * 找不到的話回傳 \c this->end()
+ */
+ Element lowerBound(Key const& key) const {
+ splay(findKey(root_, key));
+ if (root_ == NULL || !(root_->key_ < key)) return Element(root_);
+ if (root_->child_[1] == NULL) return Element(NULL);
+ splay(findMinMax(root_->child_[1], true));
+ return Element(root_);
+ }
+
+ /*!
+ * @brief 找出第一個(最小的) Element且 \c k < 它的 Key, 並且回傳之.
+ *
+ * 找不到的話回傳 \c this->end()
+ */
+ Element upperBound(Key const& key) const {
+ splay(findKey(root_, key));
+ if (root_ == NULL || key < root_->key_) return Element(root_);
+ if (root_->child_[1] == NULL) return Element(NULL);
+ splay(findMinMax(root_->child_[1], true));
+ return Element(root_);
+ }
+
+ /*!
+ * @brief 找出第一個(最小的) Element且 \c k >= 它的 Key, 並且回傳之.
+ *
+ * 找不到的話回傳 \c this->end()
+ */
+ Element rLowerBound(Key const& key) const {
+ splay(findKey(root_, key));
+ if (root_ == NULL || !(key < root_->key_)) return Element(root_);
+ if (root_->child_[0] == NULL) return Element(NULL);
+ splay(findMinMax(root_->child_[0], false));
+ return Element(root_);
+ }
+
+ /*!
+ * @brief 找出第一個(最小的) Element且 \c k > 它的 Key, 並且回傳之.
+ *
+ * 找不到的話回傳 \c this->end()
+ */
+ Element rUpperBound(Key const& key) const {
+ splay(findKey(root_, key));
+ if (root_ == NULL || root_->key_ < key) return Element(root_);
+ if (root_->child_[0] == NULL) return Element(NULL);
+ splay(findMinMax(root_->child_[0], false));
+ return Element(root_);
+ }
+
+ /*!
+ * @brief 找出 Key= \c k 的Elemenet 並回傳. 找不到的話回傳 \c this->end()
+ */
+ Element find(Key const& key) const {
+ splay(findKey(root_, key));
+ if (root_ != NULL && !(key < root_->key_) && !(root_->key_ < key)) {
+ return Element(root_);
+ }
+ return Element(NULL);
+ }
+
+ /*!
+ * @brief 將Elements依照Key由小到大排序, 回傳第 \c ord 個Element (由0算起).
+ *
+ * 其中如果 \c ord>N-1, 則會回傳 \c this->last()
+ */
+ Element order(size_t order) const {
+ if (root_ == NULL || order >= root_->size_) return Element(NULL);
+ splay(findOrder(root_, order + 1));
+ return Element(root_);
+ }
+
+ /*!
+ * @brief 回傳Key最小的Element, 如果SplayTree為空, 則回傳 \c this->end()
+ */
+ Element first() const {
+ splay(findMinMax(root_, true));
+ return Element(root_);
+ }
+
+ /*!
+ * @brief 回傳Key最大的Element, 如果SplayTree為空, 則回傳 \c this->end()
+ */
+ Element last() const {
+ splay(findMinMax(root_, false));
+ return Element(root_);
+ }
+
+ /*!
+ * @brief 回傳一個指向NULL的Element,
+ *
+ * 以供 \c find ,\c order ,\c first ,\c last 等判斷是否有找到相對應的Element
+ */
+ Element end() const {
+ return Element(NULL);
+ }
+
+ /*!
+ * @brief 回傳資料個數
+ */
+ size_t size() const {
+ return (root_ == NULL ? 0 : root_->size_);
+ }
+
+ /*!
+ * @brief 回傳是否為空
+ */
+ bool empty() const{
+ return (size() == 0);
+ }
+
+ /*!
+ * @brief 查找
+ *
+ * 詢問目前整個range的值
+ */
+ Value query() const {
+ if (root_ == NULL) return Value(0);
+ return root_->range_;
+ }
+
+ /*!
+ * @brief 查找
+ *
+ * 詢問給定range的值
+ */
+ Value query(Key const& first, Key const& last) const {
+ SplayTree_Range* self = (SplayTree_Range*)this;
+ Node* tmp;
+ rUpperBound(first);
+ self->split(self->root_, &tmp, &(self->root_));
+ upperBound(last);
+ Value ret(0);
+ if (root_ != NULL && root_->child_[0] != NULL) {
+ ret = root_->child_[0]->range_;
+ }
+ self->root_ = self->merge(tmp, self->root_);
+ return ret;
+ }
+
+ /*!
+ * @brief 清空
+ */
+ void clear() {
+ clear(root_);
+ root_ = NULL;
+ }
+
+ /*!
+ * @brief 插入一組\c (Key ---> \c Value)
+ *
+ * 檢查是否已有Element的Key 為 \c key, 若有則回傳 \c false , 否則將
+ * 一個 (Key -> Value) = (\c key -> \c value)的Element加入, 並回傳 \c true
+ */
+ bool insert(Key const& key, Value const& value) {
+ if (root_ == NULL) {
+ root_ = new Node(key, value);
+ }
+ else {
+ Node* parent = (Node*)findKey(root_, key);
+ if (!(parent->key_ < key) && !(key < parent->key_)) {
+ splay(parent);
+ return false;
+ }
+ Node* new_node = new Node(key, value);
+ connect(parent, (parent->key_ < key ? 1 : 0), new_node);
+ parent->syncUp();
+ splay(new_node);
+ }
+ return true;
+ }
+
+ /*!
+ * @brief 刪除一組資料
+ *
+ * 檢查是否已有Element的Key 為 \c key, 若有則刪除之, 並回傳 \c true,
+ * 否則則回傳 \c false
+ */
+ bool erase(Key const& key) {
+ if (root_ == NULL) return false;
+ Node* body = (Node*)findKey(root_, key);
+ if (body->key_ < key || key < body->key_) {
+ splay(body);
+ return false;
+ }
+ Node* ghost;
+ if (body->child_[1] == NULL) {
+ ghost = body->child_[0];
+ if (ghost != NULL) ghost->syncDown();
+ }
+ else {
+ ghost = (Node*)findMinMax(body->child_[1], true);
+ connect(ghost, 0, body->child_[0]);
+ if (ghost != body->child_[1]) {
+ connect(ghost->parent_, 0, ghost->child_[1]);
+ connect(ghost, 1, body->child_[1]);
+ for (Node* a = ghost->parent_; a != ghost; a = a->parent_)
+ a->syncUp();
+ }
+ ghost->syncUp();
+ }
+ Node* parent = body->parent_;
+ connect(parent, parent != NULL && parent->child_[0] == body ? 0 : 1, ghost);
+ delete body;
+ splay(ghost != NULL ? ghost : parent);
+ return true;
+ }
+
+ /*!
+ * @brief 將所有Element的Key同加上 \c delta
+ */
+ void keyOffset(Key const& delta) {
+ if (root_ != NULL) {
+ root_->keyOffset(delta);
+ }
+ }
+
+ /*!
+ * @brief 將所有Element的Value同加上 \c delta
+ */
+ void valueOffset(Value const& delta){
+ if (root_ != NULL) {
+ root_->valueUpdate(delta, false);
+ }
+ }
+
+ /*!
+ * @brief 將所有Element的Value全部設定成\c value
+ */
+ void valueOverride(Value const& value){
+ if(root_ != NULL){
+ root_->valueUpdate(value, true);
+ }
+ }
+
+ /*!
+ * @brief 將\c tree2 清空, 再將所有Key > \c upper_bound 的Element都丟過去
+ */
+ void splitOut(Key const& upper_bound, SplayTree_Range* right) {
+ right->clear();
+ if (rLowerBound(upper_bound) != end()) {
+ split(root_, &root_, &(right->root_));
+ }
+ else {
+ right->root_ = root_;
+ root_ = NULL;
+ }
+ }
+
+ /*!
+ * @brief 合併
+ *
+ * 檢查是否自己中的 Key 都小於 \c tree2 中的Key, 是的話把 \c tree2`
+ * 中的 Element 都搬到自己這, 同時清空 \c tree2 , 否則回傳 \c false
+ */
+ bool mergeAfter(SplayTree_Range* tree2) {
+ if (root_ == NULL || tree2->root_ == NULL ||
+ last()->first < tree2->first()->first) {
+ root_ = merge(root_, tree2->root_);
+ tree2->root_ = NULL;
+ return true;
+ }
+ return false;
+ }
+
+ /*!
+ * @brief 合併
+ *
+ * 檢查是否自己中的 Key 都小於 \c tree2 中的Key, 或是完全相反,
+ * 是的話把 \c tree2`中的 Element 都搬到自己這,
+ * 同時清空 \c tree2 , 否則回傳 \c false
+ */
+ bool merge(SplayTree_Range* tree2) {
+ if (root_ == NULL || tree2->root_ == NULL ||
+ last()->first < tree2->first()->first) {
+ root_ = merge(root_, tree2->root_);
+ }
+ else if(tree2->last()->first < first()->first) {
+ root_ = merge(tree2->root_, root_);
+ }
+ else {
+ return false;
+ }
+ tree2->root_ = NULL;
+ return true;
+ }
+
+ /*!
+ * @brief 就像\c stl::map::operator[]
+ *
+ * 會先檢查是否已有Element的Key 為 \c key, 若有則回傳相對應的Value的Reference
+ * 否則先執行 \c insert(key,Value()) 再回傳相對應的Reference
+ */
+ Value& operator[](Key const& key) {
+ if (find(key) == end()) insert(key, Value());
+ return root_->value_;
+ }
+
+ //! @brief same as \c copyFrom(tree2)
+ SplayTree_Range& operator=(SplayTree_Range const& tree2){
+ return copyFrom(tree2);
+ }
+};
+
+}
#endif // dsa_SplayTree_h__