aboutsummaryrefslogblamecommitdiffstats
path: root/meowpp/dsa/VP_Tree.h
blob: e2daa285ce61595fbe9ccd21c4c9336f86c5ea47 (plain) (tree)
1
2
3
4
5
6
7
8
9





                            


                 
                










                                                                                               



                                                         




































































                                                                                     






































                                                                                
                            


















                                                                                                    



                                             


                                                                                                

                                                          






                                             
                         
#ifndef   dsa_VP_Tree_H__
#define   dsa_VP_Tree_H__

#include "../math/utility.h"

#include <cstdlib>

#include <list>
#include <vector>
#include <queue>

namespace meow{
  //#
  //#=== meow:: *VP_Tree<Vector, Scalar>* (C++ class)
  //#==== Description
  //#  `VP_Tree` 用來維護由 *N個K維度向量所成的集合*, 
  //#  並可於該set中查找 *前i個離給定向量最接近的向量*. +
  //#  不像 `KD_Tree` 二分樹每次都選擇一個維度去分, 分成小的跟大的, 
  //#  `VP_Tree` 每次選一個點, 將資料分成 離這個點近的, 跟離這個點遠的.
  //#  至於怎麼選呢...., 嘛還沒研究, 先random
  //#
  //#  .參考資料連結: 
  //#  * http://stevehanov.ca/blog/index.php?id=130[link]
  //#  * http://pnylab.com/pny/papers/vptree/vptree[link]
  //#
  //#==== 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 |  Vector|operator[] |(size_t `n`) | Scalar     | 取得第 `n` 維度量
  //#|const |  Vector|operator=  |(Vector `v`) | Vector&    | copy operator
  //#|const |  Vector|operator<  |(Vector `v`) | bool       | 權重比較
  //#|const |  Scalar| 'Scalar'  |(int    `n`) | Scalar     | 建構子,
  //#                                                         其中一定`n=0 or 4`
  //#|const |  Scalar|operator*  |(Scalar `s`) | Scalar     | 相乘
  //#|const |  Scalar|operator+  |(Scalar `s`) | Scalar     | 相加
  //#|const |  Scalar|operator-  |(Scalar `s`) | Scalar     | 相差
  //#|const |  Scalar|operator-  |(          ) | Scalar     | 取負號
  //#|const |  Scalar|operator<  |(Scalar `s`) | bool       | 大小比較
  //#|=====================================================================
  //#
  template<class Vector, class Scalar>
  class VP_Tree{
    public:
      //#==== Custom Type Definitions
      //# * `Vectors` <- `std::vector<Vector>`
      //#
      typedef typename std::vector<Vector> Vectors;
    private:
      //
      struct Node{
        size_t _index;
        Scalar _threshold;
        Node*  _nearChild;
        Node*  _farChild;
        Node(size_t __index);
      };
      struct Answer{
        size_t _index;
        Scalar _dist2;
        //
        Answer(size_t __index, Scalar const& __dist2);
        Answer(Answer const& __answer2);
      };
      class AnswerCompare{
        private:
          Vectors const* _vectors;
          bool           _cmpValue;
        public:
          AnswerCompare(Vectors const* __vectors, bool __cmpValue);
          bool operator()(Answer const& __a, Answer const& __b) const;
      };
      typedef std::vector<Answer> AnswerV;
      typedef std::priority_queue<Answer, AnswerV, AnswerCompare> Answers;
      //
      Vectors _vectors;
      Node*   _root;
      size_t  _dimension;
      bool    _needRebuild;
      //
      Scalar distance2(Vector const& __v1, Vector const& __v2) const;
      int distanceCompare(Scalar const& __a2, Scalar const& __b2,
                          Scalar const& __c2) const;
      Scalar split(ssize_t __first, ssize_t __last, size_t __order,
                   Vector const& __center);
      //
      Node* build(ssize_t __first, ssize_t __last);
      void query(Vector const&        __vector,
                 size_t               __k,
                 AnswerCompare const& __cmp,
                 Node const*          __node,
                 Answers*             __out) const;
      void clear(Node* __root);
      Node* dup(Node* __root);
    public:
      VP_Tree();
      VP_Tree(VP_Tree const& __tree2);
      VP_Tree(size_t __dimension);
      ~VP_Tree();
      VP_Tree& operator=(VP_Tree const& __tree2);

      //#==== Support Methods
      //#
      //# * N <- `this` 中擁有的資料數
      //# * D <- `this` 資料維度
      //#
      //#[options="header",width="100%",cols="1>m,3>s,7<,3<,3^,20<",grid="rows"]
      //#|=====================================================================
      //#|Const?|Name | Parameters   | Return_Type| Time_Complexity| Description


      //#||insert|(Vector const& `v`)|void| O(1)
      //#|將向量 `v` 加到set中
      void insert(Vector const& __vector);


      //#||erase|(Vector const& `v`)|bool| O(N)
      //#|將向量 `v` 從set中移除, '~TODO:可以再優化~'
      bool erase (Vector const& __vector);


      //#||build|()|void|O(KN logN) or O(1)
      //#|檢查距上一次 `build()` 至今是否有 `insert/erase` 被呼叫,
      //# 若有, 重新建樹, 否則不做事
      void build();


      //#||forceBuild|()|void|O(KN logN)
      //#|重新建樹
      void forceBuild();


      //#|const|query|(Vector const& `v`,\size_t `i`,\bool `cmp`)|Vectors
      //#|O(logN) ~Expected~
      //#|於set中找尋距離 `v` 前 `i` 近的向量, 並依照由近而遠的順序排序.
      //# 如果有兩個向量 `v1`,`v2` 距離一樣, 且 `cmp` 為 `true` , 則直接依照
      //# `v1 < v2` 來決定誰在前面. 最後回傳一陣列包含所有解.
      Vectors query(Vector const& __vector,
                    size_t        __nearestNumber,
                    bool          __compareWholeVector) const;


      //#||clear|()|void|O(1)
      //#|清空所有資料
      void clear();


      //#||reset|(size_t `dimension`)|size_t|O(1)
      //#|清空所有資料並且指定維度為 `max(1, dimension)` 並且回傳指定後的維度
      size_t reset(size_t __dimension);


      //#|=====================================================================
  };
  //#
  //#[NOTE]
  //#========================================
  //# * 實測結果發覺, 維度小的時候, 比起中規中矩的 `KD_Tree`, `VP_Tree` 有
  //#   'randomp' 於其中, 因此時間複雜度只是期望值 'O(logN)' 但是測資大到
  //#   一定程度, `KD_Tree` 效率會一整個大幅掉下, 但 `VP_Tree` 幾乎不受影響
  //# * 'TODO' `insert()`, `erase()` 算是未完成功能
  //#
  //#========================================
  //#
  //# '''
}

#include "VP_Tree.hpp"

#endif // dsa_VP_Tree_H__