1205查找

查找

查找参数

ASL(Average Search Length),即平均查找长度,在查找运算中,由于所费时间在关键字的比较上,所以把平均需要和待查找值比较的关键字次数称为平均查找长度。

img

其中n为查找表中元素个数,Pi为查找第i个元素的概率,通常假设每个元素查找概率相同,Pi=1/n,Ci是找到第i个元素的比较次数。

线性表的查找
  • 顺序查找
  • 折半查找
  • 分块查找

普通查找法

时间效率O(n)

折半查找法:

若k==R[mid].key,查找成功

若k<R[mid].key,则high=mid-1

若k>R[mid].key,则low=mid+1

练习:假定每个元素的查找概率相等,

判定树:总查找次数=每一层的元素个数*层数

总结:

时间复杂度O(log2n)

适合顺序存储结构有序表,插入删除频繁时需要移动很多记录,更适用于静态查找表

分块查找(索引顺序查找)

分块有序,即分成若干子表,要求每个子表的数值都比后一块中数值小(但子表内部未必有序)然后将各子表中的最大关键字构成一个索引表,表中还要包含头指针(起始地址)

查找过程:对索引表使用折半查找法;确定子表之后在内部采用顺序查找法

过程:查找效率:ASL=Lb+Lw(对索引表查找的ASL+对块内查找的ASL)

​ O(log2(n/s+1)+s/2) 分成n/s块

适用于线性表需要快速查找又要动态变化时

树表

表结构在查找过程中动态生成,对于给定值key,若表中存在,则成功返回,若不存在,则插入生成新的记录。

排序二叉树

定义:要么是空树,或者满足以下条件

左子树所有的数<根节点<右子树所有的数

生成方法:【使用中序遍历】

查找方法:先判断根节点,再选择左右子树【时间复杂度O(log2n)】

BSTree Search(BSTree T,KeyType key)
{
    if(!T||key->T->data)
    return T;
    else
    {
        if(T->data>key->data)Searth(T->left,key);
        else Searth(T->right,key);
    }
}

插入:若二叉排序树为空,则插入结点应为根节点;否则,继续在其左、右子树上查找。树中已有,不再插入;树中没有,查找直至某个叶子结点左右子树均为空时,插入【时间复杂度O(log2n)】

删除:

将因删除结点而断开的二叉链表重新链接起来,防止重新链接后树的高度增加

方法:删除的节点缺右子树用左子女填补;缺左子树用右子女填补;都不缺的在右子树上找中序遍历的第一个结点填补,再来处理这个结点的删除问题【时间复杂度O(log2n)】

查找的性能分析

最好:O(log2n)

最差:O((n+1)/2)

平衡二叉排序树(AVL树)

定义: 左右子树高度之差<=1,任意结点的平衡因子只能取-1,0,1【平衡因子算法:左子树深度-右子树深度】

(1)LL平衡旋转: 由于在A的左孩子B的左子树上插入结点F,使 A 的平衡因子由 1 增至 2 而失去平衡。故需进行一次顺时针旋转操作。 即将 A 的左孩子 B 向右上旋转代替 A 作为根结点, A 向右下旋转成为 B 的右子树的根结点。而原来 B 的右子树则变成 A 的左子树。

(2)RR平衡旋转: 由于在 A 的右孩子 C 的右子树上插入结点 F ,使 A 的平衡因子由 -1 减至 -2 而失去平衡。故需进行一次逆时针旋转操作。即将 A 的右孩子 C 向左上旋转代替 A 作为根结点, A 向左下旋转成为 C 的左子树的根结点。而原来 C 的左子树则变成 A 的右子树。

(3)LR平衡旋转: 由于在 A 的左孩子 B 的右子数上插入结点 F ,使 A 的平衡因子由 1 增至 2 而失去平衡。故需进行两次旋转操作(先逆时针,后顺时针)。即先将 A 结点的左孩子 B 的右子树的根结点 D 向左上旋转提升到 B 结点的位置,然后再把该 D 结点向右上旋转提升到 A 结点的位置。即先使之成为 LL 型,再按 LL 型处理

(4)RL平衡旋转: 由于在 A 的右孩子 C 的左子树上插入结点 F ,使 A 的平衡因子由 -1 减至 -2 而失去平衡。故需进行两次旋转操作(先顺时针,后逆时针),即先将 A 结点的右孩子 C 的左子树的根结点 D 向右上旋转提升到 C 结点的位置,然后再把该 D 结点向左上旋转提升到 A 结点的位置。即先使之成为 RR 型,再按 RR 型处理。

变种的AVL树--红黑树

哈希表

基本思想:记录的存储位置与关键字之间存在对应关系,LOC(i)=H(keyi)

优点:查找速度极快O(1),与元素个数没有关系

哈希方法(杂凑法):选取某个函数,依据该函数计算存储位置

冲突:不同的关键码映射到同一个哈希地址,key1!=key2,H(key1)=H(key2)

哈希函数的构造方法

直接定址法

例如:H[key]=a*key+b

优点:不会产生冲突

缺点:要占用连续地址空间,空间效率低

除留余数法

H[key]=key mod p

p选取小于元素个数的最大质数

数字分析法

折叠法

平方取中法

处理冲突的方法

(1)开放地址法

基本思想:有冲突时就去寻找下一个空的哈希地址,只要哈希表足够大,空的哈希地址总能找到

线性探测法:H=(Hash(key)+di) mod m,找下一个空余的位置【缺点:产生“二次聚集”现象,降低查找效率】

二次探测法:H=(Hash(key)+di) mod m,(d=1^2 ,2^2, -1^2, -2^2)

伪随机探测法:H=(Hash(key)+di) mod m(di为伪随机数)

【二次探测法和伪随机探测法可以避免“二次聚集”,但不能保证一定找到不发生冲突的地址】

步骤:

1.取数据的关键字key,计算其哈希函数值(地址),若该地址对应的存储空间为空,存入函数,否则执行第2步;

2.根据选择的冲突方法计算地址值存入下一个

(2)链地址法

基本思想:相同哈希地址的记录连成一单链表(同义词链表),m个哈希地址就设m个单链表,然后用一个数组储存表头

优点:非同义词没有冲突,无聚集现象;链表上结点空间动态申请,可扩长表长

有冲突处理的哈希表的查找

查找效率与装填因子a有关,不是o(1)也不是o(n)

a=表中填入的记录数/哈希表的长度

结论:链地址法优于开放地址法

地址的记录连成一单链表(同义词链表),m个哈希地址就设m个单链表,然后用一个数组储存表头

优点:非同义词没有冲突,无聚集现象;链表上结点空间动态申请,可扩长表长

有冲突处理的哈希表的查找

查找效率与装填因子a有关,不是o(1)也不是o(n)

a=表中填入的记录数/哈希表的长度

结论:链地址法优于开放地址法

除留余数法作哈希函数优于其他类型函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值