哈希树 (HashTree)

article/2025/10/4 22:55:09

在讲hash树之前首先我们来理解一下质数分辨定理。

    什么是质数分辨定理?

        什么是质数 : 即只能被 1 和 本身 整除的数。

        为什么用质数:因为N个不同的质数可以 ”辨别“ 的连续整数的数量,与这些质数的乘积相同。

            百度文库解答:https://wenku.baidu.com/view/16b2c7abd1f34693daef3e58.html

         

        也就是说如果有21亿个数字的话,我们查找的哪怕是最底层的也仅仅需要计算10次就能找到对应的数字。

        所以hash树是一棵为查找而生的树。       

如何实现一棵Hash树呢?

    Hash树结点的数据结构:

 private static class Node{  //定义了一个内部类,每一个结点会有一个next数组  public Node[] next = null;    //用来装孩子的下标表示余数public Integer data = 0;        //数值public boolean isDel = false;   //是否被删除的标记public Node(Integer data,Integer level){    //构造函数next = new Node[level];this.data = data;}public Node(Integer data){    //构造函数this.data = data;}}

    哈希树的插入方法:

        宗旨:求余看对应位置的结点,如果为空则在空处插入一个新节点,如果被逻辑删除了替换值再逻辑恢复,如果有值就继续往下找,继续求余判断。

        图解:有一组元素,按照顺序向hash树中插入元素,取余找位置插入。我们以下图中的 “68” 为例子, 假设前面的数字已经插入完成,68先对2取余得0,但是0位置上有人了,继续对3取余得2,2得位置上也有人了,那就继续对5取余得3,3得位置上没有人则插入 到3的位置。这样说是否清晰呢?

        

    Hash树的查找方法:

            也以上图中的68为例子,我们从2开始取余查找,找对应位置的值是否和它相同,不相同则继续向下取余,直到找到和68相同的数值或者直到为空为止。

    Hash树的删除算法:

            与查找相同,查找到元素后,逻辑删除改变一下 isDel 的值即可。

    那么Hash树的基本操作就已经说完了,下面粘贴上源代码!

/*** Created by 小H on 2018/3/25.*/
public class MyHashTree {private static Integer[] PRIME_NUMBER = { 2 , 3 , 5 , 7 , 11 , 13 , 17 , 19 , 23 , 29}; //连续11个质数能表示6464693230个数字private Node root = new Node(0,PRIME_NUMBER[0]);/*** 插入一个元素* @param data* @return*/public boolean insertData(Integer data){Integer count = 0;      //当前 要用的质数数组的下标   又可以标识层数   1层为树根 层数从2开始计算所以实际层数要+2Integer remain = 0;     //每次计算的余数Node point = this.root; //指针从根节点开始走while (true){remain = data % PRIME_NUMBER[count];        //计算余数if (point.next[remain] == null){   //余数位上为空新建一个结点加进去point.next[remain] = new Node(data,PRIME_NUMBER[count+1]);break;}else if(point.next[remain].isDel){ //或者是余数位上元素被逻辑删除了那么就把值给他替换信息然后逻辑恢复point.next[remain].data = data;point.next[remain].isDel = false;break;}else {                                //既不为空也不为逻辑删除那么我就继续找位置point = point.next[remain];count++;}}return true;}/*** 查询一个元素* 正常返回的应该是查询到的元素,这里就查个值,元素没有附带的信息也没什么好返回的,就瞎搞一下** @param data* @return*/public boolean serach(Integer data){Integer count = 0;      //当前 要用的质数数组的下标   又可以标识层数   1层为树根 层数从2开始计算所以实际层数要+2Integer remain = 0;     //每次计算的余数Node temp = null;       //一个引用,用来清晰的表示求余后指针余数位置上的元素Node point = this.root; //指针从根节点开始走while (true){remain = data % PRIME_NUMBER[count];    //计算余数temp = point.next[remain];              //描述余数位的结点if (temp != null){                      //结点不能为空为空就输出没找到if (!temp.isDel && data.equals(temp.data)){ //不为空的话就看相不相等,删没删除System.out.println("层数:" + (count+2) + "         算上根节点的层数,当前结点所在的层数");System.out.println("层数:" + (count+1) + "         不算根节点的层数,当前结点所在的层数");System.out.println("值  :" + point.next[remain].data);System.out.println("质数:" + PRIME_NUMBER[count]);System.out.println("余数:" + remain);return true;}else {point = point.next[remain];count++;}}else if (point.next[remain] == null){System.out.println("没找到!");return false;}}}/*** 删除结点  逻辑删除* @param data* @return*/public Boolean delData(Integer data){Integer count = 0;      //当前 要用的质数数组的下标   又可以标识层数   1层为树根 层数从2开始计算所以实际层数要+2Integer remain = 0;     //每次计算的余数Node temp = null;       //一个引用,用来清晰的表示求余后指针余数位置上的元素Node point = this.root; //指针从根节点开始走while (true){remain = data % PRIME_NUMBER[count];temp = point.next[remain];if (temp != null){if (!temp.isDel && data.equals(temp.data)){System.out.println("=====结点信息输出======");System.out.println("层数:" + (count+2) + "         算上根节点的层数,当前结点所在的层数");System.out.println("层数:" + (count+1) + "         不算根节点的层数,当前结点所在的层数");System.out.println("值  :" + temp.data);System.out.println("质数:" + PRIME_NUMBER[count]);System.out.println("余数:" + remain);System.out.println("========正在删除=======");temp.isDel = true;return true;}else {point = point.next[remain];count++;}}else if (point.next[remain] == null){System.out.println("没找到要删除的结点!");return false;}}}/*** 层序遍历输出值*/public void showHashTree(){System.out.println("=========层序遍历开始=========");Node point = this.root; //指针从根节点开始走Node temp = null;MyLinkedQueue<Node> queue = new MyLinkedQueue<Node>();queue.enQueue(point);while (queue.getCount()>0){temp = queue.deQueue();if (temp.data == 0)System.out.println("根节点:" + temp.data);System.out.print(" " + temp.data + " ");for (int i = 0; i <temp.next.length ; i++) {if (temp.next[i] == null || temp.next[i].isDel )continue;else {queue.enQueue(temp.next[i]);}}}System.out.println();System.out.println("=========层序遍历结束=========");}private static class Node{public Node[] next = null;public Integer data = 0;public boolean isDel = false;public Node(Integer data,Integer level){next = new Node[level];this.data = data;}public Node(Integer data){this.data = data;}}}

 


http://chatgpt.dhexx.cn/article/2DQgX6O1.shtml

相关文章

Merkle树介绍

默克尔树&#xff08;Merkle树&#xff09;又叫哈希树&#xff0c;是区块链数据存储运用到的一个重要的技术算法。 简单来说&#xff0c;哈希树&#xff08;默克尔树&#xff09;中&#xff0c;每个节点都标有一个数据块的加密哈希值。哈希树可以用来验证任何一种在计算机中和计…

Merkle Tree(默克尔树)算法解析

Merkle Tree概念 Merkle Tree&#xff0c;通常也被称作Hash Tree&#xff0c;顾名思义&#xff0c;就是存储hash值的一棵树。Merkle树的叶子是数据块(例如&#xff0c;文件或者文件的集合)的hash值。非叶节点是其对应子节点串联字符串的hash。[1] 1、Hash Hash是一个把任意长…

js中的var是什么意思

js中的var是定义变量的意思&#xff0c;使用和不使用var都能定义变量&#xff0c;但是两个变量的作用域不同。 &#xff08;1&#xff09;在函数中和函数外分别用var定义一个变量a&#xff0c;函数外的变量a是全局变量&#xff0c;函数内的变量a是局部变量&#xff0c;所以在函…

python中的var是什么什么的缩写_var是什么意思

展开全部 VAR是英文Video Assistant Referee的缩写&#xff0c;也被称作“视频助理裁判”&#xff0c;由现役裁判员担任&#xff0c;他的职责是通过回放视频向裁e5a48de588b63231313335323631343130323136353331333366303733判员提供信息&#xff0c;协助裁判员纠正改变比赛走…

var 作用域||变量

平常我们在使用js 的时候一般使用var来声明变量&#xff0c;相比于C语言Java当中的声明变量要简单一些&#xff0c;但是简单肯定也会有简单的不好之处。 一般来讲&#xff0c;在函数内部&#xff08;local variable&#xff09;中&#xff0c;js初始化变量加var的为局部变量不加…

第一讲:var的使用

目录 使用var声明变量 不使用var&#xff0c;直接给变量赋值 变量的作用域 全局变量和局部变量的混用 变量提升 总结 javascript中&#xff0c;使用var声明变量&#xff0c;看似简单易学&#xff0c;其实不然。 在我接触的许多编程语言中&#xff0c;如c, c#, vb, java, p…

let与var的区别

前端小白刚学习JavaScript接触到变量的时候可能会有点懵&#xff0c;那就是什么时候该用let&#xff0c;什么时候该用var&#xff0c;这里给大家一个最简单&#xff0c;最明了的答案&#xff0c;看完就能明白。 首先&#xff0c;let是拥有块级作用域的&#xff0c;什么是块级作…

val和var的区别

美图欣赏&#xff1a; 一.背景 学习过程中&#xff0c;会有很多小的并且容易混淆知识点&#xff0c;因此会把它记录下来。 二.val(value)和var(variable)的区别 基本语法&#xff1a; var|val 变量名 : 变量类型 变量值1.使用var或者val定义一个变量。 使用var(variable)声…

var

在函数中&#xff0c;使用var声明的变量&#xff0c;为局部变量&#xff0c;只能在函数内部访问。 不使用var声明的变量&#xff0c;为全局变量&#xff0c;在函数外边也能访问。 没有var的情况 <script type"text/javascript">a 10;function demo() {console…

VaR如何计算?VaR计算方法

VaR方法提出的背景 传统的ALM(Asset-Liability Management,资产负债管理)过于依赖报表分析&#xff0c;缺乏时效性&#xff1b;利用方差及β系数来衡量风险太过于抽象&#xff0c;不直观&#xff0c;而且反映的只是市场&#xff08;或资产&#xff09;的波动幅度&#xff1b;而…

Matlab画线实例图

1 plot画线 直线&#xff1b; 设置线宽和颜色&#xff1b; 黄色&#xff0c;8像素宽&#xff1b; 直线&#xff0c;黄色&#xff1b; 2 line 画线 画的是坐标(1,3)到(2,4)的一条线&#xff1b; 设置线型和颜色&#xff1b; 3 数学曲线 另一个&#xff1b;

matlab 绘制三维空间直线

绘制三维空间直线 clc,clear; x-2:0.1:2; y(-17*x9)/9; z(-7*x7)/9; plot3(x,y,z,m); grid on

Matlab图像线条绘制

1.线型 定义符---:-.线型实线&#xff08;缺省值&#xff09;划线点线点划线 2.线条宽度 指定线条的宽度&#xff0c;取整为整数&#xff08;单位为像素&#xff09;。 3.线条颜色 定义符r(red)g(green)b(blue)c(cyan)颜色红色绿色蓝色青色 定义符m(magenta)y(yellow)k(bla…

matlab绘制垂线(x轴或y轴)

使用line函数就可以绘制垂线 1、绘制垂直于x轴的垂线 line([xvalue xvalue],[y1 y2])&#xff1b; 比如绘制x5 y取值为[0,10]&#xff1b; line([5 5],[0 10]); 2、绘制垂直于y轴的垂线 line([x1 x2], [yvalue yvalue])&#xff1b; 比如绘制y5 x取值为[0,10]&#xff…

由两点坐标如何画出直线 matlab

由两点坐标如何画出直线 方法1&#xff1a;利用直线方程 斜率加截距 方法2&#xff1a;数据拟合 1 %由两点坐标得数据拟合直线与画线 2 x [1,2];3 y [5,8];4 k ((8-2)/(5-1));% 由两点坐标得到直线斜率5 line k*x0.5;% 直线方程6 7 xy 1:10;% 定义画线的 x 长度8 line1 …

matplotlib画直线

使用matplotlib画两条直线&#xff1a; Code : from matplotlib.lines import Line2D import matplotlib.pyplot as pltfigure, ax plt.subplots() # 设置x&#xff0c;y值域 ax.set_xlim(left0, right20) ax.set_ylim(bottom0, top10) # 两条line的数据 line1 [(1, 1), (5…

Matlab点画线

这个作图和python还是有点区别的&#xff0c;似乎对命令输入的顺序还有要求。 t[1190.2 1153.14 1071.56 1069.22 1063.18 ]; w10:10:50; % scatter(w,t,sz,r,filled); plot(w,t,o--,linewidth,2) hold on t1[1073.02 1057.81 1129.7 1028.18 1015.6 ]; plot(w,t1,*--,linewid…

用MATLAB一直画直线竟然得到了简单的禅绕画,论一直画直线的人有多无聊

之前看过一个视频&#xff0c;有个人把纸面分割成一个一个三角后一直画直线&#xff0c;慢慢的图纸上的图案变得复杂了起来&#xff0c;大概是像下面这样&#xff1a; 上面这个图便是我用matlab模拟的效果&#xff0c;过程很简单&#xff0c;就是用了泊松云盘采点构建三角网格&…

matlab画图线形

线型说明-实线–虚线:点线-.点划线 标记说明o圆圈加号*星号.点x叉号s方形d菱形^上三角v下三角>右三角<左三角p五角形h六角形 颜色说明y黄色m品红色c青蓝色r红色g绿色b蓝色w白色k黑色 plot(x,y1,‘g’,x,y2,‘b–o’,x,y3,‘c*’) 循环设置线形 linestyle{--,-,:,-o,…

matlab画平行坐标轴的直线

想要在普通图形的基础上添加平行于坐标轴的直线 clc clear xmin 2000 xmax 2120 ymin 0 ymax 16 x[2020 2040 2060 2080 2100 2110]; y[1.3 2 3.5 5.8 10 14.8]; xxlinspace(2012,2110); yyspline(x,y,xx); plot(xx,yy,-c,LineWidth,3) axis([xmin xmax ymin ymax]) grid o…