1.基本概念:
1.1 静态查找和动态查找
- 静态查找:数据集合稳定,不需要添加,删除元素的查找操作。
- 动态查找:数据集合在查找的过程中需要同时添加或删除元素的查找操作。
1.2 查找结构
- 对于静态查找来说,可以用线性表结构,这样可以使用顺序查找算法,如果再对关键字进行排序,则可以使用折半查找算法来提高查找效率。
- 对于动态查找来说,可以使用二叉排序树,也可以使用散列表结构来解决一些查找问题。
1.3 (主)关键字
数据元素(或记录)中某个数据项的值,可以唯一地标识一个记录。
1.4 平均查找长度(ASL)
主要是理解定义,需要注意的是,查找成功和查找失败的ASL一般是不相同的。
2.顺序查找:
int Sq_Search(int *a, int n, int key) { int i; for( i=1; i <= n; i++ ) { if( a[i] == key ) { return i; } } return 0; }
上面这段代码的复杂度是 O(2n) ,适当地取巧(设置哨兵),其实可以获得下面这一种O(n)的代码。
int Sq_Search(int *a, int n, int key){ int i = n; a[0] = key while( a[i] != key ) { i--; } return i; }
3. 折半查找
如果数据记录的关键字是有序排列的,则可以用折半(二分)查找法,这样一种效率比较高的查找方法(时间复杂度O(log2(n)))
int Bin_Search( int str[], int n, int key ){//迭代二分 int low, high, mid; low = 0; high = n - 1; while( low <= high ) { mid = (low + high) / 2; if( str[mid] == key ) { return mid; } if( str[mid] < key ) { low = mid + 1; } if( str[mid] > key ) { high = mid - 1; } } return -1; }
int Bin_Search(SSTable ST, KeyType key, int low, int high) {//递归二分 if(low <= high){ mid = (low + high) / 2; if(key == ST.R[mid].key) { return mid; } else if(key < ST.R[mid].key) { return Bin_Search(ST,key, low, mid - 1); } else { return Bin_Search(ST.key, mid + 1, high); } } return 0; }
基于二分的查找效率虽然高,但对数据组织的结构要求比较苛刻,如果是处理数据量小的问题,应该尽量使用顺序查找。
4.分块查找
索引存储结构:索引存储结构 = 主数据表 + 索引表
数据整体是无序,但是分块后按块是有序的。
在索引表(有序)中按关键字查找:可以 顺序查找 或 二分查找。在对应的数据块(无序)中查找:只能顺序查找块中元素。
算法的时间复杂度:折半查找确定块,顺序查找确定块中元素,ASL是俩次查找平均查找长度之和。
5.树表的查找
以二叉树或其他树作为查找表的形式,称为树表。树表多采用链式存储结构,本质上是动态查找表。书上介绍了以下四类,感觉自己对这一部分的理解还不到位,不能很好地进行总结。希望接下来能花时间回过头看多几遍。
- 二叉排序树
- 平衡二叉树
- B树
- B+树
6.哈希(散列)表的查找:
6.1.哈希表的基本概念
散列表(Hash table,也叫哈希表),是根据键(Key)而 直接 访问在内存存储位置的数据结构。它通过计算一个关于键值的函数,将所需查询的数据映射到表中一个位置来访问记录,这加快了查找速度。
映射函数称做散列函数(哈希函数),存放记录的数组称做散列表(哈希表)。
散列函数的规则是:通过某种转换关系,使关键字适度的分散到指定大小的的顺序结构中,越分散,则以后查找的时间复杂度越小,空间复杂度越高。因此,哈希函数是用空间换取时间效率的算法。
6.2.哈希函数构造方法
直接定址法(h(k) = k + c)
除留余数法(h(k)=k mod p)
数字分析法
6.3.哈希冲突的解决方法
哈希冲突是指哈希函数算出来的地址被别的元素占用了。
①开放地址法
冲突时找一个新的空闲的哈希地址。那么,如何找空闲单元呢?
- 线性探测法(d0 = h(k),di = (di - 1 + 1) mod m (1 ≤ i ≤ m -1))
- 平方探测法(d0 = h(k),di=(d0 ± i^2) mod m (1≤ i ≤m - 1))
与线性探测相比,平方探测法能更好地避免出现堆积现象(即减少二次聚集的情况)。但它的缺点是不能探测到哈希表上的所有单元(至少能探测到一半单元)。
②拉链法
拉链法是把所有的同义词用单链表链接起来的方法。(是更为常见的哈希结构)