我們先來接受幾個概念:
質數分解定律,任何一個數都可以分解為幾個不同素數額乘積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個連續的素數)。

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;(數據不太大無敵)
