9.1静态查找表
c语言数据结构查找算法大全

printf("This number does not exist in this array.\n");
else
printf("a[%d]=%d\n",p,x);
}
9.2.2 折半查找(二分查找)
使用折半查找必须具备两个前提条件:
(1)要求查找表中的记录按关键字有序(设,从小到大有序) (2)只能适用于顺序存储结构
}
※折半查找算法性能分析:
在折半查找的过程中,每经过一次比较,查找范围都要缩小一半,所 以折半查找的最大查找长度为
MSL=[log2 n]+1
当n足够大时,可近似的表示为log2(n)。可见在查找速度上,折半查找 比顺序查找速度要快的多,这是它的主要优点。
结论:折半查找要求查找表按关键字有序,而排序是一 种很费时的运算;另外,折半查找要求表是顺序存储的,为 保持表的有序性,在进行插入和删除操作时,都必须移动大 量记录。因此,折半查找的高查找效率是以牺牲排序为代价 的,它特别适合于一经建立就很少移动、而又经常需要查找 的线性表。
查找技术分为: 1 静态查找表技术 顺序查找、折半查找、索引顺序查找 2 动态查找表技术 二叉查找树 3哈希表技术 哈希表技术
※查找算法的衡量指标
在查找一个记录时所做的主要操作是关键字的比较, 所以通常把查找过程中对关键字的平均比较次数作为衡量 一个查找算法效率优劣的标准,并称平均比较次数为平均 查找长度(Average Search Length)。平均查找长度的 定义为:
high2=N-1;
/*N为查找表的长度,high2为块在表中的末地址*/
else
high2=ID[low1+1].addr-1;
第九章 查找

} // Search_Seq
例:在顺序查找表中查找key=8的关键字 ST.elem
0 8 1 100 2 10 3 0 4 8 i 5 1 6 3 7 7
查找成功 i=4
9.1.1 顺序表的查找性能分析
等概率下查找成功的平均查找长度:Pi=1/n;Ci=n-i+1,
1 ASLSS n
(n i 1)
9.1.2 有序表的查找的性能分析
•判定树:用二叉树描述折半查找过程,树中每个结点表示一个 记录,结点值为该记录在表中的位臵,结点所在的层次表示查找 该值需要进行的比较次数。则有如下的表:
位臵 0 1 2 3 4 5 6 7 8 9 10 11
05 13 19 21 37 56 64 75 80 88 92
} // Search_Seq
例:在顺序查找表中查找key=8的关键字 ST.elem
0 8 1 100 2 10 3 0 4 8 5 1 6 3 i 7 7
9.1.1 顺序表的查找
适用场合:以顺序表表示静态查找表,表内元素无序。
思想:从表中最后一条记录起,逐个比较记录关键字与给定值, 若相等查找成功;反之,直至与第一条记录不等,查找不成功 int Search_Seq( SSTable ST, KeyType key ) { ST.elem[0]. key = key;//哨兵 for ( i = ST.length ; ! EQ(ST.elem[i]. key, key ) ; - - i ); return i;
比较次数 0 3 4 2 3 4 1 3 4 2 3 4
查找的定义和术语(2)
“特定的”数据元素 关键字(Key):数据元素中某个数据项的值,用以标识一个 数据元素 主关键字(Primary Key):可以唯一标识一个记录的关键 字 次关键字(Secondary Key):用以识别若干记录的关键 字 查找(Searching):根据给定值,在查找表中确定一个其关 键字等于给定值的数据元素或记录. 查找成功(Searching Success):若存在这一记录,给 出该记录信息或指示该记录在表中的位臵 查找不成功(Searching Failed):若查找表中不存在这 一记录,给出“空记录”或“空指针”。
数据结构教案第9章 查找

●性能分析 定义:为了确定记录在查找表中的位置,需和给定值进行比 较的关键字个数的期望值称为查找算法在查找成功时的平均查找 长度。
ASL = ∑ Pi C i
i =1
n
其中:Pi为查找表中第i个记录的概率;Ci为找到第i个记 录的比较次数; 查找成功的平均查找长度:
1 n n +1 ASL = ∑ (n − i + 1) = 2 n i =1
索引表 最大关键字 起始地址
22 48 86 1 7 13
22 12 13 8 9 20 33 42 44 38 24 48 60 58 74 49 86 53
9.2动态查找表 特点:表结构本身是在查找过程中动态生 成的,即对于给定值key,若表中存在其关键 字等于key的记录,则查找成功返回;否则插 入关键字等于key的记录。
10 10 9 15 9 17 17 15
a
16
作业:(P55)9.9, 9. 33
9.3哈希表 9.3.1什么是哈希表 哈希函数:在记录的关键字和它的存储位置之间建立 一个确定的对应关系f,使每个关键字和结构中一个 唯一的存储位置相对应,称对应关系f为哈希(Hash) 函数。 哈希表:按哈希函数建立的表称为哈希表。
void Delete(BiTree &p){ if(!p->rchild) { q=p; p=p->lchild; free(q); } else if(!p->lchild) { q=p; p=p->rchild; free(q); } else{ q=p; s=p->lchild; while(s->rchild) {q=s; s=s->rchild;} p->data=s->data; if(q!=p) q->rchild=s->lchild; \*q!=p正常情况 else q->lchile= s->lchild; \* q=p意外者,p的左子树的根没有右子树 free(s); }\\else }
静态查找

查找的基本方法
基于线性表的查找法 ——顺序查找法、折半查找法、分块查找法 比较式查找法 基于树的查找法 —— ——二叉排序树、平衡二叉排序树、B树 B
顺序查找的算法
//不设置监视哨 int seqsearch(l, k) RecordList l; keytype k; { i=l.length; while(i>=1&&l.r[i].key!=k) i--; if(i>=1) return i; else return 0; }
监视哨: 监视哨:l.r[0],起 , 防止越界的作用
基本概念
关键字:数据元素的某个数据项的值。 关键字:数据元素的某个数据项的值。
主关键字: 主关键字:一个关键字可以唯一标识列表中的 一个元素 注意:如果数据元素只有一个数据项时, 注意:如果数据元素只有一个数据项时,数据 元素的值就是关键字
查找的基本概念
列表): (1)查找表 列表 :由同一类型的数据元素(或记录) )查找表(列表 由同一类型的数据元素(或记录) 构成的集合。 构成的集合。 如图的学生招生录取登记表。 如图的学生招生录取登记表。
数据元素( (5)关键字(Key)——数据元素(或记 )关键字( ) 数据元素 中某个数据项的值, 录)中某个数据项的值,用它可以标识数 据元素(或记录)。 据元素(或记录)。 (6)主关键字(Primary Key)——可以 )主关键字( ) 可以 唯一地标识一个记录的关键字称为主关键 如图的“学号” 字。如图的“学号”。
基本概念
数据结构_查找原理及典型的查找算法

3.对非线性(树)结构如何进行折半查找? 可借助二叉排序树来查找(属动态查找表形式)。
9.1.2 有序表的查找
折半查找过程可以描述为一棵二叉树
折半查找的判定树 如:(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11)
总之:
二叉排序树既有类似于折半查找的特性,又采用了链 表存储,它是动态查找表的一种适宜表示。
一、二叉排序树
(3)构造过程: 例:输入序列{45,12,37,3,53,100,24}
45
12
53
3
37
100
24
一、二叉排序树
(2)非递归查找过程 BiTree SearchBST(BiTree T,KeyType key){
CH9 查找
查找的基本概念 9.1 静态查找表
9.1.1 顺序查找 9.1.2 有序表的查找 9.1.3 索引顺序表的查找
9.2 动态查找表
9.2.1 二叉排序树和平衡二叉树 9.2.2 B-和B+树
9.3 哈希表
查找的基本概念
1.查找表 2.查找
关键字 主关键字 次关键字
}
9.2.1 二叉排序树和平衡二叉树
一、二叉排序树 二、平衡二叉树
一、二叉排序树
1.定义、特点、构造过程
(1)定义 二叉排序树或者是一棵空树,或是具有下列性质的二叉树:
若左子树非空,则左子树上所有结点的值均小于它的 根结点的值。
若右子树非空,则右子树上所有结点的值均大于它的 根结点的值。
有序/无序表 有序表
顺序/链式存 储
顺序存储
分块查找 介于二者之间 表中元素逐段有序 顺序/链式存储
数据结构查找表

如何进行查找
在一个结构中查找某个数据元素的过程,依赖于数据 元素在结构中的地位,即依赖于数据元素的组织关系 (人为的)。
在计算机中进行查找的方法随数据结构不同而不同。 即随查找表的不同而不同。
9.1 静态查找表
顺序表的查找 有序表的查找 静态树表的查找
查找表的结构 查找过程描述 查找性能分析 查找方法比较
n ASLbs log 2 ( 1) 1 s
9.2 动态查找表
动态查找表的ADT
动态查找表的特点是,表结构本身是在查找过程中动态生成的。即, 对于给定值key,若表中存在其关键字等于key的记录,则查找成 功返回;否则,插入关键字等于key的记录。
P226: SearchDSTable(DT,key ); InsertDSTable(&DT,e ); DeleteDSTable(&DT, e );
给定值进行比较的关键字个数最多也不超过log2 n 1
折半查找的ASL
假设有序表的长度为n=2h-1,则描述折半查找的判定树是深度 为h的满二叉树。 该树中层次为1的结点有1个,层次为2的结点有2个,…,层次 为h的结点有2h-1个。 假设有序表中每个记录的查找概率相等(Pi = 1/n)。
05 low 13 19 21 37 56 64 75 80 88 92 high
mid
high low
mid (low high) / 2
例子
给定值key = 21的查找过程: 给定值key = 85的查找过程:
下界low>上界high,查找不成功。
int Search_Bin( SSTable ST,KeyType key ){ low = 1; high = ST.length; while( low <= high ){ mid = ( low + high ) /2; if EQ( key , ST.elem[mid].key ) return mid; else if LT( key , ST.elem[mid].key ) high = mid-1; else low = mid +1; } return 0; }
第九章查找3哈希表

解决方案:可采用二次探测法或伪随机探测法,以 改善‚堆积‛问题。
9.3
三.处理冲突的方法
哈希表
例2:设哈希表长为11,哈希函数 H(key)=key MOD 11, 试用开放定址法中二次探测再散列解决冲突 Hi(key)=(H(key)+di) MOD 11 (di=12,-12,22,-22,…,k2,-k2 ), 试对下列关键字序列(19,13,33,02,16,29,24) 构造哈希表HT。
9.3
哈希表
0
1 BAI 2 CHEN
例:假设在例2的记录集合中添 加关键字{DAI,ZHOU,…}。 4、冲突 对不同的关键字可能得到同一 哈希地址的现象叫做冲突。
……
3 DIAO
… 6 GAO … 18 SUN 19 TANG
关 键 码 集 合
…
22 WU 23 XIAO 24 YI 25 ZHAO
9.3
三.处理冲突的方法
3.链地址法
哈希表
9.3
三.处理冲突的方法
1.开放定址法 2.再哈希法
哈希表
3.链地址法(拉链法) 4.建立公共溢出区
P258
9.3
三.处理冲突的方法
例:关键码集合 {47, 7, 29, 11, 16, 92, 22, 8, 3},散列 函数为H(key)=key mod 11,用公共溢 出区法处理冲突, 构造的散列表为:
哈希表
二.哈希函数的构造方法
1、直接定址法 思想:哈希函数为关键字的某个线性函数
H(key)= a.key+b 或 H(key)=key
适应情况:事先知道关键码,关键码集合不是 很大且连续性较好。 优点:不会产生冲突
缺点:占用连续空间,空间效率低
数据结构——第五章查找:01静态查找表和动态查找表

数据结构——第五章查找:01静态查找表和动态查找表1.查找表可分为两类:(1)静态查找表:仅做查询和检索操作的查找表。
(2)动态查找表:在查询之后,还需要将查询结果为不在查找表中的数据元素插⼊到查找表中;或者,从查找表中删除其查询结果为在查找表中的数据元素。
2.查找的⽅法取决于查找表的结构:由于查找表中的数据元素之间不存在明显的组织规律,因此不便于查找。
为了提⾼查找效率,需要在查找表中的元素之间⼈为地附加某种确定的关系,⽤另外⼀种结构来表⽰查找表。
3.顺序查找表:以顺序表或线性链表表⽰静态查找表,假设数组0号单元留空。
算法如下:int location(SqList L, ElemType &elem){ i = 1; p = L.elem; while (i <= L.length && *(p++)!= e) { i++; } if (i <= L.length) { return i; } else { return 0; }}此算法每次循环都要判断数组下标是否越界,改进⽅法:加⼊哨兵,将⽬标值赋给数组下标为0的元素,并从后向前查找。
改进后算法如下:int Search_Seq(SSTable ST, KeyType kval) //在顺序表ST中顺序查找其关键字等于key的数据元素。
若找到,则函数值为该元素在表中的位置,否则为0。
{ ST.elem[0].key = kval; //设置哨兵 for (i = ST.length; ST.elem[i].key != kval; i--) //从后往前找,找不到则返回0 { } return 0;}4.顺序表查找的平均查找长度为:(n+1)/2。
5.上述顺序查找表的查找算法简单,但平均查找长度较⼤,不适⽤于表长较⼤的查找表。
若以有序表表⽰静态查找表,则查找过程可以基于折半进⾏。
算法如下:int Search_Bin(SSTable ST, KeyType kval){ low = 1; high = ST.length; //置区间初值 while (low <= high) { mid = (low + high) / 2; if (kval == ST.elem[mid].key) { return mid; //找到待查元素 } else if (kval < ST.elem[mid].key) { high = mid - 1; //继续在前半区间查找 } else { low = mid + 1; //继续在后半区间查找 } } return 0; //顺序表中不存在待查元素} //表长为n的折半查找的判定树的深度和含有n个结点的完全⼆叉树的深度相同6.⼏种查找表的时间复杂度:(1)从查找性能看,最好情况能达到O(logn),此时要求表有序;(2)从插⼊和删除性能看,最好情况能达到O(1),此时要求存储结构是链表。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
9.1静态查找表
关键字类型说明:
typedef float KeyType; //实型。
typedef int KeyType; //整型。
typedef char *KeyType; //字符串型。
数据元素类型定义:
typedef struct{
KeyType key; //关键字域。
... //其它域。
}ElemType;
对两个关键字的比较:
//--对数值型关键字---
#define EQ(a,b) ((a)==(b))
#define LT(a,b) ((a)<(b))
#define LQ(a,b) ((a)>=(b))
//--对字符串型关键字---
#define EQ(a,b) (!strcmp((a),(b)))
#define LT(a,b) (strcmp((a),(b))<0)
#define LQ(a,b) (strcmp((a),(b))>=0)
...
9.1.1顺序表的查找
//---静态查找表的顺序存储结构-------
typedef struct
{
ElemType *elem; //数据元素存储空间基址,建表时按实际长度分配,0号单元留空。
int length; //表长度。
}SSTable;
程序:
int Search_Seq(SSTable ST,KeyType key)
//在顺序表ST中顺序查找其关键字等于key的数据元素,若找到,则函数值为
//该元素在表中的位置,否则为0。
{
ST.elem[0].key=key;
for(i=ST.length;!EQ(ST.elem[i].key,key);--i);//从后往前找。
return i; //找不到时,i为0。
}//Search_Seq
9.1.2有序表的查找。
①折半查找实例:
(05,13,19,21,37,56,64,75,80,88,92)查找21和85.
(1)找21.
low=1,high=11 ,mid=(low+high)/2=6,ST.elem[mid]=56>21;
low=1,high=mid-1=5,mid=(low+high)/2=3,ST.elem[mid]=19<21;
low=mid+1=4,high=5,mid=(low+high)/2=4,ST.elem[mid]=21=21;
(2)找85.
(05,13,19,21,37,56,64,75,80,88,92)
low=1,high=11 ,mid=(low+high)/2=6,ST.elem[mid]=56<85; low=mid+1=7 ,high=11,mid=(low+high)/2=9,ST.elem[mid]=80<85; low=mid+1=10,high=11,mid=(low+high)/2=10,ST.elem[mid]=88>85; low=10,high=mid-1=9 ,low>high;
②程序
int Search_Bin(SSTable ST,KeyType key)
{
//在有序表ST中折半查找其关键字等于key的数据元素。
若找到,则函数值为//该元素在表中的位置,否则为0。
low=1;high=ST.length; //置区间初值。
while(low<=high)
{
mid=(low+high)/2;
if EQ(key,ST.elem[mid].key) return mid; //找到待查元素。
else if LT(key,ST.elem[mid].key) high=mid-1; //继续在前半区间进行查找。
else low=mid+1; //继续在后半区间进行查找。
}// while
return 0; //顺序表中不存在待查元素。
}//Search_Bin
③折半查找判定树,及找21的过程。
④加上外部节点的判定树,及查找85的过程。
9.1.3静态树表的查找1.公式。
2.程序。
Status SecondOptimal(BiTree &T,ElemType R[],float sw[],int low,int high)
{
//由有序表R[low..high]及其累计权值表sw(其中sw[0]==0)递归构造次优查找树T。
i=low;min=abs(sw[high]-sw[low]);dw=sw[high]+sw[low-1];
for(j=low+1;j<=high;++j) //选择最小的ΔPi值。
{
if(abs(dw-sw[j]-sw[j-1])<min)
{
i=j;min=abs(dw-sw[j]-sw[j-1]);
}// if
}// for(j=low+1;j<=high;++j)
if(!(T=(BiTree)malloc(sizeof(BiTNode)))) return ERROR;
T->data=R[i]; //生成节点。
if(i==low) T->lchild=NULL; //左子树空。
else SecondOptimal(T->lchild,R,sw,low,i-1); //构造左子树。
if(i==high) T->rchild=NULL; //右子树空。
else SecondOptimal(T->rchild,R,sw,i+1,high); //构造右子树。
return OK;
}// SecondOptimal
3.实例。
例9-1:已知含9个关键字的有序表及其相应权值为:
关键字:A B C D E F G H I
权值:1 1 2 5 3 4 4 3 5
00000000000000000000000累计权值和及ΔP值
j 0 1 2 3 4 5 6 7 8 9
A B C D E F G H I
key
j
w
0 1 1 2 5 3 4 4 3 5
j
0 1 2 4 9 12 16 20 23 28
sw
j
ΔPj 27 25 22 15 7 0 8 15 23
(根) ↑i
ΔPj 11 9 6 1 9 8 1 7
(根) ↑i ↑i
ΔPj 3 1 2 0 0 0
(根) ↑i ↑i ↑i ↑i
ΔPj 0 0
(根) ↑i ↑i
00000000000000000000000
例9-2:已知含5个关键字的有序表及其相应权值为
关键字:A B C D E
权值: 1 30 2 29 3
4.程序。
//---静态查找表的顺序存储结构-------
typedef struct
{
ElemType *elem; //数据元素存储空间基址,建表时按实际长度分配,0号单元留空。
int length; //表长度。
}SSTable;
typedef BiTree SOSTree; //次优查找树采用二叉链表的存储结构
Status CreateSOSTree(SOSTree &T,SSTable ST)
{
//由有序表ST构造一棵次优查找树T。
ST的数据元素含有权域weight.
if(ST.length==0) T=NULL;
else
{
FindSW(sw,ST);//按照由有序表ST中各数据元素的weight域求累计权值表sw. SecondOptimal(T,ST.elem,sw,1,ST.length);
}
return OK;
}//CreateSOSTree
9.1.4索引顺序表的查找。
略。
--end--。