数据结构知识点系列三:查找
1、顺序表查找
平均查找长度为: n+12
查找方式:从表中第一个或最后一个元素开始,逐个进行比较,直到找到关键字或查找结束。
2、有序表查找
二分查找:在有序表中,取中间元素作为比较对象,若相等,则查找成功;若给定值小于中间元素,则在中间元素的左半区查找;否则在右半区查找。 mid=low+high−low2
插值查找:与二分查找类似, mid=low+key−a[low]a[high]−a[low]∗(high−low)
斐波那契查找: mid=low+F[k−1]−1 ,k的初始值为n,注意用a[n]补全n~F[k]-1之间的空位。
//二分查找
int BinarySearch(int* a,int n,int key){
int low,high,mid;
low = 1;high = n;
while (low<=high){
mid = (low+high)/2;
if (key<a[mid]) high = mid-1;
else if (key>a[mid]) low = mid+1;
else return mid;
}
return 0;
}
//斐波那契查找
int FibonacciSearch(int* a,int n,int key){
int low,high,mid,i,k;
low = 1;high = n;k = 0;
while (n>F[k]-1) k++;
for (i=n;i<F[k]-1;i++) a[i] = a[n];
while (low<=high){
mid = low+F[k-1]-1;
if (key<a[mid]) {high = mid-1;k--;}
else if (key>a[mid]) {low = mid+1;k=k-2;}
else{
if (mid<=n) return mid;
else return n;
}
}
return 0;
}
3、线性索引查找
索引:把一个关键字与它对应的元素相关联的过程。
线性索引:将索引项集合组织为线性结构。
1. 稠密索引:每个数据元素对应一个索引项,索引项按照关键码有序的排列。
2. 分块索引:块内无序,块间有序。索引项的结构是最大关键码、块长和块首指针。查找:先查找关键字所在的块,再在块内用顺序查找方法。
3. 倒排索引:索引项的结构是次关键字码和记录号表,其中记录号表存储具有相同关键字的所有记录的记录号。
4、二叉排序树(二叉查找树)
定义:空树或者满足以下性质的二叉树:若左子树不为空,左子树上所有结点的值小于根结点的值;若右子树不为空,右子树上所有结点的值大于根结点的值;左右子树均为二叉排序树。
//定义
typedef struct BiTNode
{
int data;
struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;
//查找
int SearchBST(BiTree* T,int key,BiTree* f,BiTree* p){
if (T==NULL){
p = f;
return -1;
}
else if (T->data==key) return T;
else if (T->data>key)
SearchBST(T->lchild,key,T,p);
else SearchBST(T->rchild,key,T,p);
}
//插入
int InsertBST(BiTree *T, int key)
{
BiTree p,s;
if (!SearchBST(*T, key, NULL, &p))
{
s = (BiTree)malloc(sizeof(BiTNode));
s->data = key;
s->lchild = s->rchild = NULL;
if (!p)
*T = s;
else if (key<p->data)
p->lchild = s;
else
p->rchild = s;
return 1;
}
else
return 0;
}
//删除
int DeleteBST(BiTree* T,int key){
if (!*T) return 0;
else{
if (key==(*T)->data)
return Delete(T);
else if (key<(*T)->data)
return DeleteBST(&(*T)->lchild,key);
else
return DeleteBST(&(*T)->rchild,key);
}
}
int Delete(BiTree *p)
{
BiTree q,s;
if((*p)->rchild==NULL)
{
q=*p; *p=(*p)->lchild; free(q);
}
else if((*p)->lchild==NULL)
{
q=*p; *p=(*p)->rchild; free(q);
}
else
{
q=*p; s=(*p)->lchild;
while(s->rchild)
{
q=s;
s=s->rchild;
}
(*p)->data=s->data;
if(q!=*p)
q->rchild=s->lchild;
else
q->lchild=s->lchild;
free(s);
}
return 1;
}
5、散列表查找(哈希表查找)
存储位置=f(关键字),f为散列函数。
冲突: f(key1)=f(key2),key1≠key2
1. 构造散列函数
直接定址法: f(key)=a∗key+b ,需要实现知道关键字的分布情况,适合查找表较小且连续的情况。
数字分析法:抽取关键字的一部分数字映射为散列位置。适合关键字较长,若干位分布均匀的情况。
平方取中法:取关键字平方的中间几位数为散列位置。
折叠法:关键字分为几部分,进行求和再取后几位作为散列位置。
除留余数法: f(key)=keymodp,p≤m ,p通常取小于m的最小质数。
随机数法: f(key)=random(key)
2. 处理散列冲突的方法
开放定址法: f(key)=(f(key)+di)Modm ,一旦发生冲突,去寻找下一个空散列位置。 di=1,2,⋯,m 称为线性探测法; di=1,−1,22,−22⋯,q2,−q2 成为二次探测法; di 为随机数,称为随即探测法。
再散列函数法
链地址法:将所有关键字为同义词的记录放在单链表中,散列表存储链表头指针。
公共溢出法:将所有冲突的关键字存放在公共溢出区。
散列表的装填因子: α=填入表中的记录数散列表长度 ,越大越易冲突。
6、平衡二叉树AVL、多路查找树B树简单介绍
1. 平衡二叉树:二叉排序树,每个结点的左子树和右子树的高度差小于等于1。平衡因子BF:二叉树上结点的左子树深度减去右子树深度的值。
2. 多路查找树:每个结点的孩子可以多于两个且每个结点处可以存储多个元素。2-3树:每个结点具有两个孩子或三个孩子。B-树:平衡的多路查找树,结点的孩子数目最大值称为B树的阶。