(0)测试代码:
int arr[] = {0, 2, 4, 6, 8, 10, 12, 14}; int idx[] = { Search(arr, 8, -15), //-1 Search(arr, 8, 0), //0 Search(arr, 8, 5), //-1 Search(arr, 8, 6), //3 Search(arr, 8, 14), //7 Search(arr, 8, 15), //-1 };
(1)顺序查找:最原始最通用
template<typename TYPE> int SequentialSearch(TYPE arr[], int num, TYPE key) { int found = -1, idx; for (idx = 0; idx < num; ++idx) { if (arr[idx] == key) { found = idx; break; } } return found; }
(2)二分查找(折半查找):
据说,只有10%的程序员能完全正确地实现二分查找算法!
优点是,比较次数少,查找速度快;缺点是,要求待查表为有序表,导致插入和删除困难。
适用于,不经常变动,但经常查找的有序表。算法复杂度为 log2(n)
template<typename TYPE> int BinarySearch(TYPE arr[], int num, TYPE key) //假设已为升序 { if (num <= 0) return -1; int found = -1; int low = 0, high = num - 1, idx; while (low <= high) //注意此处:等于也可,否则两端元素找不到 { idx = (low + high) / 2; if (arr[idx] == key) //找到 { found = idx; break; } else if (arr[idx] > key) //当前值偏大 { high = idx - 1; } else //arr[idx] < key //当前值偏小 { low = idx + 1; } } return found; }
(3)二叉树查找:
NODE *BinarySortTreeSearch(NODE *node, int key) { NODE *found = NULL; while (node) { if (node->key == key) { found = node; break; } else if (node->key < key) { node = node->right; } else //node->key > key { node = node->left; } } return found; }
(4)分块查找(索引查找):
是顺序查找的改进。不常用,知道流程即可。
(a)将 arr[n] 划分为 m 块(m <= n),每块内结点不必有序,但块与块间必须有序(前块中任意元素必须小于后块中任意元素);
(b)选取各块中首结点索引、块内最大关键字,构成一个索引表;
(c)二分查找,确定待查记录在哪一块中;
(d)在该块中顺序查找指定的元素。
(5)哈希表查找:
使用一个下标范围比较大的数组来存储元素。
设计一个哈希函数(散列函数),使得 hash(key) = idx,该函数的设计是关键。
哈希冲突是指不同的 key 却生成了相同的 hash(key),导致多个元素要存储在同一位置。
(a)除余法(最常用):选择一个适当较大的正整素数p, h(k) = k % p
(b)数字选择法:选择关键字中数字分布比较均匀的若干位,所组成的新值作为哈希值。
哈希查找虽然看上去有些离谱,但它非常实用,压缩程序、磁盘高速缓存程序都使用它。