经典查找算法

查找 —— 在数据集合中寻找满足某种条件的数据元素的过程

查找表(查找结构)—— 用于查找的数据集合称为查找表,它由同一类型的数据元素组成

关键字 —— 数据元素中唯一标识该元素的某个数据项的值,使用基于关键字的查找,查找结果应该是唯一的。

评价指标:

查找长度 —— 在查找运算中,需要对比关键字的次数

平均查找长度 —— 所有查找过程中进行关键字的比较次数的平均值

顺序查找

算法思想:从头到尾挨个找,适用于顺序表、链表。

A S L 查找成功 = n + 1 2 ASL_{查找成功} = \frac{n+1}{2} ASL查找成功=2n+1 A S L 查找失败 = n + 1 ASL_{查找失败} = n+1 ASL查找失败=n+1

顺序查找的优化(对有序表):查找表中元素有序存放

A S L 查找失败 = n 2 + n n + 1 ASL_{查找失败} = \frac{n}{2}+\frac{n}{n+1} ASL查找失败=2n+n+1n

用查找判定树分析ASL:

一个成功结点的查找长度 = 自身所在层数

一个失败结点的查找长度 = 其父节点所在层数

折半查找

算法思想:二分查找,只适用于有序的顺序表
算法实现:

#include <iostream>
#include <vector>

using namespace std;

int BinarySearch(vector<int>& L, int key) {
	int low = 0, high = L.size() - 1, mid;
	while (low <= high) {
		mid = (low + high) / 2;
		if (L[mid] < key) low = mid + 1;
		else if (L[mid] > key) high = mid - 1;
		else return mid;
	}
	return -1;
}

int main()
{
	vector<int> num = { 1, 2, 4, 6, 7, 9, 10 };

	int loc = BinarySearch(num, 7);

	cout << loc << endl;

	return 0;
}

查找效率分析

分块查找

分块查找,又称索引顺序查找,算法过程如下:

  1. 索引表中确定待查记录所属的分块(可顺序,可折半)
  2. 在块内顺序查找

索引表中保存每个分块的最大关键字和分块的存储空间。

//索引表
typedef struct {
		int maxValue;
		int low, high;
}Index;

// 顺序表存储实际元素
int Lsit[100];

用折半查找查索引,若索引表中不包含目标关键字,则折半查找索引表最终停在 l o w > h i g h low > high low>high,最终要在low所指分块中查找

查找效率分析:n个记录,均匀分为b块,每块s个记录

  1. 若索引表采用顺序查找, A S L = b + 1 2 + s + 1 2 ASL = \frac{b+1}{2} + \frac{s+1}{2} ASL=2b+1+2s+1
  2. 若索引表采用折半查找

若查找表是动态查找表,有没有更好的实现方式?链式存储

B树

//5叉排序树的结点定义
struct Node {
	int keys[4]; //最多四个关键字
	struct Node* child[5]; //最多五个孩子
	int num; //结点中几个关键字
};

如何保证查找效率?

  1. m叉树中,规定除了根节点外,任何结点至少[m/2]个分叉,即至少含有[m/2] - 1个关键字
  2. m叉查找树中,规定对于任何一个结点,其所有子树的高度都要相同

B树,又称多路平衡查找树,B树中所有结点的孩子个数的最大值称为B树的阶,通常用m表示。一棵m阶B树或为空树,或为满足如下特性的m叉树:

(1)树中每个结点至多有m棵子树,即至多含有m-1个关键字。

(2)若根结点不是终端结点,则至少有两棵子树。

(3)除根节点外的所有非叶结点至少有[m/2]棵子树,即至少含有[m/2] - 1个关键字。

(4)所有非叶子结点的结构如下:

n P 0 P_0 P0 K 1 K_1 K1 P 1 P_1 P1 K 2 K_2 K2 P 2 P_2 P2 K n K_n Kn P n P_n Pn

其中, K i ( i = 1 , 2 , . . . , n ) K_i(i = 1,2,...,n) Kii=12...n结点关键字,且满足 K 1 < K 2 < . . . < K n K_1 < K_2 < ... < K_n K1<K2<...<Kn P i ( i = 0 , 1 , . . . , n ) P_i ( i = 0, 1, ... , n) Pi(i=0,1,...,n)指向子树根节点的指针,且指针 P i − 1 P_{i - 1} Pi1所指子树中所有结点的关键字均小于 K i K_i Ki P i P_i Pi所指子树中所有结点的关键字均大于 K i K_i Ki n为结点中关键字的个数。( [ m / 2 ] − 1 ≤ n ≤ m − 1 [m/2] - 1 \leq n \leq m-1 [m/2]1nm1

(5)所有的叶子结点都出现在同一层次上,并且不带信息(可以视为外部结点或类似于折半查找判定树的查找失败结点,实际上这些结点不存在,指定这些结点的指针为空)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值