查找算法
(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)数字选择法:选择关键字中数字分布比较均匀的若干位,所组成的新值作为哈希值。
哈希查找虽然看上去有些离谱,但它非常实用,压缩程序、磁盘高速缓存程序都使用它。

浙公网安备 33010602011771号