您的位置:首页 > 理论基础 > 数据结构算法

数据结构9-查找

2016-03-23 17:00 260 查看

9.查找

9.1 简介

查找是在一组数据中查找需要检索的数据,并输出他的位置。

查找按照数据量的大小分为内部查找和外部查找:

内部查找:数据量较小,可以直接载入内存进行查找;

外部查找:数据量较大的文件,无法一次载入内存处理,需要辅助存储器来分次处理。

根据在查找过程中查找的数据是否变动将查找区分为静态查找和动态查找:

静态查找:查找过程中,查找数据不会增加、删除或者更新等行为;

动态查找:查找过程中会经常性的增加、删除或更新。

9.2 常见的查找方法

常用的方法有:顺序查找、二分查找法、斐波那契法、插值查找法、哈希法等。

9.2.1 顺序查找法

顺序查找法又称为线性查找法,是一种简单的查找法。

他的思路是将数据按照顺序依次查找,不管数据顺序如何都要从头到尾遍历一次。

优点:文件在查找前不需要进行任何处理与排序;

缺点:查找速度慢。

特性:

1)时间复杂度,最差情况是未找到数据,但是比较了n次,时间复杂度为O(n);

2)在平均情况下,假设数据出现概率相等,需要(n+1)/2次查找;

3)数据量很大时候,不适合采用顺序查找法。

9.2.2 二分查找法

又称为“折半查找”法。如果查找的数据实现已经排好序则可以采用二分查找法来进行操作。

主要思路:

1)将从小到大排序好的数据取中间值与待查询数据做对比,如果相同则查询到;

2)如果小于中间值,则取左半部分继续折半,进行中间值的对比;

3)如果大于中间值,则取右半部份继续折半,进行中间值的对比;

4)重复二/三步骤。

9.2.3 插入查找法

又称为查补查找法,是二分法的改进版本。他是按照数据位置的分布预测数据所在位置,再以二分法的方式渐渐逼近。

插值公式如下:Mid=low+((key-data[low])/(data[high]-data[low]))x(high-low)

其中key是要寻找的键,data[high]、data[low]是待查纪录的最大值和最小值,数据个数为n。

步骤如下:

1)将记录按照从小到大顺序给予1,2,3.。。。n的编号;

2)令low=1,high=n;

3)当low<high时候,重复4,5步骤;

4)令Mid=low+((key-data[low])/(data[high]-data[low]))x(high-low);

5)若key<key
mid且low不等于Mid-1,则令high=Mid-1;

6)若key=key
mid,则表示查找成功;

7)若key>key
mid且low不等于Mid+1,则令low=Mid+1.

特性:

1)一般而言,插值法优于顺序查找法,而且数据分布越平均,则查找速度越快,甚至可能一次就找到数据。此法的时间复杂度取决于数据分布情况,平均而言优于O(log2
n);

2)使用插值查找法时数据需要先经过排序。

9.2.4 斐波那契查找法

斐波那契查找法和二分查找发一样都是以切割查找范围的方式来进行查找,不同的是费氏查找法并不是以对半方式进行切割,而是以费氏级数方式进行查找。

费氏级数定义:

1)fib(0)=0;

2)fib(1)=1;

3)fib(i)=fib(i-1)+fib(i-2),i>=2.

也就是说费氏级数:0,1,1,2,3,5,8,13,21,34,55,89.........................

具体建立步骤为:

1)费氏树的左右均为费氏树;

2)当数据个数n给定时候,需要知道费氏树的高度k,找到最小的k,使得费氏级数的Fib(k+1)>=n+1;如果n+1的值不是费氏数值,可以找到一个m,m=fib(k+1)-(n+1),然后按照费氏树原则建立费氏树,最后费氏树每个结点减去差值m即可;

3)费氏树的树根一定是费氏数,并且子结点与父结点的绝对值之差为费氏数;

4)当k>=2时,费氏树的树根为fib(k),左子树为k-1阶费氏树(树根为fib(k-1)),右子树为k-2阶费氏树,树根为fib(k)+fib(k-2);

特性:

1)平均而言,费氏查找法的比较次数会少于二叉查找法,但是最坏情况下则是二叉查找法较快。平均时间复杂度为O(log2
n);

2)费氏查找法较为复杂,需要额外产生费氏数。

9.2.5 哈希查找法

哈希法又称为散列法,哈希法不仅用于数据的查找,在数据结构的领域中还能将他的英勇在数据的建立、插入、删除与更新中。哈希表是静态表的一种,将相关的数据和键值存储在一个固定大小的表格中。所谓哈希法就是将本身的键值经过特定的数学函数运算或使用其他方法转换成相对应的数据存储地址。而哈希法所使用的数学函数就称为“哈希函数”。

专有名词:

1)桶(Bucket)哈希表中存储数据的位置,每一个位置对应唯一的地址;

2)冲突(Collision)若两个不同的数据经过哈希函数运算后对应到相同的地址,就称为冲突;

3)溢出如果数据经过哈希函数运算后,所对应的桶已满,就会发生溢出;

4)哈希表哈希表是一种类似于数据表的索引表格,其中可分为n个桶,每个桶又可以分为m个域。

设计哈希表四个原则:

1)降低冲突和溢出的产生;

2)哈希函数不宜过于复杂,越容易计算越佳;

3)尽量把文字的键值转换成数字键值,从而利于哈希函数计算;

4)所设计的哈希函数计算而得到值,尽量能均匀分布在每一桶中,不要集中在某些桶内,这样可以降低冲突,减少溢出发生。

常见的哈希函数:除留余数法、中间平方法、折叠法、数字分析法

除留余数法:

最简单的哈希函数是将数据除以某一个常数取余数来当作索引。比如有一个13位置的数组只使用7个地址。这些值为:12、65、70、99、33、67、48把这些数除以13,取余数来当作索引。利用公式:h(key)=key
mod B一般而言B最好是质数!

中间平方法:

思路:将数据平方,然后取中间某段数字来作为索引。如果数据量较小,而去两位就会有0——99个空间,此时需要压缩。可以取中间某两个字段然后除以十,取整数,作为索引。

折叠法:

思路:将数据分段,然后分别相加起来作为索引。如数字:23456789分段为234
567 89,将这三个数字相加起来作为索引值。有时候为了降低冲突,可以选择将其中奇数位(234 89)反转(432 98).或者偶数位反转,得到的数值作为索引。这种改良算法称为“边界折叠法”。

数字分析法:

思路:取数据集中某一段作为索引,如后三位。。。。

冲突问题的解决:线性探测法、平方探测法、再哈希法、拉链法

线性探测法:

当发生冲突时候,若索引有数据,则以线性方式向右寻找空的存储位置,找到位置就放进去。有时候可以把哈希位置视为环状结构,如此一来后面位置被填满可以放到数据前面。

平方探测法:

当发生溢出,则下一次查找地址为(f(x)+i^2)mod
B与(f(x)-i^2)mod B.

再哈希法:

就是指定多种那个哈希函数,得到多种索引列表,当第一种溢出,采用第二种,。。。以此类推!

拉链法:

将哈希表所有空间建立n个链表,最初的默认值只有n个表头。如果溢出就把相同的地址键值链接到表头后面,形成一个链表,直到所有可用空间全部用完为止。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: