概念:
(1)查找表:是由同一类型的数据元素构成的集合,元素间关系松散,应用灵活;可分为静态查找表(仅查询)和动态查找表(需进行插入和删除操作)
(2)关键字:用来标识某个数据元素的某个数据项的值,分为主关键字(唯一标识一个数据项)和次关键字(标识了多个数据项)
(3)平均查找长度ASL:关键字的平均比较次数


查找方式:
顺序查找:
应用范围:
(1)顺序表或线性表表示的静态查找表
(2)表内元素无序
代码展示:
typedef int KeyType;
typedef struct
{
KeyType key;
}ElemType;
typedef struct
{
ElemType* R;
int length;
}SSTable;
int SearchSeq(SSTable ST, KeyType key)
{
int i;
for (i = ST.length; i >= 1; i--)
if (ST.R[i].key == key)
return i;
return 0;
}
运行:

改进(监视哨):
int SearchSeq(SSTable ST, KeyType key)
{
int i;
ST.R[0].key = key;/*监视哨*/
for (i = ST.length; ST.R[i].key != key; i--);
return i;
}
优点:算法简单,不同存储结构均适用
缺点:时间效率低
折半查找:
代码展示:
int SearchBin(SSTable ST, KeyType key)
{
int low = 1, high=ST.length,mid;
while (low <= high)
{
mid = (low + high) / 2;
if (ST.R[mid].key == key) return mid;
else if (key < ST.R[mid].key) high = mid - 1;
else low = mid + 1;
}
return 0;
}
运行:

文本输出:


代码:
int main()
{
ofstream output("output",ios::out);
SSTable ST;
string s;
int key;
int a,b,i;
ST.R = new ElemType[MAXSIZE];
cout << "请输入存储数据需要的空间大小" << endl;
cin >> ST.length;
cout << "请输入需要存储的数据" << endl;
for (i = 0; i < ST.length; i++)
cin >> ST.R[i].key;
cout << "请输入需要查找的数据" << endl;
cin >> key;
a=SearchSeq(ST, key)+1;
b = SearchBin(ST, key) + 1;
if (a == 0)output << "无此数据" << endl;
else if (a > 0)output << "该数据在第" << a << "个位置上(顺序查找)" << endl;
else output << "发生错误" << endl;
if (a == 0)output << "无此数据" << endl;
else if (a > 0)output << "该数据在第" << b << "个位置上(折半查找)" << endl;
else output << "发生错误" << endl;
cout << "成功" << endl;
return 0;
}
改进:
int SearchBin(SSTable ST,KeyType key, int low,int high)
{
int mid = (low + high) / 2;;
if (low > high)return 0;
if (key = ST.R[mid].key)return mid;
else if (key < ST.R[mid].key)
SearchBin(ST,key,low, mid - 1);
else
SearchBin(ST, key,low+1,high);
return 0;
}
优点:效率比顺序查找高
缺点:只适用于顺序存储的有序表,不适用于线性链表
分块查找:
即索引顺序表查找
适用范围:
要快速查找又要经常动态变化
操作过程:
(1)将表分成几块,且表有序,或者分块有序
(2)建立索引表

优点:插入和删除容易,无需大量移动数据
缺点:要增加一个索引表空间
比较:

树表的查找:
表结构在查找过程中动态生成
类别:
二叉排序树,平衡二叉树,红黑树,B-树,B+树,键树
二叉排序树:
定义:

用中序遍历非空二叉排序树得到的数据元素序列是递增有序的
实现原理:

查找过程:

代码实现:
typedef int KeyType;
typedef int InfoType;
typedef struct/*定义数据的类型*/
{
KeyType key;
InfoType otherinfo;
}ElemType;
typedef struct BSTNode/*定义二叉排序树*/
{
ElemType data;
struct BSTNode* lchild, * rchild;
}BSTNode,*BSTree;
BSTree SearchBST(BSTree T, KeyType key)/*二叉排序树查找*/
{
if (!T || key == T->data.key)return T;
else if (key < T->data.key)return SearchBST(T->lchild, key);
else return SearchBST(T->rchild, key);
}
插入操作:
若二叉排序树为空,则插入结点作为根结点

删除操作:
原理:

过程:
(1)被删除结点是叶子结点:直接删去该结点
(2)被删除结点只有左子树或右子树:用其左子树或右子树替换它
(3)被删除结点既有左子树,还有右子树:

在左子树上找到最大结点,以它作为根结点

并在左子树中将其删除

平衡二叉树(AVL):
定义:

给每个结点一个平衡因子,表示其左右子树的高度差,只能为-1,0,1
失衡二叉树调整方法:
(1)降低高度
(2)保证二叉排序树性质
散列表:
记录存储位置于关键字之间的关系,对应关系称为hash函数
查找:根据散列函数H(key)=k
优点:查找效率高
缺点:空间效率低
散列方法:

构造散列函数的考虑因素:

构造方法:
(1)直接定址法:
优点:以key的某个线性函数值为散列地址,不会产生冲突
缺点:要占用连续地址空间,空间效率低
(2)除留余数法:

处理冲突的方法:
(1)开放定址法
线性探测法:
有冲突时按照增量序列
1,2,3,...,n
寻找下一个空的散列地址,并存入数据元素
二次探测法:
有冲突时按照增量序列
将数据存入下一个空的散列地址


伪随机探测法:

(2)链地址法:
基本思想:将相同散列地址的数据连接成一个单链表
举例:

优点:不会冲突;结点空间动态申请,更适合于表长不确定的情况
编码问题总结:
(1)调用函数中参数过多
原因:函数参数名与宏函数名相同
改正方法:引入一个新变量作为中间变量来传递数据
(2)从文件中输入和输出数据
需添加一个#include<fstream>头文件
用ifstream来读取文件,用ofstream来输出数据存入文件
总结:
查找方法多种多样,我们应根据数据的存储类型和数据量大小来选择适合的方法,以提高效率,减少查找的时间,可在查找时记录下每个数据查找的频率,根据频率大小实时调整数据存储位置,提高效率