第7章学习小结

查找分为线性表的查找、树表的查找、散列表的查找。

  一些定义:

  查找表:由同一类型的数据元素(或记录)构成的集合(在查找时对表做修改操作,如插入和删除,则称为动态查找表;否则称为静态查找表)

  关键字:数据元素(或记录)中某个数据项的值(如果一个查找表里只存储了关键字,意义不是很大

  平均查找长度ASL:从1到第n个数据元素  查找第 i 个记录的概率 * 找到第 i 个记录所需的比较次数  之和

类型定义

//数据元素类型定义
typedef struct
{
    KeyType key ; //关键字域
    InfoType otherinfo ; //其他域
}ElemType ; 

//顺序表的定义
typedef struct
{ 
    ElemType *R ; //存储空间基地址
    int length ; //当前长度
}SSTable ;

 

一、线性表的查找

  顺序查找

(1)顺序查找方法既适用于线性表的顺序存储结构,又适用于线性表的链式存储结构,表内元素不要求有序

(2)空间复杂度:O(1)

         时间复杂度:O(n)

                              查找成功时(设表中每个记录的查找概率相等),ASL = (1+2+...+n)/ n = (n+1)/ 2

                              查找不成功时,ASL = n+1

int Search_Seq(SSTable ST, KeyType key)
{//在顺序表ST中顺序查找其关键字等于key的数据元素。
 //若找到,则函数值为该元素在表中的位置;否则为0。
    ST.R[0].key = key ; //哨兵
    for(int i = ST.length ; ST.R[i].key != key ; --i) ; //从后往前找
    return i ;
}

 (3)优点:算法简单,对表结构无任何要求,既适用于顺序结构,也适用于链式结构,无论记录是否按关键字有序均可应用。

          缺点:平均查找长度较大,查找效率较低,所以当 n 很大时,不宜采用顺序查找。

  折半查找

 (1)折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列

 (2)空间复杂度:O(1)

          时间复杂度:O(log2n)

int Search_Bin(SSTable ST, KetType key)
{
    int low = 0 ;
    int high = ST.length - 1 ;
    
    while(low <= high)
    {
        int mid = (low + high) / 2 ;
        if(key == ST.R[mid].key)    return mid ; //找到待查元素
        else if(key < ST.R[mid].key)    high = mid - 1 ; //继续在前一子表进行查找
        else low = mid + 1 ; //继续在后一子表进行查找
    }
    return 0 ; //表中不存在待查元素
}
//递归算法
int Search_Bin(SSTable ST, KeyType key, int low, int high)
{
    if(low > high)    return 0 ;

    int mid = (low + high) / 2 ;
    if(key == ST.R[mid].key)    return mid ;
    else if(key < ST.R[mid].key)    return Search_Bin(ST, key, low, mid-1) ;
    else return Search_Bin(ST, key, mid+1, high) ;
}

 (3)优点:比较次数少,查找效率高。

          缺点:对表结构要求高,只能用于顺序表存储的有序表

                     适合一次排序,多次查找。因此,针对有序且静态数据(在动态数据集合中,考虑树查找)

                     数据量小,不需要二分(数组:连续内存空间)

                     数据量太大也不可以用二分

  分块查找(块内无序,块间有序)

  (1)分块查找的平均查找长度为 ASL = 查找索引表确定所在块的平均查找长度 + 在块中查找元素的平均查找长度

  (2) 优点:快速查找 + 动态变化

            缺点:要增加一个索引表的存储空间并对初始索引表进行排序

  

 

二、树表的查找

  二叉排序树:若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值

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

                        它的左、右子树也分别为二叉排序树

                        或者是空树

                      (中序遍历一棵二叉树时可以得到一个结点值递增的有序排列)

//二叉排序树的二叉链表存储表示
typedef struct
{
    KeyType key ;
    InfoType otherinfo ;
}ElemType ;

typedef struct BSTNode
{
    ElemType data ; //每个结点的数据域包括关键字项和其他数据项
    struct BSTNode *lchild, *rchild ; //左右孩子指针
}BSTNode, *BSTree ;

//二叉排序树的递归查找
BSTree SearchBST(BSTree T, KeyType key)
{
    if( (!T ) || key == T->data.key)    return T ;
    else if (key < T->data.key)    return SearchBST(T->lchild, key) ;
    else return SearchBST(T->rchild, key) ;
}

 (1)时间复杂度:最好的情况(类似于折半查找):log2n

                                最坏的情况(类似于顺序查找):(n + 1) / 2

  平衡二叉树:左子树和右子树的深度之差的绝对值不超过1

                        左子树和右子树也是平衡二叉树

                        或者是空树

     平衡因子:该结点左子树和右子树的深度之差,则平衡二叉树上所有结点的平衡因子只可能是-1,0,1

     平衡调整方法:保持有序+平衡

   

  B+树、B-树:多叉树

 

三、散列表的查找

  散列表:一个有限连续的地址空间。通常散列表的存储空间是一个一维数组,散列地址是数组的下标。

  冲突:不同的关键字得到同一散列地址

  同义词:具有相同函数值的关键字

 (1)散列函数的构造方法:数字分析法、平方取中法、折叠法、除留余数法

 (2)处理冲突的方法:开放地址法(线性探测法、二次探测法、伪随机探测法)

                                       链地址法(把具有相同散列地址的记录放在同一个单链表中,称为同义词链表)

//开放地址法散列表的存储表示
#define m 20 //散列表的表长
typedef struct
{
    KeyType key ;
    InfoType otherinfo ;
}HashTable[m] ;

//散列表的查找
#define NULLKEY 0 //单元为空的标记
int SearchHash(HashTable HT, KeyType key)
{
    H0 = H(key) ; //根据散列函数H(key)计算散列地址
    if(HT[H0].key == NULLKEY)    return -1 ;
    else if(HT[H0].key == key)    return H0 ;
    else 
    {
        for(int i=1 ; i<m ; ++i)
        {
            Hi = (H0 + i) % m ; //根据线性探测法计算下一个散列地址Hi
            if(HT[Hi].key == NULLKEY)    return -1 ;
            else if(HT[Hi].key == key)    return Hi ;
         } //for
         return -1 ;
    } //else
}

  (3)装填因子:表中填入的记录数 / 散列表的长度(越大说明表中已填入的记录越多,发生冲突的可能性就越大)

  (4)在查找概率相等的前提下,

               平均长度 ASL = (1/n) * Ci ( i = 1, 2, 3, 4...)           n为散列表中记录的个数,Ci为成功查找第 i 个纪录所需的比较次数)

 

posted @ 2020-06-26 22:31  咕咕鸽子王  阅读(170)  评论(0编辑  收藏  举报