数据结构基础攻略——查找(Search)

1.基本概念

1)查找表(Search Table)是由同一类型的数据元素(或记录)构成的集合。关键字(Key)是数据元素中某个数据项的值。可以唯一地标识一个记录的关键字称为主关键字(Primary Key)。可以识别多个数据元素的关键字称为次关键字(Secondary Key)

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

3)静态查找表(Static SearchTable)是指只作查找操作的查找表;动态查找表(Dynamic Search Table)是指在查找过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素。

2.顺序查找(SequentialSearch)

在一个已知无序(或有序)查找表中找出与给定关键字相等的数据元素的具体位置。原理是让关键字按查找表中数据元素的顺序逐个比较,直到找出与给定关键字相等的数据元素或遍历所有的数据元素为止。算法的时间复杂度O(n)。

3.有序表查找(Ordered List Search)

1)二分查找(Binary Search)

假设有序表的数据元素data是按升序排列,则将该有序表的中间位置元素data[mid]与需要查找的关键字key比较:如果data[mid]=key,则表明搜索成功;如果data[mid]<key,则再在mid位置的右半子区间搜索;如果data[mid]>key,则再在mid位置的左半子区间搜索。不断重复data[mid]与key的比较,直到查找成功或者子区间不存在为止。算法的时间复杂度为O(log n)。

2)插值查找(InterpolationSearch)

我们知道二分查找的关键是中间位置的更新mid=low+(high-low)/2,而插值查找的关键是将二分查找中间位置计算公式中的系数1/2变为(key-data[low])/(data[high]-data[low]),即mid=low+(high-low)(key-data[low])/(data[high]-data[low])。算法的时间复杂度为O(log n)。

3)斐波那契查找(FibonacciSearch)

假设有序表的元素个数为n,若n不是斐波那契数,则对该有序表补充元素使其元素个数为一个斐波那契数fibonacci(k),中间位置mid的更新规则为mid=low+ fibonacci(k-1)-1,每次搜素时,mid的左半子区间的元素个数为fibonacci(k-1)-1,右半子区间的为fibonacci(k-2)-1,其他地方也是跟二分搜素一样。

4.二叉排序树(Binary Sort Tree)

又称二叉查找树。 它或者是一棵空树;或者是具有下列性质的二叉树a)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;b)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;c)左、右子树也分别为二叉排序树;

1)查找操作

若根结点的关键字值root等于查找的关键字key,则查找成功;否则,key<root,则递归查找根结点的左子树;若key<root,则递归查找根结点的右子树。若子树为空,则查找不成功。算法的时间复杂度为O(log n)。

2)插入操作

首先对需要插入的节点p(关键字为key)执行查找操作,若查找成功则不进行插入操作;否则,找出被插结点的父亲结点parents(即查找不成功时路径上访问的最后一个结点),若parents为空,则插入p为新的根结点;若key<parents.key,则插入到parents的左孩子中;若key>parents.key,则插入到parents的右孩子中。

3)删除操作

可分为三种情况讨论:

a)若需要删除的节点p是叶子结点,则直接删除p,并将其双亲结点parents与之所对应孩子的结点设为空;b)若p仅有左子树或右子树,则将其双亲结点parents与之对应孩子的结点设为p的左孩子(右孩子)即可;c)若p的左右子树非空,可按中序遍历保持有序进行调整,可以有两种做法:一是使p的左子树的最右下结点q代替p,并删除原来在p的左子树中的q;二是p的直接前驱(或直接后继)替代p,然后再从二叉排序树中删去它的直接前驱(或直接后继)。

5.平衡二叉树(AVL Tree)

它是一种二叉排序树,其中每一个结点的左子树和右子树的高度差至多等于1。二叉树上结点的左子树深度减去右子树深度的值称为平衡因子BF(Balance Factor)。距离插入结点最近的,且平衡因子的绝对值大于1的结点为根的子树,我们称为最小不平衡树。

1)AVL旋转

假设由于在二叉排序树上插入结点而失去平衡的最小子树根结点为p(即p是离插入点最近,且平衡因子绝对值超过1的祖先结点),则失去平衡后进行进行的规律可归纳为下列四种情况:

a)LL型右旋:由于在p的左子树根结点的左子树上插入结点,p的平衡因子p.BF由1增至2,p左孩子平衡因子p.lchild.BF由0增至1,即p.BF与p.lchild.BF同号为正,则需进行一次单向右旋即可完成平衡操作;

b)RR型左旋:由于在p的右子树根结点的右子树上插入结点,p的平衡因子p.BF由-1变为-2,p右孩子平衡因子p.rchild.BF由0增至-1,即p.BF与p.rchild.BF同号为负,则需进行一次单向右旋即可完成平衡操作;

c)LR型先左旋后右旋的双旋:由于在p的左子树根结点的右子树上插入结点,p的平衡因子p.BF由1增至2,p左孩子平衡因子p.lchild.BF由0增至-1,即p.BF与p.lchild.BF异号一正一负,则先对p.lchild左旋使得p.BF与p.lchild.BF同号,再对p右旋即可完成平衡操作;

d)RL型先右旋后左旋的双旋:由于在p的右子树根结点的左子树上插入结点,p的平衡因子p.BF由-1变为-2,p右孩子平衡因子p.rchild.BF由0增至1,即p.BF与p.rchild.BF异号一负一正,则先对p.rchild右旋使得p.BF与p.rchild.BF同号,再对p左旋即可完成平衡操作。

2)插入操作的递归算法

a)若当前递归查找到的结点BST为空树,则插入的新结点p作为BST的根结点,树的深度增1; b)若p的关键字key和BST的根结点的关键字BST.key相等,则不进行插入操作; c)若key<BST.key,且在BST的左子树中不存在等于key的结点,则将p插入在BST的左子树上,p.lchild深度增加(+1),并且计算p.BF,若其大于1,则判断其属于LL型右旋还是LR型双旋对其完成平衡操作,并更新平衡因子BST.BF;d)若key>BST.key,且在BST的右子树中不存在等于key的结点,则将p插入在BST的右子树上,p.rchild深度增加(+1),并且计算p.BF,若其小于-1,则判断其属于RR型左旋还是RL型双旋对其完成平衡操作,并更新平衡因子BST.BF。

6.多路查找树(Multi-way search tree)

它每一个结点的孩子数可以多于两个,且每一个结点处可以存储多个元素。

1)2-3树

它是一种多路查找树,其中的每一个结点都具有两个孩子(称为2结点)或三个孩子(称为3结点)。一个2结点包含一个元素和两个孩子(或者没有孩子);一个3结点包含一小一大两个元素和三个孩子(或者没有孩子);2-3树德所有叶子结点都必须在同一层次。

2)2-3-4树

它是对2-3树德一个扩展。其中的每一个结点都具有两个孩子、三个孩子或四个孩子。一个4结点包含小中大三个元素和四个孩子(或者没有孩子)。

3)B树(B-tree)

结点最大的孩子数目称为B树的阶。

一个m阶B树是具有以下结构特性的树:

a)根结点至少有两棵子树;

b)每一个非根的分值结点都有k-1个元素和k个孩子,元素k小于子树k+1中最小的元素,元素k大于子树k-1中最大的元素,其中[m/2]≤k≤m;

c)所有叶子结点都位于同一层次,且有k-1个元素,其中[m/2]≤k≤m;

4)B+树

出现在分支结点中的元素会被当做它们在该分支结点位置的中序后继者再次列出,所故有叶子结点包含全部关键字的信息,并且每一个叶子结点都保存一个指向后一叶子结点的指针,即所有叶子结点存储在按照关键字的升序排列的单链表。每个分支结点只包含其子树中的最大(或最小)关键字,故可以看作索引。

7.哈希表(HashTable)

散列技术是一种直接将关键字映射到其存储位置的存储技术(也是一种查找技术),使得每个关键字key对应一个存储位置f(key);映射关系f称为哈希(Hash)函数;采用这种技术存储数据的连续存储空间称为散列表或哈希表。当对不同的关键字得到同一散列地址时,即key1≠key2,而f(key1)=f(key2),这种现象称冲突(collision);key1、key2对该散列函数来说称做同义词(synonym)

1)哈希函数的构做方法

a)直接定址法:取关键字key的某个线性函数值作为哈希地址,即H(key) = a·key + b,其中a、b为常数;b)数字分析法:先对关键字的各位数字进行分析,抽取关键字的一部分来计算散列地址;c)平方取中法:取关键字平方后的中间几位作为散列地址;d)折叠法:将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后取这几部分的叠加和(去除进位)作为散列地址;e)除留余数法:取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址。即 H(key) = key mod p,其中,p<=m;f)随机数法:选择一随机函数,取关键字的随机值作为散列地址。

2)处理散列冲突的方法

a)开放定址法:一旦发生了冲突,就去寻找下一个空的散列地址;b)再散列函数法:同义词产生地址冲突时计算另一个散列函数地址,直到冲突不再发生,即Hi(key)=RHi(key),i=1,2,…,k,RHi是不同的散列函数;c)链地址法:将所有同义词的数据元素存储在一个单链表中;d)公共溢出区法:用于存放所有冲突的关键字。

3)影响查找效率的因素

包括:散列函数是否均匀、处理冲突的方法、散列表的装填因子α。其中,装填因子α=填入表中的元素个数 / 散列表的长度(哈希表的平均查找长度取决于装填因子,而不是取决于哈希表中的元素个数)。


原文转载出处:http://50vip.com/blog.php?i=163

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值