哈希树的python实现

article/2025/10/4 22:59:53

一、问题的背景

        给定一组商品购买信息,找到商品购买中频繁出现的商品集。比如说,我们有如下的商品交易信息:

市场购物信息
TipItems
1Bread, Milk
2Bread, Diaper, Beer, Egg
3Milk, Diaper, Beer, Coke
4Bread, Milk, Diaper, Beer
5Bread, Milk, Diaper, Coke

        我们定义,Itemset 为一系列item的集合,比如:{Milk, Bread, Diaper};定义 k-itemset 为包含k个items的itemset;定义support 是所有交易信息中,包含这个 itemset 的子集。比如s({Milk, Bread, Diaper}) = 2/5;定义frequent Itemset 是一组itemset,它的support 大于等于minsup,这个minsup值由我们自己给定。

        为了找出频繁项集,最直观的方法是我们罗列出所有的候选项,然后计算每个候选项的support,最后将满足要求的频繁项保存下来。比如说,我们有M个交易信息储存在数据库中,有N个候选项,那么我们必须要比较MN次,显然它的时间复杂度是非常大的。一个有效的解决途径是我们使用有效的数据结构来存储候选项和交易信息,这样我们不需要将每个候选项与每个交易都匹配一次。

        我们可以将候选集储存在哈希树中,这样我们不需要一个交易信息与每一个候选集进行比较,我们只需要比较那些哈希树中存在的候选集。

二、如何构建哈希树

        假设我们有15个候选集,长度均为3:

{1 4 5}, {1 2 4}, {4 5 7}, {1 2 5}, {4 5 8}, {1 5 9}, {1 3 6}, {2 3 4}, {5 6 7}, {3 4 5}, {3 5 6}, {3 5 7}, {6 8 9}, {3 6 7}, {3 6 8}

我们需要:1、构建一个hash函数。 2、设定叶子的最大大小(每片叶子中能够存储的最大数据),如果某片叶子中的候选集数量超过了限制,我们需要对这个叶节点做分裂处理。

比如说我们构建了如下图所示的hash函数,在第一个层,对候选集的第一项进行判断,比如说我们对{1,2,5}进行判断,由于第一项为1,因此我们将它放到root的左节点。在第二层,我们对候选集的第二项进行判断,{1,2,5}的第二项是2,根据hash函数,我们再想中间走一步。在第三层,{1,2,5}的第三项是5,因此我们往中间走一步。当然,往下走一步仅在于你当前无法存储在3个节点的情况,因为我们定义了叶子的最大size是3,如果你这个节点能够存储下3个数据,那就没必要继续往下分裂了。

由此我们可以建立如下的哈希树:

那么给定一次商品交易信息,比如[1,2,3,5,6],我们应该如何将这次交易与候选项进行比较?根据hash函数,如果我们想左走,那么我们的选择一定是1开头,然后从[2,3,5,6]选择长度为2的子序列,继续往左走的话,由于[2,3,5,6]与哈希函数中的[1,4,7]无法找到共同项,因此往左走是行不通的,这样我们就避免了这次交易与候选集[1,4,5]的比较。同理我们往中间走,根据哈希函数得到了12[3,5,6]的集合,这样也就是有123,125,126三种可能性,因此与哈希树中对应叶节点的125,458,因此我们知道,在这次交易信息中,125这个候选集出现过一次。因此利用哈希树,我们避免了一部分的比较,减少了比较次数。

 

三、哈希树的Python实现

class Node:def __init__(self,val=[]):self.val = valself.children = {}class HashTree:def __init__(self):self.root = Node()#建立根节点def insert(self,val):#给定一个值val,创建一个值为val的节点并将其插入到树中root = self.rooti = 0while root.children:#if root has childrenif (val[i]-1) % 3 in root.children.keys():#如果想找的孩子存在root = root.children[(val[i]-1)%3]i += 1else:#if the child doesn't existroot.children[(val[i]-1)%3] = Node([val])return#so the root doesn't have childif len(root.val) < 3:#the value of root is smaller than 3root.val.append(val)returnelse:#root的值的个数已经等于3了,那么我们必须split rootroot.val.append(val)#先把val加入到root的值当中for item in root.val:#对于root值中的的每一项j = (item[i]-1) % 3#表示余数是多少if j in root.children.keys():#如果余数已经在其中了root.children[j].val.append(item)#将item加入到列表中else:root.children[j] = Node()#首先创建该节点root.children[j].val = [item]#如果没有,则创建新列表root.val = []                if len(root.children[j].val) == 4:#分裂节点后,仍然出现了大于3的情况,那么我们需要继续分裂节点i += 1root = root.children[j]for item in root.val:#对于root值中的的每一项j = (item[i]-1) % 3#表示余数是多少if j in root.children.keys():#如果余数已经在其中了                            root.children[j].val.append(item)#将item加入到列表中else: root.children[j] = Node()root.children[j].val = [item]#如果没有,则创建新列表root.val = []def PrintTree(self,node):#如何 层次的输出树if not node.val:#如果这个节点的值不存在if not node.children: return#如果孩子也没有else:#有孩子了res = []for item in node.children.values():res += [self.PrintTree(item)]else:#这个节点的值存在return node.valreturn resobj = HashTree()
values = '[{1 2 4}, {1 2 9}, {1 3 5}, {1 3 9}, {1 4 7}, {1 5 8}, {1 6 7}, {1 7 9}, {1 8 9}, {2 3 5}, {2 4 7}, {2 5 6}, {2 5 7}, {2 5 8}, {2 6 7}, {2 6 8}, {2 6 9}, {2 7 8}, {3 4 5}, {3 4 7}, {3 5 7}, {3 5 8}, {3 6 8}, {3 7 9}, {3 8 9}, {4 5 7}, {4 5 8}, {4 6 7}, {4 6 9}, {4 7 8}, {5 6 7}, {5 7 9}, {5 8 9}, {6 7 8}, {6 7 9}]' 
values = values.replace('{','[').replace('}',']').replace(' ',',').replace(',,',',')
values = 'values = ' + valuesexec(values)for item in values:obj.insert(item)print(obj.PrintTree(obj.root))

 


http://chatgpt.dhexx.cn/article/Uc3et9Ji.shtml

相关文章

哈希列表、哈希链、哈希树

通过哈希算法检验大量数据&#xff08;比如大量文件&#xff09;的一致性时&#xff0c;常见的存储方案&#xff1a; 哈希列表&#xff08;Hash List&#xff09; 原理&#xff1a; 计算每个数据的哈希值&#xff0c;保存为一个列表。记录该列表的哈希值&#xff0c;用于检验…

哈希树

哈希树&#xff1a; 哈希树(HashTree)算法就是要提供一种在理论上和实际应用中均能有效地处理冲突的方法。一般的哈希(Hash)算法都是O(1)的&#xff0c;而且基本是以空间换时间。这很容易导致对存储空间无限制的需求。本文中哈希树(HashTree)算法在实际操作中使用了一些技巧使…

哈希树 (HashTree)

在讲hash树之前首先我们来理解一下质数分辨定理。 什么是质数分辨定理&#xff1f; 什么是质数 &#xff1a; 即只能被 1 和 本身 整除的数。 为什么用质数&#xff1a;因为N个不同的质数可以 ”辨别“ 的连续整数的数量&#xff0c;与这些质数的乘积相同。 百度文库解答&#…

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…