查找的定义:给定一个值K,在含有n个记录的表中找出关键字等于K的记录
采用何种方法进行查找的相关因素如下:
1、使用何种数据结构来表示查找表,即查找表中记录按照何种方式组织
2、查找表中关键字的次序,即对无序集合还是有序集合查找
查找过程中对关键的平均比较次数,也称为平均查找长度,作为衡量查找算法优劣的标准
n代表查找表中记录的个数,pi是查找到第i个记录的概率,
ci是找到第i个记录所需要进行的比较次数
——————————————————————————————————————
顺序查找法,即从一端开始,顺序扫描
ASL分为查找成功和失败的情况,成功时ASL=(n+1)/2,失败时ASL=n
对于顺序查找法,无论查找成功还是失败
折半查找法要求线性表是有序的
代码如下:
int Bsearch(int R[],int low, int high,int k)
{
int mid;
while(low<=high)
{
mid=(low<=high)/2;
if(R[mid]==k)
{
return mid;
}
else if(R[mid]>k){
high=mid-1;
}
else{
low=mid+1;
}
return 0;
}
}
折半查找时间复杂度为log2 n
例题:对于含有13个关键字的有序表(0~12)
查找成功概率和查找不成功概率分别为ASL1和ASL2,画出的判定树如下
分块查找
分块查找把线性表分成若干块,块中元素存储顺序任意,但是块之间必须按照关键字大小有序排列
即前一块中的最大关键字要小于后一块中的最小关键字
对顺序表进行分块查找需要额外建立一个索引表,每个索引项有块中最大关键字和本块第一个和最后一个元素的下表地址
分块查找实际上进行两次查找,即二分查找平均长度+顺序查找平均长度
——————————————————————————————————————————
二叉排序树与平衡二叉树
二叉排序树满足以下三个条件:
1、若它左子树不空,则左子树所有关键字的值均小于根关键字的值
2、若它右子树不空,则右子树所有关键字的值均大于根关键字的值
3、左右子树又各是一棵二叉排序树
二叉排序树查找关键字算法
BTNode* BSTSearch(BSTNode* bt,int key)
{
if(bt==NULL)
{
return NULL;
}
else{
if(bt->key=key)
return bt;
else if(key<bt->key)
return BSTSearch(bt->lchild,key);
else
return BSTSearch(bt->rchild,key);
}
}
二叉排序树插入关键字算法
int BSTInsert(BTNode *&bt,int key)
{
if(bt==NULL)
{
bt=(BTNode*)malloc(sizeof(BTNode));
bt->lchild=bt->rchild=NULL;
bt->key=key;
return 1;
}
else
{
if(key==bt->key)
{
return 0;
}
else if(key<bt->key)
{
return BSTInsert(bt->lchild,key);
}
else{
return BSTInsert(bt->rchild,key);
}
}
}
二叉排序树删除关键字分为以下三种情况
1、被删除结点p为叶子结点,直接删除即可
2、p只有左子树或p只有右子树,只需将p删掉,再将p的子树连接在p的父节点
3、p有左子树和右子树,此时需找到p的左子树最右节点或是p的右子树最左节点,将此节点替代p
——————————————————————————————————————————————————————
平衡二叉树
平衡二叉树是一种特殊的二叉排序树,其左右子树皆是平衡二叉树,左右子树高度之差绝对值不超过1
下面通过例题展示如何建立平衡二叉树和插入节点维持平衡二叉树
例题:通过序列{16,3,7,11,9,26,18,14,15}构造一棵AVL树,构造完成后依次删除16,15,11
————————————————————————————————————————————————————————————————————————————
b-树与b树
b-树中所有节点的孩子结点个数的最大值称为b-树的阶,通常用m表示,并且满足以下条件:
1、每个结点最多有m个分支,最少分支数要看是否为根节点,根节点至少有2个分支,非根非叶几点至少有m/2(向上取整)个结点
2、有n个分支的结点有n-1个关键字,按递增顺序排列,且各关键字不相等
3、叶节点处于同一层,可用空指针表示,代表查找失败的位置
b-树的特点
1、结点的分支数等于关键字数加1,最大的分支数就是b-树的阶树
2、上图为一颗5阶b-树,因此m/2=3(向上取整),除根节点,各节点要至少3个分支
3、下层结点内的关键字取值总是落在由上层结点关键字所划分的区间内
b-树的基本操作
关键字查找
二叉排序树是二路查找,b-树是多路查找
b-树关键字的插入和删除
例子:用关键字序列:1,2,6,7,11,4,8,13,10,5,17,9,16,20,3,12,14,18,19,15创建一棵5阶b-树
给出删除关键字8,16,15,4的过程
1、求结点中关键字的个数范围
因为要求为5阶,所以关键字个数范围为2~4
2、插入过程
3、删除过程
tip:对于不在底端节点上的关键字,需要用它左子树最大值或右子树最小值来替换他的位置,再进行删除
——————————————————————————————————————————————————
b+树:
b+树中具有n个关键字的结点含有n个分支;b-树中n个关键字的结点有n+1个分支
b+树中除根节点的关键字个数范围为m/2<=n<=m,根节点为2<=n<=m;b-树中除根节点的关键字个数范围为(m/2)-1<=n<=m-1,根节点为1<=n<=m-1;(均为向上取整)
b+树中叶子结点包含信息
b+树中所有非叶子结点仅起到一个索引的作用,结点中的每个索引项只含有对应子树的最大关键字和指向该子树的指针
——————————————————————————————————————————————————————————
散列表:根据给定关键字来计算出关键字在表中的地址
哈希地址即为key在查找表中的地址
例子
查找成功的ASL指找到表中已有表项的平均比较次数
查找不成功的ASL指在表中找不到待查表项,但找到插入位置(空位置)的平均比较次数,根据hash函数可以映射到的个数做除数,而不是表长
装填因子是关键字个数和表长的比值
常用hash函数构造方法
1、直接定址法,即H(key)=key或H(key)=a*key+b;
2、数字分析法,取关键字的若干位组成hash地址
3、平方取中法,取关键字平方后的中间几位作为Hash地址
4、除留余数法(上面例子用的方法),H(key)=key mod p,p选择小于等于表长的最大素数
常用的Hash冲突处理方法
1、开放定址法
1.1线性探查法(上面例子用的方法)依次找到下一个空位置,易产生堆积问题
1.2平方探查法 设发生冲突的地址为d 探查d+1,d-1,d+4,d-4,d+9........
2、链地址法,hash表中每个单元不再存放记录本身,而是响应同义词链表的头指针