第 7章 查找技术

1.查找的基本概念

查找 :在具有相同类型的记录构成的集合中找出满足定条件的记录。

查找的结果 :若在查找集合中找到了与给定值相匹配的记录,则称查找成功;否则,称查找失败

静态查找 :不涉及插入和删除操作的查找 。

动态查找 :涉及插入和删除操作的查找。

静态查找适用于:查找集合一经生成,便对其进行查找,而进行插入和删除操作; 或经过一段时间的查找之后,集中地进行插入和删除等修改操作;

动态查找适用于:查找与插入和删除操作在同一个阶段进行,例如当查找成功时,要删除查找到的记录,当查找不成功时,要插入被查找的记录。

查找结构面向查找操作的数据结构 ,即查找基于的数据结构。

线性表:适用于静态查找,主要采用顺序查找技术、折半查找技术。

树表:适用于动态查找,主要采用二叉排序树的查找技术。

散列表:静态查找和动态查找均适用,主要采用散列技术。

平均查找长度:将查找算法进行的关键码的比较次数的数学期望值定义为平均查找长度。计算公式为:

其中:n问题规模,查找集合中的记录个数;

            pi查找第i个记录的概率;

            ci查找第i个记录所需的关键码的比较次数。

结论ci取决于算法;pi与算法无关,取决于具体应用。如果pi是已知的,则平均查找长度只是问题规模的函数。

 

 

2.顺序查找 (线性查找)

基本思想

从线性表的一端向另一端逐个将关键码给定值进行比较,

若相等,则查找成功,给出该记录在表中的位置;

若整个表检测完仍未找到与给定值相等的关键码,则查找失败,给出失败信息。

改进的顺序查找

基本思想:设置“哨兵”

哨兵就是待查值

哨兵放在查找方向的尽头处,

免去了在查找过程中每一次比较后都要判断查找位置是否越界,从而提高查找速度。

顺序查找查找性能的改进方法

记录每个数据的访问频率,

把访问频率高的数据移向顺序表的右端

可以减少查找成功时所进行的比较次数,提高效率

构造有序的顺序表

减少查找失败时所进行的比较次数,提高查找效率

顺序查找的优点:

算法简单而且使用面广。

Ø 对表中记录的 存储结构没有任何要求 ,顺序存储和链接存储均可;
Ø 对表中记录的 有序性也没有要求 ,无论记录是否按关键码有序均可。b

顺序查找的缺点:

平均查找长度较大,特别是当待查找集合中元素较多时,查找效率较低。

 

3.折半查找

适用条件

Ø 线性表中的记录必须按关键码 有序
Ø 必须采用 顺序 存储
 

基本思想

有序表中(low, high,low<=high),

中间记录作为比较对象,

若给定值与中间记录的关键码相等,则查找成功;

若给定值小于中间记录的关键码,则在中间记录的左半区继续查找;

若给定值大于中间记录的关键码,则在中间记录的右半区继续查找。

不断重复上述过程,直到查找成功,或所查找的区域无记录,查找失败。

折半查找 —— 非递归算法

int BinSearch1(int r[ ], int n, int k){

  int  low=1; high=nmid;

    while (low<=high)                  

    {

       mid=(low+high)/2;           

       if (k<r[mid])  high=mid-1;

       else if (k>r[mid])  low=mid+1;

              else return mid;

    }

    return 0;

}

折半查找 —— 递归算法
 

int BinSearch2(int r[ ], int low, int high, int k){   

    if (low>high) return 0; 

    else {

           mid=(low+high)/2;

           if (k<r[mid])

                 return BinSearch2(r, low, mid-1, k);

           else  if (k>r[mid])

                  return BinSearch2(r, mid+1, high, k);

           else return mid;

     }

 }

 
折半查找判定树

判定树折半查找的过程可以用二叉树来描述,

树中的每个结点对应有序表中的一个记录

结点的值该记录在表中位置

通常称这个描述折半查找过程的二叉树为折半查找判定树,简称判定树

判定树的构造方法

⑴ 当n=0时,折半查找判定树为空;

⑵ 当n>0时,

  折半查找判定树的根结点为mid=(n+1)/2

  根结点的左子树是与有序表r[1] ~ r[mid-1]相对应的折半查找判定树,

  根结点的右子树是与r[mid+1] ~ r[n]相对应的折半查找判定树。

判定树的特点

任意两棵折半查找判定树,若它们的结点个数相同,则它们的结构完全相同

判定树的性质

任意结点的左右子树中结点个数最多相差1

任意结点的左右子树的高度最多相差1

任意两个叶子所处的层次最多相差1

查找成功时的平均查找长度ASL:

4.树表的查找技术

二叉排序树(Binary Search Tree

二叉排序树(也称二叉查找树):或者是一棵空的二叉树,或者是具有下列性质的二叉树:

⑴若它的左子树不空,则左子树上所有结点的值均小于根结点的值;

⑵若它的右子树不空,则右子树上所有结点的值均大于根结点的值;

⑶ 它的左右子树也都是二叉排序树。

二叉排序树的插入

void InsertBST(BiNode<int> * & root , BiNode<int> *s);

分析:若二叉排序树为空树,则新插入的结点为新的根结点;否则,新插入的结点必为一个新的叶子结点,其插入位置由查找过程得到。

若二叉排序树为空树,则新插入的结点为新的根结点;

否则,如果插入的值比根节点值大,则在右子树中进行插入;否则,在左子树中进行插入。

递归。

二叉排序树的构造

从空的二叉排序树开始,依次插入一个个结点 。

BiSortTree::BiSortTree(int r[ ], int n){     

    for (i=0; i<n; i++)    {

       s=new BiNode<int>;

       s->data=r[i];

       s->lchild=s->rchild=NULL;

       InsertBST(root, s);

    }

}

二叉排序树的删除

在二叉排序树上删除某个结点之后,仍然保持二叉排序树的特性。

分三种情况讨论:

1. 被删除的结点是叶子;
操作: 将双亲结点中相应指针域的值改为空。
2. 被删除的结点只有左子树或者只有右子树;
操作: 将双亲结点的相应指针域的值指向被删除结点的左子树(或右子树)。
3. 被删除的结点既有左子树,也有右子树
操作: 以其前驱(左子树中的最大值)替代之,然后再删除该前驱结点。

 

1. 若结点 p 是叶子,则直接删除结点 p;

2. 若结点p只有左子树,  则只需重接p的左子树;

    若结点p只有右子树,  则只需重接p的右子树;

3. 若结点p的左右子树均不空,则

   3.1 查找结点p的右子树上的最左下结点ss双亲结点par

   3.2 将结点s数据域替换到被删结点p的数据域;

   3.3 若结点p的右孩子无左子树,

         则将s的右子树接到par的右子树上

二叉排序树的查找

在二叉排序树中查找给定值k的过程是:

⑴ 若root是空树,则查找失败;

⑵ 若k=root->data,则查找成功;否则

⑶ 若k<root->data,则在root的左子树上查找;否则

⑷ 在root的右子树上查找。

     上述过程一直持续到k被找到或者待查找的子树为空,如果待查找的子树为空,则查找失败。

二叉排序树的查找效率在于只需查找二个子树之一。

-

 

5.平衡二叉树(AVL树)

平衡二叉树:或者是一棵空的二叉排序树,或者是具有下列性质的二叉排序树:

⑴ 根结点的左子树和右子树的深度最多相差1;

根结点的左子树和右子树也都是平衡二叉树。

平衡因子:结点的平衡因子是该结点的左子树的深度与右子树的深度之差。

结点的平衡因子=HL-HR

在平衡树中,结点的平衡因子可以是10-1

最小不平衡子树:在平衡二叉树的构造过程中,以距离插入结点最近的、且平衡因子的绝对值大于1的结点为的子树。

基本思想

在构造二叉排序树的过程中,每插入一个结点时,首先检查是否因插入而破坏了树的平衡性,

若是,则找出最小不平衡子树,

  在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的链接关系,进行相应的旋转,使之成为新的平衡子树。

设结点A最小不平衡子树的根结点,对该子树进行平衡调整归纳起来有以下四种情况:

  1. LL

  2. RR

  3. LR

  4. RL

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值