1、顺序查找
对于一个无序的,即关键字没有排序的线性表来说,用所给的关键字与线性表中的所有记录逐个进行比较,直到成功或者失败。
平均查找长度:ASL=(n+1)/2
I、最不频繁使用法(LFU):也叫作计数法,为线性表中的每条记录保存一个访问计数,并按照访问频率从高到低进行排序,而且一直按照这个顺序维护记录。这样,每当访问一条记录时,如果该记录的访问数已经大于它前面记录的访问数,这条记录就会在线性表中向前移动。很明显,这种方法为了保护访问计数需要占用空间,另外,该方法对记录访问频率随时间而改变的反应也不好。在频率计数中,一旦一条记录被访问了很多次,不管将来的访问次数怎样。它都一直位于线性表的前面。
II、最近最少使用法(LUR):也叫作移至前端法,如果找到一条记录就把他移至线性表的最前面,而把其他记录后退一个位置。显然,这种方式使用链表来存储比较好实现。同时,该方法对访问频率的局部变化反应很好,这是因为如果一条记录在一段时间内被频繁访问,在短时间它就会靠近线性表的前边。现在,搜狗拼音、紫光等输入法,使用的都是这种方法,把当前常用的字和词都移至前端,有效的提高了输入汉字的速度。
III、转置(transpose)方法:也叫作调换方法,把找到的记录与它表中的前一条记录交换位置。这种方法无论是基于链表存储还是数组存储,都是很好的方法。随着时间的推移,最常使用的记录将移动到线性表的前面。曾经被频繁访问但以后不会再使用的记录将会慢慢的落到后面。该方法在大部分情况下对访问频率的变化有很好的反应。但是,也会出现一些极端的情况。例如,首先访问线性表的最后一条记录I,然后就把这条记录与倒数第二条记录J交换位置,使得J称为最后一条记录。如果接下来访问的依然是最后一条记录J,那么就会和倒数第二条记录I交换位置。如果访问序列恰好就这样在I和J之间不断交替,将总是查找该表的最后位置,而这两条记录始终不能往前移动。不过,这种情况在实际情况中很少出现。
2、折半查找(二分查找)
对于任何一个线性表,若其中的所有数据元素都按照关键字的大小呈递减或递增排列,则称为有序表。
折半查找首先要求查找表满足:查找表采用顺序存储(数组)结构,并且按关键字大小有序排列。
基本查找过程:每次将待查范围中间位置上的数据元素的关键字与给定值K比较,如果相等就查找成功;否则利用该位置将整个表划分成前、后两个子表,如果中间位置记录的关键字大于待查关键字,则继续在前半部分子表进行查找,否则就在后半部分子表进行查找,重复此过程,直到“查找成功”或“查找不成功”。
折半查找是典型的分治类算法,所以算法也可以利用递归来实现。
平均查找长度:ASL=((n+1)/n)*log2(n+1)-1,当n>50时,ASL约等于log2(n+1)-1
折半查找的有点2在于关键字的比较次数比较少,查找速度快,平均性能较好,但缺点是要求待查表必须为有序表,而且要基于顺序结构存储,这对于插入和删除操作来说是比较困难的。因此,折半查找适合于一经建立就很少改动,而且有需要经常查找的有序查找表。
3、索引查找(分块查找)
如果线性表既希望有较快的查找速度,有需要动态变化,则可以采用索引查找。索引查找又称为分块查找,它是一种性能介于顺序查找和折半查找之间的查找办法。
基本思想:1、把线性表分成若干块,每块包含若干记录,在每一块中记录的存放是任意的,但块与块之间必须是有序的(分块有序)。2、建立一个索引表,把每块中的最大关键字值以及每块的第一个记录在表中的位置和最后一个记录在表中的位置存放在索引项中。所以,索引表是一个有序表。
查找时,首先用待查找的关键字在索引表中查找,确定具有该关键字的结点应该在哪一个分块中,在索引中查找的方法可以采用顺序查找或是折半查找,然后再到相应的分块中顺序查找,即可得到查找结果。
第一个阶段以折半查找ASL约为log2(n/i+1)+(i+1)/2;若第一阶段以顺序查找ASL=(n+i^2)/(2*i)+1
索引查找的优点在于在线性表中插入一个或删除一个结点时,只要找到该结点应属于的块,然后在块内进行插入或删除运算。由于块内结点的存放是任意的,因此插入或删除比较容易,不需要移动大量的结点。插入可直接在块尾进行;如果待删的记录不是块中最后一个记录时,可将本块内最后一个记录移入被删记录的位置。因此,在某些情况下索引查找是比较容易实现的。