查找算法笔记

目录

查找的基本概念

顺序查找

 算法实现

效率分析

二分查找(折半查找)

代码实现

效率分析

哈希查找(散列查找)

哈希表(散列表)的基本概念

散列函数的构造方法

要解决的问题

直接定址法

除留余数法

处理冲突的方法

开放定址法(线性探测法和二次探测法)

链地址法(拉链表)

哈希表的查找

效率分析

 几点结论:



查找的基本概念

查找表:有同一类型的数据元素构成的集合(或记录)。由于“集合”中的数据元素之间存在着松散的关系,因此查找表是一种应用灵便的结构。没有严格的前驱后继关系。

什么是查找:根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录)。

关键字:用于表示一个数据元素(或记录)的某个数据项的值。

主关键字:可唯一的标识一个记录的关键字。

次关键字:用以标识若干记录的关键字。

若查找表中存在这样一个记录,则称“查找成功”,查找结果给出整个记录的信息,或指示该记录在查找表中的位置。否则称“查找不成功”,查找结果给出空记录或空指针。

静态查找表:仅作查询操作的查找表。

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

如何评价查找算法

平均查找长度:ASL(Average Search Length)


顺序查找

应用范围顺序表线性链表表示的静态查找表;表内元素无序

数据元素类型定义:

typedef char KeyType;
typedef struct{
    KeyType key;//关键字域
                //其他域
}ElemType;

typedef struct{
    ElemType *R;//表基址
    int length;//表长
}sstable;
//sstable st;

 算法实现

(只用查找一次):

int Search_Seq(sstable st,KeyType key){
    st.R[0].key = key;
    int i;
    for(i = st.length;st.R[i].key!=key;i--);
    return i;
}

效率分析

时间复杂度:O(n)

空间复杂度:O(1)

如何提高查找效率?

已知查找概率的情况下,在查找表进行存储时,就按照概率的高低来存储。

若是从前往后找,就将查找概率高的放在前面。

不知道查找概率时:动态调整记录顺序

1.在每个记录中设置一个访问频度域,始终保持记录按有序的次序排列;

2.每次查找后将刚查找到的记录直接移至表头;

顺序查找法的特点

优点:算法简单,逻辑次序无要求,且不同存储结构均适用。

缺点:ASL太长,时间效率太低。


二分查找(折半查找)

用在有序表示的顺序查找表。

代码实现

int Search_Bin(sstable st,KeyType key){
    int low = 1;
    int high = st.length;
    int mid;
    while(low<=high){
        mid = (low+high)/2;
        if(st.R[mid].key == key)
            return mid;
        else
            if(key<st.R[mid].key)
                high = mid -1;
            else
                low = mid + 1;
    }
    return 0;
}//用循环的二分查找

int Search_Bin2(sstable st,KeyType key,int low,int high){
    if(low>high)
        return 0;
    int mid;
    mid = (low+high)/2;
    if(key==st.R[mid].key)
        return mid;
    else
        if(key<st.R[mid].key){
            high = mid - 1;
            Search_Bin2(st,key,low,high);
        }
        else{
            low = mid+1;
            Search_Bin2(st,key,low,high);
        }
}//用递归的二分查找

效率分析

紫色矩形中:-1表示比第1个数还小,11-表示比第11个数还大。其他表示要查找的数的大小在那个区间。 

 第i层表示需要比较的次数。

同时可以看出比较途中的路径,以查找第4个元素为例:先与6比,再与3比,最后和4比。

平均查找长度ASL(成功时):

 时间复杂度:O(logn)

优点:效率比顺序查找高。

缺点:只适用于有序表,且限于顺序存储结构(对线性链表无效)


哈希查找(散列查找)

哈希表(散列表)的基本概念

基本思想:记录的存储位置与关键字之间存在对应关系。

对应关系——hash函数

Loc(i) = H(keyi)        //H为哈希函数。表示i与其存储位置的关系。例如:H(key)=k;表示k的地址就在k号地址。

优点:查找效率高;

缺点:空间效率低。

散列方法(杂凑法):

        选取某个函数,依该函数按关键字计算元素的存储位置,并按此存放;

        查找时,由同一个函数对给定值k计算地址,将k与地址单元中元素关键码进行比较,确定查找是否成功。

散列函数(杂凑函数):散列方法中使用的转换函数。

冲突:不同的关键码映射到同一个散列地址

        key1!=key2,但是H(key1) = H(key2)

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

散列函数的构造方法

要解决的问题

1.构造好的散列函数

        a.所选函数尽可能简单,以便提高转换效率

        b.所选函数对关键码计算出的地址,应在散列地址集中,均匀分布,以便减少空间浪费。

        即要考虑:执行速度,关键字地长度,散列表的大小,关键字的分布情况,查找频率。

2.制定一个好的解决冲突的方案

        查找时,如果从散列函数计算出的地址中查找不到关键码,则应当依据解决冲突的规则,有规律地查询其他单元。

 地址空间尽量小,元素尽量均匀存放。

直接定址法

Hash(key) = a*key +b (a,b为常数)

优点:以关键字key的某个线性函数值为散列地址,不会产生冲突。

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

除留余数法

Hash(key) = key mod p

关键:如何选取合适的p?

技巧:设表长为m,取p<=m,且p为质数。


处理冲突的方法

开放定址法(线性探测法和二次探测法)

基本思想:有冲突时就去寻找下一个空的散列地址,只要散列表足够大,空的散列地址总能找到,并将数据元素存入。

即:先用hash函数存储,若地址已被占,一个函数Hi来找地址存放,后续一直使用Hi,直到成功。

线性探测法:

二次探测法:

 伪随机探测法:


链地址法(拉链表)

基本思想:相同散列地址的记录链成一个单链表。

m个散列地址就设m个单链表,然后用一个数组将m个指针的表头指针存储起来,形成一个动态的结构。

步骤

链地址法的优点:

非同义词不会冲突,无聚集现象。

链表上的空间动态申请,更适合于表长不确定的情况。


哈希表的查找

 

 

 在一个链的第几个就要比较几次。

效率分析

 

 几点结论:

1.散列表技术具有很好的平均性能,优于一些传统的技术

2.链地址法优于开地址法

3.除留余数法作散列函数优于其它类型函数
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值