HASH樹


我們先來接受幾個概念:

質數分解定律,任何一個數都可以分解為幾個不同素數額乘積P1,P2,P3...到Pn;

質數分辨定理:

定理一:

  我們選擇n個互不相同的素數p1,p2,p3,p4,p5,....pn;我們定義:

  M=p1*p2*p3*...*pn,m<k1<k2<=m+M,則,對於任意一個pi,(k1 mod Pi)=(k2 mod Pi)總成立;

我們來簡單的正面一下,

  設K=k1-k2;如果(k1 mod pi)=(k2 mod pi) 恆成立,則存在K%pi==0恆成立,所以K=M*s(s>=1)與結論不符

余數分辨定理:

定理2,選取任意n個互不相同的自然數:I1,I2,I3,I4,I5...In;定義LCM為他們的最小公倍數,則存在m<k1<k2<=m+M,則,對於任意一個pi,(k1 mod Pi)=(k2 mod Pi)總成立;這個證明過程模仿定理一。

我們通過分辨定理可以分辨M個連續的數。

分辨算法的評價標准:

狀態和特征:

  分辨也即分辨不同的狀態。分辨一般是先定義一組不同的狀態,然后將這些狀態記錄下來形成特征。由這些特征所形成的空間是特征空間。特征空間的維度就是特征數列的長度。

2.分辨能力:

  分辨能力D,也成分辨范圍,就是可以分辨多少個連續的狀態。在這個范圍內,不存在完全相同的特征數。這些信息既可以用數列記錄下來,也可以通過數據結構記錄下來。

3.沖突概率:

  對於任意一個數,他可能是D范圍內的任意一種狀態,所以沖突的概率為 k=1/D<=1,當D越大,沖突的概率越小。

4.分辨效率

   我 們可以定義分辨效率G=(分辨能力)/(所有特征數的成積)=LCM/M;

  由定理1和2可知,當余數分辨定理的一系列整數互質時G=1,如果有兩個數存在公約數則G<1;

  我們可以對一直數列進行處理,讓他G=1,如果Ik,IJ的最大公約數為GCD,則我們可以用(Ik/GCD) 和Ij代替原來的數,使他分辨效率變高。

5.簡化度 H

  我們定義H=1/(特征數之和),特征數之和越小簡化度越高。

綜合評價指數:

Q=D*H/特征維度。

我們

哈希樹的組織結構:

使用不同的分辨算法可以組織不同的哈希樹,一般來說,每一個哈希樹的節點下的子節點數是和分辨數列一致的。哈希樹的最大深度就是特征空間的維度。

為了方便研究我們用質數分辨算法建立一顆哈希樹。第一層位給節點,根節點下有2個節點;第二層的每一個節點下有3個節點;以此例推,即每層節點的子節點的數目為連續的素數。單量地市層每個節點下面有29個節點(2-29有10個連續的素數)。

 

hash樹的插入
1.設置幾個參數,prime數列,0位2,level層數,0,層位根節點;
2.如果當前的位置沒有被占領,我們改變這個節點的key和value 然后標記為true
3.如果當前的節點被占領了,我們就模這一層的prime[level],如果這個節點不存在,我們就往下建一個節點然后到下一層去比較。
4.比較兩個數不同的標准是特征編碼是否相同(長度和內容)
 1 #include<iostream> 
 2 hashnode 的結構
 3 首先要key 和value值,
 4 還要申請子節點的個數的地址值,初始化為NULL,noise[]
 5 該節點是否被占領 occupied
 6 void insert(HashNode entry int level, int key,int value)
 7 {
 8     if(this.occupied==false)
 9     {
10         this->key=key;
11         this->value=value;
12         this->occupied=true;
13         return;
14     }
15     int index=key%prime[level];
16     if(node[index]==NULL)
17     {
18         nodes[index]=new hashNode(); 
19     } 
20     level+=1;
21     insert(nodes[index],level,key,value);
22 } 

查找操作:
1.如果當前節點沒有被占領,執行第五步;
2.如果當前節點已經被占領,比較key的值;
3.如果關鍵值相同,返回value;
4.如果不等,執行第五步
5.計算index=key%prime[level];
6.如果nodes[index]=NULL,返回查找失敗;
7.如果nodes[index]為一個已經存在的子節點,我們遞歸下去往下找,重復第一步操作

 1 偽代碼;
 2 int find(HashNode entry,int level,int key/*,int value*/)
 3 {
 4     if(this->occupied==true)
 5     {
 6         if(this->key==key)
 7             return this->value
 8     }
 9     int index=key%prime[level++];
10     //level+=1;
11     if(nodes[index]==NULL)
12         return fail;
13     return find(nodes[index],level,key); 
14 } 
 
刪除操作,就是在查找的基礎上實現的
 1.如果當前節點沒有被占領,執行第五步;
2.如果當前節點已經被占領,比較key的值;
3.如果關鍵值相同,將這一步設為為占領occupied=false;//在找到的基礎上可以選擇設為false,我們也可以選擇直接刪除這個節點,然后將這個指針設為空,同時我們也可以選擇返回查找的地址
4.如果不等,執行第五步
5.計算index=key%prime[level];
6.如果nodes[index]=NULL,返回查找失敗;
7.如果nodes[index]為一個已經存在的子節點,我們遞歸下去往下找,重復第一步操作
 1 RemoveNode(HashNode entry,int level,int key)
 2 {
 3     if(this->occupied==true)
 4     {
 5         if(this->key==key)
 6         {
 7             this->occpuied=false;
 8             return ;
 9             //delete this;
10             //this=NUll
11             //return;
12         }
13         int index=key MOD prime[level++]
14         //level+=1;
15         if(nodes[index]==NULL)
16             return fail;
17         /*return*/ RemoveNode(nodes[index],int level,int key); 
18     }
19 }

 


hashtree的特點,每次查找的復雜度為lg,而且合理利用指針可以避免不必要的空間浪費
初始化樹需要時間nlogn,沒有必要建齊整棵樹
操作簡單
查找迅速
結構不變,不會退化成鏈表
哈希數的退化問題;
面對相同的數我們可以增加節點的信息,time代表出現的次數;
同時這兩個數相差k*D,我么就可以繼續往下建一層一般不會數據報表的大
字符串關鍵字hash化;
我們mod兩個比較大的質數就,D=s1*s2;(數據不太大無敵)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM