查找

        由于查找运算的使用频率很高,几乎在任何一个计算机系统软件和应用软件中都会涉及到,所以当问题所涉及的数据量相当大时,查找方法的效率就显得格外重要。在一些实时查询系统中尤其如此。

查找的基本概念
1、查找表和查找
     一般,假定被查找的对象是由一组结点组成的表(Table)或文件,而每个结点则由若干个数据项组成。并假设每个结点都有一个能惟一标识该结点的关键字。
     查找(Searching)的定义是:给定一个值K,在含有n个结点的表中找出关键字等于给定值K的结点。若找到,则查找成功,返回该结点的信息或该结点在表中的位置;否则查找失败,返回相关的指示信息。

2、查找表的数据结构表示
(1)动态查找表静态查找表
       若在查找的同时对表做修改操作(如插入和删除),则相应的表称之为动态查找表。否则称之为静态查找表。
(2)内查找和外查找
       和排序类似,查找也有内查找和外查找之分。若整个查找过程都在内存进行,则称之为内查找;反之,若查找过程中需要访问外存,则称之为外查找。

3、平均查找长度ASL

     查找运算的主要操作是关键字的比较,所以通常把查找过程中对关键字需要执行的 平均比较次数(也称为平均查找长度)作为衡量一个查找算法效率优劣的标准。


顺序查找(Sequential Search)
     在表的组织方式中,线性表是最简单的一种。顺序查找是一种最简单的查找方法。
1、顺序查找的基本思想:从表的一端开始,顺序扫描线性表,依次将扫描到的结点关键宇和给定值K相比较;
2、顺序查找的存储结构要求:
顺序表、链表都可以;

3、数据操作:

                         查找:O(n)


二分查找
1、二分查找(Binary Search)
 二分查找又称折半查找,它是一种效率较高的查找方法。
 二分查找要求:线性表是有序表,即表中结点按关键字有序,并且要用向量作为表的存储结构。不妨设有序表是递增有序的。
2、二分查找的基本思想 
  (1)首先确定该区间的中点位置:
  (2)然后将待查的K值与R[mid].key比较:若相等,则查找成功并返回此位置,否则须确定新的查找区间,继续二分查找;
     因此,从初始的查找区间R[1..n]开始,每经过一次与当前查找区间的中点位置上的结点关键字的比较,就可确定查找是否成功,不成功则当前的查找区间就缩小一半。

3、二分查找判定树:用来描述二分查找的过程。

4、算法复杂度:O(logN)

      二分查找失败时所需比较的关键字个数不超过判定树的深度,虽然二分查找效率较高,但是其要求是线性表是有序表。


     当用线性表作为表的组织形式时,以二分查找效率最高。但由于二分查找要求表中结点按关键字有序,且不能用链表作存储结构,因此,当表的插入或删除操作频繁时,为维护表的有序性,势必要移动表中很多结点。这种由移动结点引起的额外时间开销,就会抵消二分查找的优点。也就是说,二分查找只适用于静态查找表。若要对动态查找表进行高效率的查找,可采用下面介绍的几种特殊的二叉树或树作为表的组织形式。不妨将它们统称为树表。下面将分别讨论在这些树表上进行查找和修改操作的方法。

二叉排序树
1、二叉排序树的定义
  二叉排序树(Binary Sort Tree)又称二叉查找(搜索)树(Binary Search Tree)。其定义为:二叉排序树或者是空树,或者是满足如下性质的二叉树:
①若它的左子树非空,则左子树上所有结点的值均小于根结点的值;
②若它的右子树非空,则右子树上所有结点的值均大于根结点的值;
③左、右子树本身又各是一棵二叉排序树。
  上述性质简称二叉排序树性质(BST性质),故二叉排序树实际上是满足BST性质的二叉树。

2、数据操作:

          查找:最好情况:O(logN)      最坏情况:O(N)
          插入、删除:O(logN)


        虽然二叉排序树在查找、插入、删除上有了较好的性能,但是其最坏情况下,这些数据操作的时间均会增加到O(n),所以,需要“平衡”二叉排序树,使其避免最坏情况的发生。


平衡树

1、平衡二叉树又称AVL树。它或者是颗空树,或者是具有下列性质的二叉树:

它的左子树和右子树都是平衡二叉树,

左子树和右子树的深度之差的绝对值不超过1。

       若将二叉树节点的平衡因子BF定义为该节点的左子树的深度减去它的右子树的深度,则平衡二叉树上所有节点的平衡因子只可能为-1,0,1.只要二叉树上有一个节点的平衡因子的绝对值大于1,那么这颗平衡二叉树就失去了平衡。

2、数据操作:

     查找:O(logN)

     插入、删除: O(logN)

            结点的调整方法:

                         LL型(右旋)、RR型(左旋)

                         LR型(双旋:左旋、右旋)、RL型(双旋:右旋、左旋)


红黑树

红黑树并不追求“完全平衡”——它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能。

红黑树的5个性质:

每个结点要么是红的要么是黑的。

根结点是黑的。

如果一个结点是红的,那么它的两个儿子都是黑的。

对于任意结点而言,其到叶结点树尾端NIL指针的每条路径都包含相同数目的黑结点。

每个叶结点(叶结点即指树尾端NIL指针或NULL结点)都是黑的。

        正是红黑树的这5条性质,使一棵n个结点的红黑树始终保持了logn的高度,从而也就解释了上面所说的“红黑树的查找、插入、删除的时间复杂度最坏为O(log n)这一结论成立的原因。

散列表

        散列方法不同于顺序查找、二分查找、二叉排序树及AVL树、红黑树上的查找。它不以关键字的比较为基本操作,采用直接寻址技术。在理想情况下,无须任何比较就可以找到待查关键字,查找的期望时间为O(1)。

       根据设定的散列函数h(key)和处理冲突的方法将一组关键字key映像到一个有限的连续的地址区间上,并以关键字在地址区间中的像作为数据元素在表中的存储位置,这种表便被称为散列表,这一映像过程称为散列,所得存储位置称为散列地址。
       关键字、散列函数以及散列表的关系如下图所示:



1、散列函数
        散列函数是从关键字到地址区间的映像。
        好的散列函数能够使得关键字经过散列后得到一个随机的地址,以便使一组关键字的散列地址均匀地分布在整个地址区间中,从而减少冲突。
       常用的构造散列函数的方法有:
(1)、直接定址法

取关键字或关键字的某个线性函数值为散列地址,即:

h(key) = key 或 h(key) = a * key + b

其中a和b为常数。

(2)、数字分析法
(3)、平方取值法:取关键字平方后的中间几位为散列地址。
(4)、折叠法

将关键字分割成位数相同的几部分(最后一部分的位数可以不同),然后取这几部分的叠加和(舍去进位)作为散列地址。

(5)、除留余数法

取关键字被某个不大于散列表表长m的数p除后所得的余数为散列地址,即:

h(key) = key MOD p p ≤ m


(6)、随机数法

选择一个随机函数,取关键字的随机函数值为它的散列地址,即:

h(key) = random(key)

其中random为随机函数。


2、处理冲突
         对不同的关键字可能得到同一散列地址,即key1 ≠ key2,而h(key1)= h(key2),这种现象称为冲突。具有相同函数值的关键字对该散列函数来说称作同义词。
        在一般情况下,散列函数是一个压缩映像,这就不可避免地会产生冲突,因此,在创建散列表时不仅要设定一个好的散列函数,而且还要设定一种处理冲突的方法。
常用的处理冲突的方法有:
(1)、开放定址法

hi =(h(key) + di) MOD m i =1,2,…,k(k ≤ m-1)

其中,h(key)为散列函数,m为散列表表长,di为增量序列,可有下列三种取法:

1)、di = 1,2,3,…,m-1,称线性探测再散列;

2)、di = 12,-12,22,-22,32,…,±k2 (k ≤m/2),称二次探测再散列;

3)、di = 伪随机数序列,称伪随机探测再散列。

(2)、再散列法

hi = rhi(key) i = 1,2,…,k

rhi均是不同的散列函数。

(3)、拉链法

将所有关键字为同义词的数据元素存储在同一线性链表中。假设某散列函数产生的散列地址在区间[0,m-1]上,则设立一个指针型向量void *vec[m],其每个分量的初始状态都是空指针。凡散列地址为i的数据元素都插入到头指针为vec[i]的链表中。在链表中的插入位置可以在表头或表尾,也可以在表的中间,以保持同义词在同一线性链表中按关键字有序排列。

3、散列表上的运算
     散列表上的运算有查找、插入和删除。其中主要是查找,这是因为散列表的目的主要是用于快速查找,且插入和删除均要用到查找操作。

        插入和删除的时间均取决于查找,故只需要分析查找操作的时间性能。
     虽然散列表在关键字和存储位置之间建立了对应关系,理想情况是无须关键字的比较就可找到待查关键字。但是由于冲突的存在,散列表的查找过程仍是一个和关键字比较的过程,不过散列表的平均查找长度比顺序查找、二分查找等完全依赖于关键字比较的查找要小得多。




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值