各种查找问题

(一)顺序查找

typedef  ***  KeyType;  //关键字类型                                                                                                  typedef struct {                                                                                                                          KeyType  key; //查询关键字字段                                                                                                            ...;                                                                                                                                                  }ElemType;  //记录类型                                                                                                                    typedef struct {                                                                                                                                  ElemType   *elem;  //首地址,0号他用                                                                                                  int    length;      //表长                                                                                                                          }SSTable;  

int Search_Seq(SStable ST, KeyType x){                                                                                         //思路:从前向后逐一比较,找到返回位序, 否则返回0                                                                       //思路:添加哨兵,从后向前比较,省略每次循环时的越界检查                                                              ST.elem[0].key = x;                                                                                                                        for( i = ST.length; ST.elem[ i ].key != x;   --i  )  ;                                                                                           return i;                                                                                                                              return 0;                                                                                                                                            }//O(n)

(二)折半查找

思路:每轮与有序区间的中间元素进行比较,若相等则返回当前元素的位置;若待查找元素大于中间元素,则到右侧区间查找;若查找元素小于中间元素,则到左侧区间查找,不断重复前述折半查找过程,直至查找成功,或者待查找区间失效!                                                                                    折半查找判定树任意节点左右子树深度相差最多为1,可证此类树深度为[log2n]+1,可证查找成功时最坏查找长度为[log2n]+1,复杂度O(log2n)

使用折半查找的前提是:1.有序  2.可以随机访问

(三)分块查找

分块查找是折半查找顺序查找的一种改进方法,分块查找由于只要求索引表是有序的,对块内节点没有排序要求,因此特别适合于节点动态变化的情况。分块查找要求把一个大的线性表分解成若干块,每块中的节点可以任意存放,但块与块之间必须排序。假设是按关键码值非递减的,那么这种块与块之间必须满足已排序要求,实际上就是对于任意的i,第i块中的所有节点的关键码值都必须小于第i+1块中的所有节点的关键码值。此外,还要建立一个索引表,把每块中的最大关键码值作为索引表的关键码值,按块的顺序存放到一个辅助数组中,显然这个辅助数组是按关键码值费递减排序的。查找时,首先在索引表中进行查找,确定要找的节点所在的块。由于索引表是排序的,因此,对索引表的查找可以采用顺序查找或折半查找;然后,在相应的块中采用顺序查找,即可找到对应的节点。

(四)二叉排序树查找(二叉搜索树)                                                                     

若它的左子树不空,则左子树上所有结点的值均小于它根结点的值。                                                若它的右子树不空,则右子树上所有结点的值均大于它根结点的值。                                                它的左、右树又分为⼆叉排序树                                                                                                        显然,二叉排序树与二叉树一样,也是通过递归的形式定义的。因此,它的操作也都是基于递归的方式。

性能                                                                                                                                                    二叉搜索树一般不直接使用,因为有可能性能很差,二叉搜索树的查找效率主要与树的高度有关,节点个数相同的情况下,二叉搜索树最优的情况是完全二叉树,高度最小,其时间复杂度为O(logN),最差情况下退化为单支树,树的高度等于节点个数,时间复杂度为O(N)。

(五)平衡二插树查找

平衡二叉树的概念:任意节点的平衡因子(左右子树深度之差)的绝对值不超过1。

平衡二叉搜索树的构造:先按照二叉搜索树的节点插入方法插入节点,不满足平衡要求时调整!找到最小不平衡二叉树的根后,根据不平衡种类作相应的旋转!既要保证平衡,也要保证是二叉搜索树!

平衡二叉树的平衡调整:

LL型,RR型,LR型,RL型

(六)B-树和B+树查找

B-树:                                                                                                                                              概念: “平衡”的“多路”“查找”树( 平衡二叉树的推广)                                                                      特点:平衡(叶子节点/失败节点同层) ,多关键字,查找树

  一颗m阶的B树是空树,或是满足下列特性的m叉树:                                                                 (1)树中每个结点至多有m棵子树(m-1个关键字)                                                                                 (2) 根结点或者为叶子结点或者至少有两棵子树                                                                                 (3)根之外所有非终端结点至少有ceil(m/2)棵子树                                                                               (4) 非终端结点包含信息(n, A0,K1,A1,K1,A2,...,Kn ,An) Ki为关键字,有序; Ai为指向子树根结点的指针,且Ai所指子树中所有结点关键字均介于Ki-1和Ki之间.(n<m)                                                           (5)叶结点出现在同一层上,不带信息,相当于查找失败结点

查找:                                                                                                                                              从根结点出发,沿树形结构搜索结点和在结点内进行顺序(或折半)查找 两个过程交叉进行。

插入:                                                                                                                                                若查找成功则不能插入,否则,应试图插入到查找路径中最后一个内部结点上。内部结点关键字个数须在Ceil(m/2)-1和m-1之间,若超界则“分裂” 分裂:选中间关键字上移,当前结点分成两个,下层相应分;若上移导致双亲关键字个数超界则继续上移.

删除:                                                                                                                                                被删节点为最下层非叶节点则直接删,否则用右侧子树最小记录顶替(规约) 内部节点关键字数量有下界Ceil(m/2)-1,低于此值要“求助”或“合并”

2-3树是最简单的B-树

B+树:                                                                                                                                                概念: “平衡”的“多路”“索引”树                                                                                                            特点:平衡(叶子节点/记录节点同层), 多关键字, 索引树, 顺序与随机查找并行

(七)哈希查找

哈希表:根据设定的哈希函数和处理冲突的方法,将一组关键字映象到一组有限的连续的存储空间上,以关键字对应的Hash函数值作存储地址,如此所得的查找表表称为哈希表。

散列:映像过程称为哈希造表或散列,存储地址称为哈希地址或散列地址。 

查找性能:依赖于Hash函数与冲突处理方法的质量!

哈希函数:

线性函数:H(key) = a % key + b

除留取余法:H(key) = key % P(  P通常取素数,或至少不包含20 以下的质因子)

数字分析法:关键字由 s 位数字组成 (u1, u2, …, us),分析全体关键字,从中提取区分度好(数字分布均匀)的若干位构成Hash地址,位数取决于拟定的表长,可直接用某几位区分度好的数字,或者叠加求和 ,适用场合:知道关键字的全部情况,能预先估计出各位上数字出现的情况,选取时尽量避免冲突,且要避免空间浪费

平方取中法:以关键字的平方值的中间几位作为存储地址。平方值的中间各位能受到整个关键字中各位的影响,区分度通常较好,如2061^2=4310541, 2161^2=4734741,H(2061)=310,适用场合:事先不知道关键字情况,或者关键字各位上都有某些数字重复多次出现.较常用

折叠法:将关键字分割成位数相同的若干部分(最后一部分可不同),然后取它们的叠加和为哈希地址。 移位叠加:低位对齐相加,后舍弃越界位 间界叠加:来回折叠取值,后对其相加,如ISBN号0-442-20586-4,每4位一块 移位叠加:5864+4220+04=10088,H(key)=0088 间界叠,适用场合:关键字位数特别多,且每一位上数字分布均匀加:5864+0224+04=6092,H(key)=6092

随机数法:H(key) = Random(key),random()为伪随机函数,适用场合:此方法用于对长度不等的关键字构造哈希函数。

字符串哈希函数:一串字符串里面的各个字符所对应的Unicode编码,进行∑(Ui*3L-i)。

开放定址法:H0 = H(key);Hi = ( H0+ di ) MOD L 第i次产生冲突则在哈希值的基础上加增量di ,如此重复直到Hs处无冲突。L为表长。增量序列:     {1,2,3,…,m-1} 线性探测再散列     {1的2,-1的2,2的2,-2的2,3的2,…,±k的2次方}二次探测再散列     伪随机数序列      伪随机探测再散列             线性探测再散列  ( H(key)+[1|2|3|…] )%L                                                                                        二次探测再散列  ( H(key)+[1的2|-1的2|2的2|-2的2|…] )%L

冲突处理方法

链地址法:冲突的记录构成一个链表,哈希表存其头指针

开放地址法

在散列表(Hash Table)中,负载因子α是当前元素数量与散列表大小的的比值。尽管增加散列表的大小可以减少冲突的可能性,但这并不意味着α>1时就不会发生碰撞。实际上,即使α>1,仍然可能存在碰撞。负载因子只是用来衡量散列表的装载程度,而不是用来避免碰撞的决定性因素。但是若装填因子α为1,则向散列表中散列元素时一定会产生冲突。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值