NOIP基础数据结构_哈希、并查集
NOIP的知识点

二、算法
• 高精度(乘法、除法、加减法) • 模拟
二、算法
• 树上两点间距离(tarjan,倍增) • 树的dfs序
二、算法
• 图论: • 连通性问题:求强连通分量,求割点和 桥,欧拉回路,拓扑排序 • 最小生成树的三种算法(Kruskal,Prim) • 最短路(Dijkstra,Bellman-Ford,SPFA, Floyd) • 验证二分图 • 熟练编写
三、数据结构
• 并查集(Tarjan算法) • NOI05 食物链 • 启发式合并思想
二、算法
• 动态规划 • 状态的表示 • 动态规划的优化 • 状态优化 • 转移优化 • 空间优化
二、算法
• 调整算法(随机调整、模拟退火、遗传算 法、爬山法) • 掌握以上算法思想 • 善于恶搞 • 骗分导论
三、数据结构
• • • • 栈 队列 堆 熟练掌握并能快速实现
三、数据结构
• Hash表 • 字符串的hash • 字典树
NOIP知识点
一、理论知识
• 复杂度理论 • 时间复杂度分析 • 空间复杂度分析
一、理论知识
• • • • 算法: 搜索(优化) 调整 贪心
一、理论知识
• 组合数学(排列与组合,容斥原理,递推, 差分序列) • 常见结论及其推导 • 常见模型分析(方程分析法,数论中的容 斥原理)
一、理论知识
• 数论(整除,集合论,关系,素数,进位 制,辗转相除,扩展的辗转相除,同余运 算,解线性同余方程,中国剩余定理) • 常见结论
二、算法
• 搜索(BFS,DFS),枚举 • 优化,剪枝 • 最优性剪枝 • 可行性剪枝 • 利用题目中奇怪的性质剪枝 • 一定要保证写对
Python中的Hash函数实现方式

Python中的Hash函数实现方式1.概述Hash函数是计算机科学中十分重要的一个概念,在Python语言中,Hash函数被广泛使用,Python标准库中也包含了一些常用的Hash函数。
本文将从以下几个方面对Python中的Hash函数进行介绍:Hash函数的概念、Hash函数的应用、Hash函数的实现方式以及Hash函数的应用实例等。
2. Hash函数的概念Hash函数,也叫散列函数,是将任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换为固定长度的输出(又叫做散列值,Hash值,message digest)的函数。
Hash函数的特点是输入和输出的类型不一定相同,而且无论输入的数据多少,输出的结果长度是固定的。
Hash函数的设计是为了保证输入数据的机密性、数据完整性以及防止重放攻击等。
在Python中,Hash函数是一个内置函数,它被用于创建Hash对象,Hash函数的格式如下:hash(object)其中,object表示要计算Hash值的对象,可以是数字、字符串、元组、列表、字典等。
3. Hash函数的应用Hash函数在计算机科学中有很多应用,下面简单介绍几个常见的应用:3.1哈希表哈希表是一种数据结构,它通过Hash函数将关键字映射为索引,可以实现快速的数据检索,常见的哈希表有字典(Dictionary)、集合(Set),Python中的字典和集合就是基于哈希表实现的,因为Hash函数可以将输入的键(Key)映射为索引(Hash值),并将索引与值(Value)组合存储在相应的数据结构中。
在Python中,字典和集合是非常常见的数据结构,它们在实际开发中被广泛使用。
3.2文件完整性验证Hash函数还可以被用于文件完整性验证,比如,我们可以通过计算文件内容的Hash值来判断文件是否被篡改或者被恶意软件所感染,这对于保证文件的安全性具有重要作用。
3.3数字签名数字签名是一种用于确认在不可否认的情况下,数据的来源和完整性的技术。
信息学奥赛 数据结构——并查集

全国青少年信息学奥林匹克联赛特殊数据结构——并查集龚禹在一些有N个元素的集合应用问题中,我们通常是在开始时让每个元素构成一个单元素的集合,然后按一定顺序将属于同一组的元素所在的集合合并,其间要反复查找一个元素在哪个集合中。
这一类问题近几年来反复出现在信息学的国际国内赛题中,其特点是看似并不复杂,但数据量极大,若用正常的数据结构来描述的话,往往在空间上过大,计算机无法承受;即使在空间上勉强通过,运行的时间复杂度也极高,根本就不可能在比赛规定的运行时间(1~3秒)内计算出试题需要的结果,只能采用一种全新的抽象的特殊数据结构——并查集来描述。
一、数学准备首先,我们从数学的角度给出等价关系和等价类的定义:定义1:如果集合S中的关系R是自反的,对称的,传递的,则称他为一个等价关系。
——自反:x=x;——对称:若x=y,则y=x;——传递:若x=y、y=z,则x=z。
要求:x、y、z必须要同一个子集中。
定义2:如果R是集合S的等价关系。
对于任何x∈S,由[x]R={y|y∈S and xRy}给出的集合[x]R S称为由x∈S生成的一个R的等价类。
定义3:若R是集合S上的一个等价关系,则由这个等价关系可产生这个集合的唯一划分。
即可以按R将S划分为若干不相交的子集S1,S2,S3,S4,……,他们的并即为S,则这些子集Si变称为S的R等价类。
划分等价类的问题的提法是:要求对S作出符合某些等价性条件的等价类的划分,已知集合S及一系列的形如“x等价于y”的具体条件,要求给出S的等价类的划分,符合所列等价性的条件。
(我们上面提到的联系,即可认为是一个等价关系,我们就是要将集合S划分成n个联系的子集,然后再判断x,y是否在一个联系子集中。
)二、引题——亲戚(relation)【问题描述】若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的两个人是否具有亲戚关系。
规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。
部分NOIP基础模块代码总结 pascal

部分NOIP基础模块代码总结--by Evan1004一、数据结构1、哈希表procedure hash_a(x:longint);vart:longint;begint:=x mod 399997;if first[t]=0 thenbegininc(tot1);first[t]:=tot1;a[tot1].x:=x;a[tot1].zhi:=0;end elsebegint:=first[t];while (a[t].zhi>0) and (a[t].x<>x) dot:=a[t].zhi;if a[t].zhi=0 thenbegininc(tot1);a[tot1].x:=x;a[tot1].zhi:=0;a[t].zhi:=tot1;end;end;end;2、堆(代码为大根堆操作,小根堆只需将a[i]>a[j]改为a[i]<a[j]即可) 1).插入(上调)procedure up(i);beginwhile i>1 dobeginj:=i div 2;if a[i]>a[j] thenbeginswap(a[i],a[j]);i:=j;endelsebreak;end;end;2).删除(下调)procedurd down(i,n:longint);beginwhile i<=n shr 1 do //因为a[n shr 1]的儿子就是a[n]了beginj:=2*i;if (j+1<=n) and (a[j+1]>a[j]) then //选择两个儿子中的较大者j:=j+1;if a[j]>a[i] thenbeginswap(a[i],a[j]);i:=j;endelsebreak;end;end;3、线段树1.建树procedure start(l,r:longint; var t:longint);varm:longint;beginm:=(l+r) div 2 ;inc(tot);t:=tot;a[t].l:=l;a[t].r:=r;if l<r then beginstart(l,m,a[t].lc);start(m+1,r,a[t].rc);end;end;2.修改区间procedure insert(t,l,r:longint);beginif (a[t].l=l) and (a[t].r=r) thenbegin inc(a[t].data); exit; end;if (r<=a[a[t].lc].r) then insert(a[t].lc,l,r)else if l>=a[a[t].rc].l then insert(a[t].rc,l,r)else begininsert(a[t].lc,l,a[a[t].lc].r);insert(a[t].rc,a[a[t].rc].l,r);end;end;3.修改点procedure insert(t,x:longint);beginif t=0 then exit;if (x=a[t].l) and (x=a[t].r) then begin inc(a[t].data);exit;end;if (x>=a[t].l) and (x<=a[t].r) thenbegininc(a[t].data);insert(a[t].lc,x);insert(a[t].rc,x);end;end;4.查询点procedure find(t,x:longint);beginif t=0 then exit;if (x=a[t].l) and (x=a[t].r) then begin inc(ans,a[t].data); exit;end;if (x>=a[t].l) and (x<=a[t].r) thenbegininc(ans,a[t].data);find(a[t].lc,x);find(a[t].rc,x);end;4.第K小(大)function find(t,x:longint):longint;beginif t=0 then exit;if (a[t].l=a[t].r) then find:=a[t].lelse if a[a[t].lc].data>=x then find:=find(a[t].lc,x)else find:=find(a[t].rc,x-a[a[t].lc].data);5.最大(小)function find(t,x,y:longint):longint;beginif t=0 then exit;if (a[t].l=x) and (a[t].r=y) then exit(a[t].data) elseif y<=a[a[t].lc].r then exit(find(a[t].lc,x,y)) elseif x>=a[a[t].rc].l then exit(find(a[t].rc,x,y)) elseexit(min(find(a[t].lc,x,a[a[t].lc].r),find(a[t].rc,a[a[t].rc].l,y)));end;4、二叉搜索树二叉搜索树procedure insert(var t,x:longint);beginif t=0 thenbegininc(tot);t:=tot;tree[t].x:=x;tree[t].lc:=0;tree[t].rc:=0;tree[t].time:=1;end elsebeginif x>tree[t].x then insert(tree[t].rc,x);if x<tree[t].x then insert(tree[t].lc,x);if x=tree[t].x then inc(tree[t].time);end;end;//======================================================== procedure print(t:longint);beginif t=0 then exit;print(tree[t].lc);writeln(tree[t].x,' ',tree[t].time);print(tree[t].rc);end;二、图论1、最小生成树1.prim算法procedure prim;vari,j,min,minj:longint;beginv[1]:=0;for i:=1 to n dobeginmin:=maxlongint;for j:=1 to n doif (b[j]=0) and (v[j]<min) thenbeginmin:=v[j];minj:=j;end;sum:=sum+min;b[minj]:=1;for j:=1 to n doif (b[j]=0)and(a[minj,j]>0)and(v[j]>a[minj,j]) thenv[j]:=a[minj,j];end;writeln(sum);end;2.Kruskal算法(算法过程较多,引一道纯最小生成树题举例)constmaxn=1000000;vari,j,k,m,n,p,q,x,y:longint;f,u,v:array[1..maxn] of longint; ans,s:extended;e:array[1..maxn] of real; procedure swap(var x,y:longint); vart:longint;begint:=x;x:=y;y:=t;end;procedure qsort(l,r:longint);vari,j:longint;x,y:extended;begini:=l;j:=r;x:=e[random(r-l)+l];repeatwhile e[i]<x do inc(i);while e[j]>x do dec(j);if i<=j thenbeginy:=e[i];e[i]:=e[j];e[j]:=y;swap(u[i],u[j]);swap(v[i],v[j]);inc(i);dec(j);end;until i>j;if l<j then qs(l,j);if i<r then qs(i,r);end;function get(x:longint):longint; beginif f[x]=0 then exit(x);if f[f[x]]=0 then exit(f[x]);f[x]:=get(f[x]);exit(f[x]);end;procedure init;beginfillchar(e,sizeof(e),0);fillchar(u,sizeof(u),0);fillchar(v,sizeof(v),0);fillchar(f,sizeof(f),0);readln(s);readln(n);m:=0;while not eof dobegininc(m);readln(u[m],v[m],e[m]);end;end;procedure outit;beginif (k=n-1) and (ans<=s) thenwriteln('Need ',ans:0:2,' miles of cable') elsewriteln('Impossible');end;begininit;qsort(1,m);// Kurskalk:=0;for i:=1 to m dobeginp:=get(u[i]);q:=get(v[i]);if p<>q thenbeginans:=ans+e[i];f[p]:=q;inc(k);end;end;outit;end.2、最短路问题1.Floyd (简单,但是雷达不动的o(n3)...)for k:=1 to 52 dofor i:=1 to 52 dofor j:=1 to 52 doif a[i,k]+a[k,j]<a[i,j] thena[i,j]:=a[i,k]+a[k,j];2.Dijkstraprocedure Dijkstra;vari,j,p:integer;min:longint;beginp:=0;fillchar(v,sizeof(v),100);fillchar(b,sizeof(b),false);v[m]:=0;for i:= 1 to n dobeginmin:=maxlongint;for j:= 1 to n doif (min>v[j])and(not b[j]) thenbeginmin:=v[j];p:=j;end;b[p]:=true;for j:= 1 to n doif (not b[j])and(v[j]>a[p,j]+v[p]) thenv[j]:=a[p,j]+v[p];end;for i:= 1 to n dowriteln(v[i]);end;3.SPFAprocedure spfa;beginfillchar(q,sizeof(q),0); h:=0; t:=0;//队列fillchar(b,sizeof(b),false);//b[i]判断i是否在队列中for i:=1 to n dov[i]:=maxint;//初始化最小值inc(t);q[t]:=1;b[1]:=true;v[1]:=0;//这里把1作为源点while h<>t dobeginh:=(h mod n)+1;x:=q[h];b[x]:=false;for i:=1 to n doif (a[x,i]>0) and (v[x]+a[x,i]<v[i]) thenbeginv[i]:=v[x]+a[x,i];if not(b[i]) thenbegint:=(t mod n)+1;q[t]:=i;b[i]:=true;end;end;end;end;三、不知道分什么类1、最大公约数:function gcd(n,m:longint):longint;beginif m=0 then exit(n);gcd:=gcd(m,n mod m);end;2、最小公倍数:lcm(n,m):=n*m/gcd(n,m) //先除再乘,不然超LONGINT了3、快速排序procedure qsort(l,r:longint);vari,j,k,mid:longint;begini:=l;j:=r;mid:=a[(l+r) shr 1];repeatwhile a[i]<mid do inc(i);while a[j]>mid do dec(j);if i<=j thenbegink:=a[i]; a[i]:=a[j];a[j]:=k;inc(i);dec(j);end;until i>j;if i<r then qsort(i,r);if l<j then qsort(l,j);end;4、并查集1.判断是否在同一并查集内function get(x:longint):longint; beginif f[x]=x then exit(x) elsebeginf[x]:=get(f[x]); \\捎带路径压缩exit(f[x]);end;end;2.合并procedure union(x,y:longint); beginif get(x)<>get(y) thenf[get(x)]:=get(y);end;深搜的基本框架procedure search;varif 结束条件1 thenbeginif 结束条件2 then inc(ans);exit;end;{ 计算、操作}for i:=1 to n do //n为搜索宽度search(n);end;。
CCF青少年计算机程序设计评级标准

七级
综合运用算法和数据结构编 写程序,解决问题。
1. 并查集、线段树、哈夫曼树、二叉排序树、二叉堆 2. 图的连通性算法,最短路、最小生成树的优化算 法,二分图的构造、判定及匹配,搜索算法的优化, 扩展欧几里德算法。 3. 中国剩余定理,剩余类,概率基础知识,解析几何 基础知识。
1. 能根据时间和空间复杂度 的要求灵活构造算法和数据 结构解决实际问题。 2. 具备较强的程序代码实现 能力。 3. 具备较强的归纳、总结和 表达能力。
级别 定义
知识要求
CCF 青少年计算机程序设计评级标准
能力要求
评价方法
1. 程序的基本结构。
2. 标识符与关键字。
一级
了解什么是计算机程序,能 够编写计算机程序解决简单 问题。
3. 4. 5. 6.
基本数据类型。 常量和变量。 算术表达式和关系表达式。 整除,求余运算,常用数学函数。
7. 赋值语句,输入输出语句,复合语句,条件语句
1. 与 NOIP 提高组复赛相衔接。 采用上机编程考核方式,分两次 测试,每次 3 个试题,考 4 小 时。共 6 道题,考8 小时。 2. 在 NOIP 提高组复赛中成绩列 全国前 10%。
七级
综合运用算法和数据结构编 写程序,解决问题。
1. 并查集、线段树、哈夫曼树、二叉排序树、二叉堆 2. 图的连通性算法,最短路、最小生成树的优化算 法,二分图的构造、判定及匹配,搜索算法的优化, 扩展欧几里德算法。 3. 中国剩余定理,剩余类,概率基础知识,解析几何 基础知识。
复赛中成绩列全国前 50%。
1. 指针类型。
2. 一般线性表,队列,堆栈,二叉树的存储和遍历。 1. 能运用常用算法和简单数
五级
python中哈希表用法

python中哈希表用法哈希表是Python中常用的数据结构之一,它可以用来存储和查询大量的键值对数据。
本文将介绍哈希表在Python中的基本用法和一些常见的应用场景。
首先,我们需要了解哈希表的概念。
哈希表其实是一个数组,每个元素都是一个键值对的集合。
在哈希表中,每个键都通过哈希函数转换成一个索引,然后该键值对将被存储在索引对应的位置上。
这样,当我们需要查询某个键的时候,可以直接通过哈希函数计算出它的索引,并在对应位置上找到对应的值,从而实现快速的查询。
在Python中,内置的哈希表实现是字典(dict)。
字典是一种可变、无序的键值对集合,非常适合存储和查询数据。
接下来,我们将详细介绍哈希表在Python中的用法。
1. 创建哈希表在Python中,可以使用大括号{}或者内置的dict()函数来创建一个哈希表。
例如:```pythonhash_table = {}hash_table = dict()```创建一个空的哈希表。
2. 添加键值对可以使用赋值运算符=来向哈希表中添加键值对。
例如:```pythonhash_table["name"] = "Alice"hash_table["age"] = 25```上述代码向哈希表中添加了键"name"和"age",并分别对应值"Alice"和25。
3. 查询键值对可以使用键来查询对应的值。
例如:```pythonname = hash_table["name"]age = hash_table["age"]```上述代码通过键"name"和"age"查询到了对应的值。
4. 修改键值对可以通过赋值运算符=修改哈希表中的键值对。
例如:```pythonhash_table["name"] = "Bob"```上述代码将键"name"对应的值修改为"Bob"。
NOIP基础数据结构详解(PASCAL与C++)

数组、栈、队列
栈的实现样例Pascal代码
const
maxn = 1000;
var your family site stack:array[1..maxn] of integer;
counter:integer;
Procedure push(x:integer); begin
your site here inc(counter); stack[counter] :=x;
LOGO
数组、栈、队列
练习 1、判断字符串({[]}(){({{[()]}})}是否括号匹 配。 your family site 2、有n(n<1000000)个数排成一行,找出一段长度 为L(1<L<=n)的连续一段,其中的最大值a与最小 值b之差(a-b)是最大(小)的。求这个最大值。 your site here 3、SPFA算法。
栈的特性
•信息学中的栈一般就是用数组实现 your family site •栈(stack)是后进先出(last-in-first-
out,LIFO)或先进后出(FILO)的 •栈有两个基本操作压入(push),弹出(pop) your site here 操作都为O(1)时间 •栈有一个计数器counter或栈顶指针
NOIP基础数据结构纲要
c
Pascal和C++双语对照
佛山石门中学 江涛
LOGO
目录
目录
your family site your site here
1 数组、栈、队列 2 记录、指针、链表 3图 4 二叉树与树
LOGO
数组、栈、队列 数组
数组的特性
•数组(array)的元素(element)或项(item) 的类型是相同的
哈希 数据结构

哈希数据结构哈希(Hash)数据结构是一种常用的数据结构,它在计算机科学领域被广泛应用。
哈希数据结构的主要特点是能够快速地进行数据查找和插入操作,具有高效的时间复杂度。
一、哈希数据结构的定义和原理哈希数据结构是一种将数据元素与索引值建立映射关系的数据结构。
它通过将数据元素经过哈希函数的计算得到对应的索引值,从而将数据元素存储在数组中的相应位置。
在哈希数据结构中,哈希函数起到了关键的作用,它能够将任意大小的数据映射为固定大小的索引值。
常见的哈希函数有散列函数、MD5、SHA等。
二、哈希数据结构的应用1. 数据存储和检索:哈希数据结构可以将数据元素按照一定的规则进行存储,从而实现快速的数据检索。
例如,在散列表中,通过哈希函数将关键字映射为索引值,就可以快速地找到对应的数据。
2. 缓存管理:哈希数据结构可以用于缓存管理,可以将频繁访问的数据存储在哈希表中,以提高数据的访问速度。
例如,在操作系统中,页面置换算法中的最近最少使用(LRU)算法就可以使用哈希表来实现。
3. 数据完整性校验:哈希数据结构可以用于数据完整性校验,通过对数据进行哈希运算,得到一个唯一的哈希值,用于校验数据是否被篡改。
例如,在文件传输过程中,可以对文件进行哈希运算,将哈希值与接收到的文件进行比较,以确保文件的完整性。
4. 密码存储:哈希数据结构可以用于密码存储,通过将密码进行哈希运算,将哈希值存储在数据库中,可以提高密码的安全性。
例如,在用户注册过程中,可以对用户密码进行哈希运算,将哈希值存储在数据库中,而不是明文存储用户密码。
三、常见的哈希数据结构1. 散列表(Hash Table):散列表是一种以键值对形式存储数据的数据结构,它使用哈希函数将关键字映射为索引值,将数据存储在数组中的相应位置。
散列表具有快速的查找和插入操作的特点,广泛应用于各种编程语言中。
2. 哈希集合(Hash Set):哈希集合是一种集合数据结构,它使用哈希函数将元素映射为索引值,将元素存储在数组中的相应位置。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
your site here
•解决冲突方法有多种,最常见的有“拉链 法”和“线性探测法”。下面主要讲解这 两种hash表的实现方法。
LOGO
哈希表(hash)
hash表的拉链法实现图示
•Key2与keyN冲突
your family site
your site here
Key1 Key2 Key3 . . . KeyN
hash表的拉链法实现pascal版
const
your family site
//注:本程序用数组模拟指针法编程
maxN = 1000000; maxM = 2000003; //大质数,通常 maxM > 2*maxN
type
Tnode =record x, c :longint; next :longint; end; //记录读入数据x和计数器c //用数组模拟指针,next是下一个元素下标
your family site
your site here
LOGO
哈希表(hash)
hash表的拉链法实现pascal版
begin
your family site
assign(input,'expa.in'); reset(input); assign(output,'expa.out'); rewrite(output); readln(n); for i:=1 to n do
your family site
your site here
•hash的思想是能直接找到需要的元素,因此必须 在元素的存储位置和它的关键字之间建立一确定 的对应关系f,使每个关键字和存储结构中一个( 几乎)唯一的存储位置相对应。
•注:虽然存储方式的多种,但NOIP的实践中,用 数组更简单实用,本讲义的hash表都是数组实现。
哈希表(hash)
hash表的线性探测法实现图示
•Key2与keyN冲突
your family site
your site here
Key1 Key2 Key3 . . . KeyN
0 1 2 . . . . . .
key2 keyN key1
向 后 找 到 空 位 插 入
key3 m>n
m
LOGO
LOGO
哈希表(hash)
Hash函数图示
•图示
your family site
单射关系f Key1 Key2 Key3 . . . Keyn
your site here
0 1 2 . . . . . .
m
m>n
LOGO
哈希表(hash)
hash表的概念
•Hash函数:上面的记录中关键字key和存 储位置(这里是数组下标)之间建立的对应 your family site 关系函数f(key)。称这个对应关系f为哈希 函数,按这个思想建立的表为哈希表(又 称为杂凑法或散列表)。
c
NOIP基础数据结构
哈希表、并查集概念与应用
LOGO
目录
目录
1
your family siteLeabharlann 哈希表---散列表 并查集
2
your site here
LOGO
哈希表(hash)
hash表的引入
•Hash表,也称散列表。一般应用于有大量 “动态”的插入(删除)和查找操作的一类 your family site 问题。
your family site
your site here
LOGO
哈希表(hash)
hash表的性探测法实现pascal版
begin
your family site
assign(input,'expa.in'); reset(input); assign(output,'expa.out'); rewrite(output); readln(n); for i:=1 to n do
your site here
LOGO
哈希表(hash)
hash表的关键问题
your family site
•Hash表冲突(collision):通常的hash函 数不是一一对应关系。比如关键字是15位的身
份证号码时,普通情况下hash函数很可能会出现 keyi≠keyj,f(keyi)=f(keyj) 现象。也就是几 个关键字可能对应同一个“地址”。
your site here
LOGO
哈希表(hash)
hash表的性探测法实现pascal版
procedure add( i: longint); //新增加第i个节点 Var p:longint; begin
p:= find(data[i].x); //先查找是否已经有相同的元素 if hash[p]>0 then inc(data[hash[p]].c) //如果有,计数+1 else begin //如果没有,直接填入 hash[p]:=i; data[i].c:=1; end; write(data[ hash[p] ].c,' '); //打印data[i].x出现的次数 end;
your family site
your site here
LOGO
哈希表(hash)
常用Hash函数举例
•直接取余法: f(x):= x mod maxM ; maxM一般 是不太接近 2^t 的一个质数。
your family site
•乘法取整法: f(x):=trunc((x/maxX)*maxlongit) mod maxM, 主要用于实数。 •平方取中法:f(x):=(x*x div 1000 ) mod 1000000); 平方后取中间的,每位包含信息比较 多。
哈希表(hash)
hash表的性探测法实现pascal版
const
your family site
//注:线性探测法的hash表仅一个大数组
maxN = 1000000; maxM = 2000003; //大质数,通常 maxM > 2*maxN
type
Tnode =record x, c :longint; // next :longint; end; //记录读入数据x和计数器c //没有指针
your site here
LOGO
哈希表(hash)
hash表的拉链法实现pascal版
procedure add( i: longint); //新增加第i个节点 Var p, cod :longint; begin
p:= find(data[i].x); //先查找是否已经有相同的元素 if p>0 then inc(data[p].c) //如果有,计数+1 else begin //如果没有,则插入到表头 cod:= data[i].x mod maxM; data[i].next:=hash[cod]; hash[cod]:=i; data[i].c:=1; p:=i; end; write(data[ p ].c,' '); //打印data[i].x出现的次数 end;
your site here
LOGO
哈希表(hash)
hash表例1
分析:
your family site
由于0< N <1,000,000,不算很大,却是“动 态”的,用排序不太好。
但下面用更方便的hash法来实现,用以示 范hash表编程方法。
your site here
LOGO
哈希表(hash)
begin
your site here
read(data[i].x); add(i); //增加新节点 i ,并打印data[i].x出现次数 end; close(input); close(output);
end.
LOGO
空
your family site
your site here
LOGO
//查找元素x有没有出现在hash表中 function find(x: longint ):longint; var p,cod:longint;
your family site
begin
cod := x mod maxM; //hash函数 p:=hash[cod]; //hash值为cod的链表开头 while (p>0) and (data[p].x <> x ) do //在这个链表中查找x p:=data[p].next; exit (p); //返回找到的节点地址(下标) end;
your site here
•如果是“静态”的,通常可以先对数据排 序,查找时就可以用“二分查找”,时间 效率也很好了。 •虽然可以用“平衡树”之类方法,但实践 中,用hash表更简单实用。
LOGO
哈希表(hash)
hash表的引入
•普通的查找方法建立在“比较”的基础上,查找 的效率与比较次数密切相关。
your site here
var
data : array[1..maxN] of Tnode; //数据节点记录 hash : array[0..maxm] of longint; //hash表.可直接Tnode,无data N, i : longint ;
LOGO
哈希表(hash)
hash表的性探测法实现pascal版
your site here
var
data : array[1..maxN] of Tnode; //数据节点记录 hash : array[0..maxm] of longint; //hash表的链表头,开始为0 N,i : longint ;