查找算法

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

原文地址:https://www.cnblogs.com/javawebsoa/p/3113104.html