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个连续的数。

扫描二维码关注公众号,回复: 11124129 查看本文章

分辨算法的评价标准:

状态和特征:

  分辨也即分辨不同的状态。分辨一般是先定义一组不同的状态,然后将这些状态记录下来形成特征。由这些特征所形成的空间是特征空间。特征空间的维度就是特征数列的长度。

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;(数据不太大无敌)

猜你喜欢

转载自www.cnblogs.com/hjw201983290498/p/12770943.html
今日推荐