查找技术

一、查找的基本概念
1.列表:由同一类型的数据元素组成的集合。
关键码:数据元素中的某个数据项,可以标识列表中的一个或一组数据元素。
键值:关键码的值。
主关键码:可以唯一地标识一个记录的关键码。
次关键码:不能唯一地标识一个记录的关键码。
2.查找 :在具有相同类型的记录构成的集合中找出满足给定条件的记录。
查找的结果 :若在查找集合中找到了与给定值相匹配的记录,则称查找成功;否则,称查找失败。
3.静态查找 :不涉及插入和删除操作的查找 。
动态查找 :涉及插入和删除操作的查找。
静态查找适用于:查找集合一经生成,便只对其进行查找,而不进行插入和删除操作; 或经过一段时间的查找之后,集中地进行插入和删除等修改操作;
动态查找适用于:查找与插入和删除操作在同一个阶段进行,例如当查找成功时,要删除查找到的记录,当查找不成功时,要插入被查找的记录。
4.查找结构 :面向查找操作的数据结构 ,即查找基于的数据结构。
线性表:适用于静态查找,主要采用顺序查找技术、折半查找技术。
树表:适用于动态查找,主要采用二叉排序树的查找技术。
散列表:静态查找和动态查找均适用,主要采用散列技术。
二、线性表的查找技术
1.普通的顺序查找
基本思想:
从线性表的一端向另一端逐个将关键码与给定值进行比较,
若相等,则查找成功,给出该记录在表中的位置;
若整个表检测完仍未找到与给定值相等的关键码,则查找失败,给出失败信息。

int SeqSearch1(int r[ ], int n, int k)//数组r[1] ~ r[n]存放查找集合
{   
     i=n;
     while (i>0 && r[i]!=k)
         i--;
     return i;
}

2.改进的顺序查找
基本思想:
设置“哨兵”。
哨兵就是待查值,
将哨兵放在查找方向的尽头处,
免去了在查找过程中每一次比较后都要判断查找位置是否越界,从而提高查找速度。

int SeqSearch2(int r[ ], int n, int k) //数组r[1] ~ r[n]存放查找集合
{   
     r[0]=k; i=n;
     while (r[i]!=k)
        i --;
     return i;
}

3.折半查找
(1)适用条件
线性表中的记录必须按关键码有序
必须采用顺序存储
(2)基本思想:
在有序表中(low, high,low<=high),
取中间记录作为比较对象,
若给定值与中间记录的关键码相等,则查找成功;
若给定值小于中间记录的关键码,则在中间记录的左半区继续查找;
若给定值大于中间记录的关键码,则在中间记录的右半区继续查找。
不断重复上述过程,直到查找成功,或所查找的区域无记录,查找失败。
(3)递归算法

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;
     }
 }

(4)非递归算法

int BinSearch1(int r[ ], int n, int k){ 
  int  low=1; high=n,mid;
    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;
}

三、数表的查找技术
1.二叉排序树
(1)二叉排序树(也称二叉查找树):或者是一棵空的二叉树,或者是具有下 列性质的二叉树:
⑴若它的左子树不空,则左子树上所有结点的值均小于根结点的值;
⑵若它的右子树不空,则右子树上所有结点的值均大于根结点的值;
⑶ 它的左右子树也都是二叉排序树。
(2)二叉排序树的插入算法

void BiSortTree::InsertBST(BiNode<int> * &root, BiNode<int> *s)
{  
    if (root==NULL)  
       root=s;
    else  
            if (s->data<root->data)
                 InsertBST(root->lchild, s);
            else   
                 InsertBST(root->rchild, s);
}

(3)二叉排序树的构造算法

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);
    }
}

(4)二叉排序树的删除算法
基本思想:
1.若结点p是叶子,则直接删除结点p;
2. 若结点p只有左子树,则只需重接p的左子树;
若结点p只有右子树,则只需重接p的右子树;
3. 若结点p的左右子树均不空,则
3.1 查找结点p的右子树上的最左下结点s及s双亲结点par;
3.2 将结点s数据域替换到被删结点p的数据域;
3.3 若结点p的右孩子无左子树,
则将s的右子树接到par的右子树上;
否则,将s的右子树接到结点par的左子树上;
3.4 删除结点s;

void BiSortTree::DeleteBST(BiNode<int> *p, BiNode<int> *f ) {
	 if (!p->lchild && !p->rchild) 	{   
              if(f->child==p)        f->lchild= NULL;  
              else  f->lchild= NULL; 
              delete p;
	  }
	 else if (!p->rchild) {     //p只有左子树
             if(f->child==p)   f->lchild=p->lchild;
             else f->rchild=p->lchild;
	               delete p;
	 }
	 else if (!p->lchild) {   //p只有右子树
		 if(f->child==p)  f->lchild=p->rchild;
		 else f->rchild=p->rchild;
            delete p;
        	}
else {   //左右子树均不空
             par=p;  s=p->rchild;  
             while (s->lchild!=NULL)   //查找最左下结点
             {
               par=s;
               s=s->lchild;
             }
             p->data=s->data;
             if (par==p) p->rchild=s->rchild;  //处理特殊情况
                 else par->lchild=s->rchild;    //一般情况
             delete s;
           } //左右子树均不空的情况处理完毕
 }

(5)二叉排序树的查找算法
在二叉排序树中查找给定值k的过程是:
⑴ 若root是空树,则查找失败;
⑵ 若k=root->data,则查找成功;否则
⑶ 若k<root->data,则在root的左子树上查找;否则
⑷ 在root的右子树上查找。
上述过程一直持续到k被找到或者待查找的子树为空,如果待查找的子树为空,则查找失败。
二叉排序树的查找效率在于只需查找二个子树之一。

BiNode *BiSortTree::SearchBST(BiNode<int> *root, int k)
{
    if (root==NULL)
    return NULL;
    else if (root->data==k) 
              return root;
           else if (k<root->data) 
                      return SearchBST(root->lchild, k);
                  else 
				return SearchBST(root->rchild, k);
}

2.平衡二叉树
(1)基本思想:
在构造二叉排序树的过程中,每插入一个结点时,首先检查是否因插入而破坏了树的平衡性,
若是,
则找出最小不平衡子树,
在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的链接关系,进行相应的旋转,使之成为新的平衡子树。
(2)设结点A为最小不平衡子树的根结点,对该子树进行平衡调整归纳起来有以下四种情况:
1. LL型
2. RR型
3. LR型
4. RL型
三、散列表的查找技术
1.概述
散列表:采用散列技术将记录存储在一块连续的存储空间中,这块连续的存储空间称为散列表。
散列函数:将关键码映射为散列表中适当存储位置的函数。
散列地址:由散列函数所得的存储位置址 。
冲突:对于两个不同关键码ki≠kj,有H(ki)=H(kj),即两个不同的记录需要存放在同一个存储位置,ki和kj相对于H称做同义词。
2.散列函数的构造
直接定址法
除留余数法
数字分析法
平方取中法
折叠法(分段叠加法)
冲突处理方法
开放定址法
链地址法
建立公共溢出区

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值