aboutsummaryrefslogblamecommitdiffstats
path: root/meowpp/dsa/SplayTree.h
blob: f8cdd20be18e8159ae1ddf4a29c1581d4aae4b27 (plain) (tree)
1
2
3
4
5
6





                       















                                                                                               





















                                                                 
                                              
        

                                  













                                                                      







                                                                                      
























                                                      
                                                     
        


















                                                                                   
                                                  




                                                                                  
                                                  




                                                                                   
                                                  




                                                                                  
                                                  



                                                                                    
                                            
























                                                                                          
                           


                                                     
                           


























                                                                                                 
                                          





















                                                                                           

                         
                                                                               
    










                                                                                                




                        
#ifndef   SplayTree_h__
#define   SplayTree_h__

#include "utility.h"

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*  _lChild;
        Node*  _rChild;
        //
        Node(Key const& __key, Value const& __value);
      };
      //
      Node* _root;
      //
      void offsetAdd    (Node* __node, Key const& __delta) const;
      void offsetDown   (Node* __node                    ) const;
      void sizeUpdate   (Node* __node                    ) const;
      void connectLChild(Node* __parent, Node* __child   ) const;
      void connectRChild(Node* __parent, Node* __child   ) const;
      Node const* setRoot(Node* __node) const;
      //
      Node* clear  (Node* __node);
      Node* dup    (Node* __node);
      //
      void rotate(               Node* __parent, Node* __child) const;
      void rotate(Node* __grand, Node* __parent, Node* __child) const;
      Node* splay(Node* __node) const;
      //
      Node* findKey   (Node* __node, Key const& __key) const;
      Node* findMinMax(Node* __node, bool minimum    ) const;
      Node* findOrder (Node* __node, size_t __order  ) const;
      //
      void  split(Node* __root, Node** __left, Node** __right);
      Node* merge(              Node*  __left, Node*  __right);
      //
      void print(Node* __now, int __depth) const;
    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();
      
      
      //#||keyOffset|(Key const& `delta`)|void|O(1)
      //#|將所有Element的Key同加上 `delta`
      void keyOffset(Key const& __delta);
      
      
      //#||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);
      
      
      //#||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);
      //
      //
      void print() const;
      //#|=====================================================================
  };
  //#
  //#[NOTE]
  //#========================================
  //# * 假設現在有兩個SplayTree `A` 和 `B`,  則:
  //# ** 執行 `B.moveTo(&A)` 後 `B` 會變成空的, `A` 原本擁有的資料也會覆蓋掉
  //# ** 執行 `A.merge(&B)` 或 `A.mergeAfter(&B)` 後
  //#    如果檢查發現確實可以merge, 則之後 `B` 會變成空的
  //#========================================
  //#
  //# '''
  //#
}

#include "SplayTree.hpp"

#endif // SplayTree_h__