只是我自己看书、视频的总结 可能不适合其他人看。
查找表:是由同一类型的数据元素(或记录)构成的集合。
关键字:是数据元素中某个数据项的值,也称为键值
查找,就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素或记录
静态查找表:只作查找操作的查找表。主要操作有:
- 查询某个“特定的”数据元素是否在查找表中。
- 检索某个“特定的”数据元素和各种属性。
动态查找表:在查找过程中同事插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素。 主要操作有:
- 查找时插入数据元素。
- 查找时删除数据元素。
顺序表查找
对线性表进行查找操作,就是静态查找
顺序查找:又叫线性查找。
过程:从表中第一个(或最后一个)记录开始,逐个进行记录的关键字和给定值比较,若某个记录的关键字和给定值相等,则成功。
代码:
/*顺序查找,a为数组,n为要查找的数组个数,key为要查找的关键字*/
int Sequenttial_Search (int *a,int n, int key)
{
int i;
for(i=1;i<=n;i++)
{
if (a[i]==key)
return i;
}
return 0;
}
有序表查找
折半查找
折半查找:二分法。前提是线性表中的记录必须是关键码有序(通常从小到大),线性表必须采用顺序存储。
代码:
/*二分法*/
int BInary_Search (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;
}
改进算法:
效果优于普通查找
斐波那契查找
利用黄金分割
下标 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|---|
F | 0 | 1 | 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 | … |
代码:
/*斐波那契查找*/
int Fibonacci_Search (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++) //计算n位于斐波那契数列的位置
a[i]=a[n];
while (low<=high)
{
mid = low+F[k-1]-1; //计算当前分隔的下标
if (key<a[mid]) //若查找记录小于当前分隔符记录
{
high = mid-1;
k=k-1; //斐波那契数列下标减一位
}
else if (key>a[mid]) //若查找记录大于当前分割记录
{
low = mid+1;
k = k-2;
}
else
{
if (mid<=n)
return mid;
else
return n; //若mid>n说明是补全数值,返回n
}
}
return 0;
}
线性索引查找
索引是把一个关键字与它对应的记录相关联的过程
分为稠密索引、分块索引和倒排索引
稠密索引
稠密索引是指在线性索引中,将数据集中的每个记录对应一个索引项。
对于稠密索引这个索引表来说,索引项一定是按照关键码有序的排列
分块索引
类似于图书馆的书架和书
分块索引:分块有序,是把数据集的记录分成了若干块,并且这些块需要满足下列两个条件:
- 块内无序
- 块间有序
倒排索引
索引项的通用结构是:
- 次关键码
- 记录号表
其中记录号表存储具有相同次关键字的所有记录的记录号。这样的索引方法就是倒排索引。
二叉排序树
二叉排序树,称为二叉查找树。它或者是一棵空树,或者是具有下列性质的二叉树
- 若他的左子树不为空,则左子树上所有结点的值均小于它根结构的值。
- 若它的右子树不为空,则右子树上所有结点的值均大于它根结构的值。
- 它的左、右子树也分别为二叉排序树。
代码:
/*二叉树的二叉链表结点定义*/
typedef struct BiTNode
{
int data;
struct BiYNode *lchild,*rchild;
}BiTNode, *BiTree;
//递归查找二叉排序树T中是否存在key
//指针f指向T的双亲,其初值调用值为NULL
//若查找成功,则指针p指向该元素结点,并返回TRUE
//否则指针p指向查找路径上访问的最后一个结点并返回FALSE
Status SearchBST (BiTree T, int key, BiTree f, BiTree *p)
{
if (!T)
{
*p = f;
return FALSE;
}
else if (key == T-> data) //查找成功
{
*p = T;
return TRUE;
}
else if (key < T -> data)
return SearchBST (T->lchild, key, T, p)
else
return SearchBST (T->rchild, key, T, p)
}
二叉排序树插入操作
代码:
//当二叉排序树T中不存在关键字等于kry的数据元素时
//插入key并返回TRUE,否则返回FALSE
Status 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; //插入s为新的根节点
else if (key<p->data)
p->lchild = s; //插入s为左孩子
else
p->rchild = s;
return TRUE;
}
else
return FALSE;
平衡二叉树
平衡二叉树(AVL)是一种二叉排序树,其中每一个结点的左子树和右子树的高度差至多等于1。
最小不平衡子树:距离插入点最近的,且平衡因子的绝对值大于1的结点为根的子树
实现原理
平衡二叉树构建的基本思想就是在构建二叉排序树的过程中,每当插入一个结点时,线检查是否因插入而破坏了树的平衡性,若是,则找出最小不平衡子树。在保持二叉排序树特性的前提下,调整最小不平衡子树中各结点之间的链接关系,进行相应的旋转,使之成为新的平衡树。