线性表的查找

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

H(k1)=061 H(k2)=052 H(k3)=363 H(k4)=144 H(k5)=961 H(k6)=227 H(k7)=038
有80个记录,其关键字为8位十进制数,设散列 表的表长为100
81346532 81372242 81387422 81301367 81322817 81338967 81354157 81368537
若表长m=128 p=127 k=4731 H(k)=473 mod127 =32
解决冲突
• 在发生冲突时,为冲突元素找到另一个散 列地址以存放该元素
– 发生第一次冲突时,经处理得到新地址H1 – 发生第二次冲突时,经处理得到新地址H2 – 发生第n次冲突时,经处理得到新地址Hn,不再 冲突
• 开式寻址法 • 拉链法
基本运算操作
• 初始化散列表
void makenull(t) int t[ ]; { int i; for (i=0;i<m;i++) t[i]=0;}
在长度为m=8的散列表中存入11,26,18 散列函数H(k)=k MOD 7
0
0
1
0 0
2
3
0
4
0 0
5
0
6
0
7
0
0
1
0 0
2
3
0
4
11
5
26 0
int bisect(a,n,v) int a[ ],v; int n; { int i,j,m; i=0; j=n-1; while (i<=j) { m=(i+j)/2; if (v= =a[m]) return(m); if (v<a[m]) j=m-1; else i=m+1} return(-1);}
int insertl(t,k) int t[ ],k; { int i,j; i=h(k); for (j=0;j<m&&t[(i+j)%m]!=k && t[(i+j)%m]>0;j++) ; i=(i+j)%m; if (t[i]<=0) { t[i]=k; return(0);} return(1);}
65 22 74 13 28 89 41 85
43 74 82 06 21 36 55 63
平方取中法
• 把元素值平方后取中间的若干位作为散列地址 若散列表的地址范围为[000,999] k=4731 k2=22382361 H(k)=382
叠加法
• 把元素值分割成位数相同的部分,然后把这 几部分的叠加和作为散列值
分块查找法
22 0 7 48 7 6 86 13 6
22 2 12 13 8 9 20 33 42 44 38 24 48 60 58 74 49 86 53
分块查找法
• 把表分成若干块
– 每块中记录的存储顺序是任意的 – 块与块之间必须按关键码有序 – 索引表
• 查找过程:
– 查找索引表,确定要找的记录在哪一块 – 在相应的块中查找
int seque2(a,n,v) int a[ ],v; int n; { int i; a[n]=v; for (i=0; a[i]!=v; i++) ; if (i<n) return(i); return(-1); }
#include<stdio.h> struct node { int data; struct node *link; } typedef struct node NODE; NODE *head; NODE *seque3(head,v) NODE *head; int v; { for ( ;head!=NULL && head->data!=v ; head=head->link); return(head); }
二分查找法
• 在具有n个结点的线性表按键值的递增次序 排列,且按顺序存贮方式存贮
置i=0,j=n-1; 若i>j ,则查找失败,算法结束;否则转(3) 置m=(i+j)/2; 若v=a[m],则查找成功,算法结束;否则转(5) 若v<a[m],则置j=m-1,转(2);否则置i=m+1,转(2)
#deifne MAXN 100 int a[MAXN]; int n;
在长度为m=8的散列表中已存入11,26 散列函数H(k)=k MOD 7
0 k=18 H(18)=4 冲突 线性再散列 H1=(H(18)+1) MOD 8=5 H2=(H(18)+2) MOD 8=6 0 1 2 3 4
11
1
2
3
4
11
5
26
6
7
5
26
6
18
7
二次再散列: H(1)=(H(18)+1)MOD 8=5 二次再散列 H(2)=(h(18)-1)MOD 8=3 0 1 2 3 4 5 6 7
有一个解放后出生的人口调查表,关键字是年份 H(k)=k+(-1948) a=1 b=-1948
地址 年份 人数
01 1949
02 1950
03 ……… 22…..
50
1951…… 1970…… 1999 5000 …… 1050………900
3000 2000
数字分析法
• 设元素是以r基的数,且表中元素的可能值已知, 从中任意取出相当多的元素进行分析,取其中 位值分布比较均匀的若干位组成散列函数 有一个表的地址范围为[000,999],元素值均为8位 十进制数,从中抽取7个元素如下:
开式寻址法解决冲突
• 在发生冲突时求Hi的方法: Hi=(H(k)+di)MOD m i=1,2,……n H(k):散列函数 m:表长 di:地址增量
开式寻址法解决冲突
• di的取值:
– di=1,2,3,……线性再散列 – di=12,-12,22,-22,……二次再散列 – di=伪随机数序列 伪随机散列
H(k)=k MOD 7
0
0 0
1
0
2 2
0
3
0
4
11
5
26
6
18
7
0
删除11
0
0 0
1
3
0 0
4
5
26
6
18 0
7
找18
0
0 0
1
0
2
3
0
4
-1
5
26
6
18
7
0
基本运算操作
• 散列表的删除
– 在散列表t[m]上进行查找 – 如查找成功,t[j]=k,则删除t[j] – 标上已被删除的标记
int deletel(t,k) int t[ ],k; { int i,j; i=h(k); for (j=0; j<m&& t[(i+j)]%m]!=k && t[(i+j)]%m]!=0;j++); i=(i+j)%m; if (t[i]= =k) { t[i]=-1; return(0);} return(1); }
k1=06103041 k2=05101042 k3=36101043 k4=14102004 k5=96105001 k6=22201147 k7=03202008
k1=06103041 k2=05101042 k3=36101043 k4=14102004 k5=96105001 k6=22201147 k7=03202008
线性表的查找
• 对给定的线性表和某一键值V,从线性表 中找一个键值为V的结点. • 衡量查找方法A的一般标准:
– MAX(A):比较次数的最大值 – AVG(A):比较次数的平均值
线性表的查找
• • • • 顺序查找 二分查找 分块查找 散列查找
顺序查找法
• 把线性表中的结点k0,k1,….,kn-1键值V作比 较
int searchl(t,k) int t[ ],k; { int i,j; i=h(k); for (j=0;j<m&&t[(i+j)%m]!=k && t[(i+j)%m]!=0;j++); i=(i+j)%m; if (t[i]= =k) return(i); return(-1); }
散列表的删除
基本运算操作
散列表的查找
H(k)=k MOD 7
0
0 0
1
0
2
3
0
4
11
5
26
6
18
7
0
(1)找26 (2)找18 (3)找25
基本运算操作
• 散列表的查找
– 计算出H(k)=i – 如t[i]=k,查找成功 – 如t[i]!=k 按照线性再散列的循环控测地址序列 进行查找 • 当前位置上的键值等于k,查找成功 • 找到一个空位置,则查找失败 • 用完循环控测地址序列仍末找到k,查找失败
基数转换法
• 设散列表中元素原来是十进制数,人为地 当作q进制数,再转换成十进制数后作为 Hash地址
k=(4731)10 q=13 H(k)=4*133+7*132+3*13+1*13 =(110011)10
除留余数法
• 取关键字被某个不大于散列表表长m的数 p除后得余数为散列地址 H(k)=k mod p (p<=m)
二分查找法
087 154 170 275 426 503 509 512 612 653 677 703 765 897 查找653 087 154 170 275 426 503 509 512 612 653 677 703 765 897 512 612 653 677 703 765 897 512 612 653 653
直接定址法
• 取元素值的某个线性函数为散列函数 H(k)=a*k+b a和b为常数 建立一个从1岁到100岁的人口数字统计表,关键 字为年龄. H(k)=k a=1 b=0
地址 年龄 人数
01 1
02 2
03 ……… 25 26 27….. 100 3…… 25 26 27……100
3000 2000 5000 …… 1050……...
– 在分割时,最后一部分的位数如不够,不足位空 – 在叠 加时,最高位进位舍去
• 移位叠加 • 折迭叠加
移位叠加
• 把分割后的每一部分右对齐然后相加 K=12320324112 地址范围为[000,999] 123 203 241 12 H(k)=579
折迭叠加
• 把分割后的每一部分来回折迭相加 K=12320324112 地址范围为[000,999] 123 302 241 21 H(k)=687
6
7
0
0
0 0
1
2
0
3
0
4
11 26
5
6
18
7
0
基本运算操作
• 散列表的插入
– 计算出H(k)=i – 如t[i]是一个空位置,把k存入t[i] – 如t[i]不是一个空位置,判断t[i]是否等于k • 如相等,插入成功 – 用线性再散列法进行冲突处理 – 找到一个空位置,存入在其中,插入成功 – 如果找不到空位置,散列表满,插入失败
– 如果找到所需结点,则查找成功; – 如果整个表都查遍了,仍末找到所需的结点, 由查找失败. – MAX(顺序查找法) – AVG(顺序查找法)
• 顺序存贮及链接存贮
#define MAXN 100 int a[MAXN] int n; int sequel(a,n,v) int a[ ],v; int n; { int i; for (i=0;i<n && a[i]!=v;i++) ; if (i<n) return(i) return(-1); }
二分查找法
087 154 170 275 426 503 509 512 612 653 677 703 765 897 查找400 087 154 170 275 426 503 509 512 612 653 677 703 765 897 087 154 170 275 426 503 275 426 503 275
18 11 26
伪随机再散列 0 1
18
H(1)=(H(18)+5)MOD 8=1 3 4
11
2
5
26
6
7
设有一组关键字(19,01,23,14,55,20,84,27), 采用散列函数: H(k)=k MOD 13 试在[0,18]的散列地址空间中对该关键字序列 构造散列表 线性再散列 二次再散列 伪随机散列,取伪随机序列为3,54,11,36,19…...
散列查找
• 根据来自百度文库键码值k计算出函数值h(k),即为关键 码k的记录的存储位置
– 散列函数:h(k) – 散列表:T[m] k1<>k2 h(k1)=h(k2) – 冲突:不同的关键码值映射到同一个存储位置 – 同义词:
• 选择散列函数 • 设计有效的解决冲突的方法
散列函数
• • • • • 直接定址法 数字分析法 平方取中法 叠加法 除留余数法
• 顺序存贮及链接存贮
F是含有六个结点的线性表,其中: k0=(9,e) k1=(12,b) k2=(20,c) k3=(26,a) k4=(34,d) k5=(48,f)
0 1 2 3 4 5 6 7 8 9 20 12 34 26 48 9 e b d a f e
H(x)=x mod 10 散列函数 存贮区域[0,9] 数组T[10]为散列表
相关文档
最新文档