数据结构|查找

树表的查找

复习

  • 线性表查找的三种方法
  •  	顺序/折半/分块
    
  •  			折半:效率most,**but需要关键字有序,不适合链表**
    
  •  			插入删除操作不方便
    

若要对动态查找表(会进行插入删除的表)进行查找:

二叉排序树(二叉搜索树)是啥?

二叉树--------》对结点值的约束--------》二叉排序树
左子树上所有节点关键字**<=根节点关键字
右…
>=**…

二叉排序树的结点类型声明:

typedef struct node{
	KeyType key;//关键字项
	InfoType data;//其他数据域
	struct node*lchild,*rchild;//左、右孩子指针
	}BSTNode;

和二叉链一样,通过根节点指针bt唯一表示二叉排序树

删除节点中用子结点上来替代的函数:

void Delet(BSTNode*&p){
	BSTNode*q;
	if(p->rchild==NULL){
		q=p;
		p=p->lchild;//用p的左孩子替代
		free(q);//释放函数

递归找结点r 的最右下结点

void Deletel(){
if(r->rchild!=NULL)
	Deletel(p,r->rchild);
	....
	}

删除有双分支的节点

  • 用该节点的中序前驱/中序后继结点q的值替换p结点的值
  • 即左子树中最右的叶节点/左子树中最左的叶节点

平衡二叉树的调整
LL型

  • 调整前后对应的中序序列相同
  • 向右旋转

LL型和RR型是对称的

RR型

  • 向左旋转,左子树换位给旁边的

LR型和RL型是对称的

平衡二叉树中删除结点

查找—》删除—》调整

  • 本来是一颗平衡的,所以平衡因子均正常
  • 调整:从被删除的地方向根结点方向找第一个失去平衡的结点
  •  	-2:右边多了
    
  •  			-1:右边多一些,RR
    
  •  			1:左边多一些,RL
    
  •  			0:RR/RL都可
    
  •  	2:左边多了
    
  •  			-1:右边多一些:LR
    
  •  			1:左边多一些:LL
    
  •  			0:LL/LR都可
    

平衡二叉树的构造

Th以Th-1和Th-2作为其根节点的左右子树

对于每一个Th,只要从中删去一个结点,就会失去平衡或高度不再是h

平衡二叉树中结点个数与高度之间的关系
h=log2(Nh+1)

  • 含有n各结点的平衡二叉树的平均查找长度为O(log2n)
  • 算法的时间复杂度为O(log2n)

折半查找对行的判断树是一颗平衡的二叉排序树
==》时间复杂度也是👆

B树

用于:多路查找

B树的特点

  • m阶==》每个节点至多m个孩子节点/m-1个关键字
  • 叶子都在同一层
  • 所有节点的平衡因子均为0
  • m/2<=孩子节点<=m
  • m/2-1<=关键字<=m-1

计算B树的高度时,需要计入最底层的外部结点

外部结点就是失败结点,指向它的指针为空

关键字与外部结点个数的关系

n个关键字–》n+1个外部结点

B树的结点类型定义

//链式
#define MAXM 19
typedef int KeyType;
typedef struct node{
	int keynum;
	KeyType key[MAXM];//存放关键字的数组从1开始
	struct node *parent;//双亲节点指针
	struct node *ptr[MAXM];//孩子节点指针数组[0....keynum]
	}BTNode;

在这里插入图片描述
n:节点个数
p:节点i
k:节点上的关键字序列

在这里插入图片描述

B树的查找

将k与根节点中的key[i]进行比较
key[i]存放该节点的关键字k1,k2,k3…
查找失败:
找到某个节点相应的指针为空时–》落入了外部节点–》查找失败
(即:外部节点指针为空)

B-树的插入

只能是叶子节点的插入
1、查找该关键字的插入节点
2、插入关键字

思考:
在这里插入图片描述
1、不是
2、不是

B-树的删除

1、查找
2、删除关键字
在这里插入图片描述

删除非叶节点

中序前驱、中序后继上来替代它

删除叶节点

注意删除后,节点的关键字数需要满足min和max,所以可能需要调整
不够的话需要找【兄弟】借

删除后min不够的情况下:
在这里插入图片描述
👇
在这里插入图片描述
17双亲下来,18兄弟上去(15,17,18)

兄弟也不够借?

将双亲中的中间(分割他们的数)放下来,与被删除节点和兄弟节点合并
在这里插入图片描述
发现双亲节点也不满足了???
继续合并!
在这里插入图片描述
这种情况下,树的高度下降了一层

B+树

与上树的不同

1、有n颗子树的节点恰好有n个关键字【某个节点的子树和关键字的关系】
2、叶子节点包含全部关键字,指向相应记录的指针
3、叶子节点按照关键字大小顺序连接,并将叶子节点连接起来
在这里插入图片描述
4、每一个分支节点向下,包含的是子节点中【最大关键字】及指向子节点的指针
类似下级索引的索引块
在这里插入图片描述

B+树的查找

一、通过【根节点】指针【随机查找】

二、通过【叶子节点】指针【顺序查找】

哈希表

适合什么?

关键字key和存储地址存在某种函数关系
在这里插入图片描述

学生信息问题

在这里插入图片描述
复习:查找方法:

  • 顺序查找
  • 二分查找

搞了一个函数关系之后(学号和存储地址的关系):
在这里插入图片描述

哈希冲突

关键字K1和k2不同,但函数值相同(地址相同)
不可避免

哈希表设计

在这里插入图片描述

哈希函数的构造方法

1、直接法
2、除留余数法
h=k mod p(p是素数,p<=m,存储空间m个单元)
3、数字分析法

  • 关键字范围较大时
  • 取最后两位为哈希地址
  • 将大数值范围映射成小数值范围
    在这里插入图片描述

哈希冲突解决办法

1、开放定址法
找个旁边的空位坐下
1)线性探查法
挨个往后找
在这里插入图片描述
2)平方探测法
找前后的空位置
在这里插入图片描述
可以避免堆积现象

开放地址法用哈希表查找k过程

  • 调用哈希函数求出d=h(k),地址
  • 该地址处的元素不是要找的
  •  	用某种探查法求处下一地址(因为存进去的时候不一定是按函数值
    
  • if下一地址没有这个元素
  •  	查找失败
    
  • 否则 有这个元素
  •  	该地址上的值即是所求
    

在这里插入图片描述
在这里插入图片描述

拉链法查找k过程

  • 根据函数求地址d=h(k)
  • 设一个指针p指向ha[d],ha[d]是一个单链表
  • 判断d处的值是否=k
  •  不相等:while循环下一节点p=p->next
    
  • p为空时
  •  查找失败
    
  • 若找到了
  •  返回p所指的节点
    

拉链法中成功查找的ASL计算

第i层节点个数*i之和
在这里插入图片描述

拉链法中不成功查找的ASL计算

  • 只有1个节点的单链表有a个,即这a个都是只用比较一次就会失败
  • 有2个节点的单链表有b个,即这b个都是只用比较一次就会失败
  • 在这里插入图片描述

查找小结

线性表查找

线性表的存储结构

线性表查找算法

顺序
折半
分块

掌握两个ASL
在这里插入图片描述
折半查找成功的最大比较次数:判断树的最大高度Log2(n+1)

在这里插入图片描述
可由log2(19+1)=5知答案
顺序查找和分块查找所需比较次数会更多!!
在这里插入图片描述
在这里插入图片描述
比较元素出现了2次47!

树表查找

二叉排序树

二叉树结构+BST特性=二叉排序树
在这里插入图片描述
确定一棵树:需要中序+后序/中序+前序
中序一定是按元素值排列的

平衡二叉树

二叉排序树+平衡特性=平衡二叉树
在这里插入图片描述
在这里插入图片描述
拉链法不会引起堆积,线性探测法易引起

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值