数据结构与算法-动态查找表

在这里插入图片描述

🎈3动态查找表

🔭3.1二叉排序树

🔎二叉排序树,又称二叉查找树,其或者是一棵空树,或者是满足下列性质的二叉树:

  1. 若它的左子树不空,则左子树上所有元素的值均小于根结点元素的值。
  2. 若它的右子树不空,则右子树所有元素的值均大于根结点元素的值。
  3. 左右子树分别为二叉排序树。

上述定义要求查找表中没有相同关键字的数据元素。
📖根据二叉排序树的定义可知,对二叉排序树进行中序遍历可以得到一个有序序列。因此对于任意一个关键字序列构造一棵二叉排序树,其实质是对此关键字序列进行排序,使其变成有序序列。

🏆3.1.1二叉排序树的类定义

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
typedef int KeyType;
typedef int InfoType;
typedef struct
{
	KeyType key;//KeyType为关键字数据类型
	InfoType otherinfo;//其他域
}DElemType;
typedef struct BstNode
{
	DElemType data;
	BstNode* lchild, * rchild;
}BstNode;
class BsTree
{
private:
	BstNode* bst;
	void Insert(BstNode*& t, DElemType e);//二叉排序树中递归插入一个结点
	BstNode* Search(BstNode* t, KeyType key);//递归查找关键字key
public:
	BsTree()//构造函数,创建空的二叉排序树
	{
		bst = NULL;
	}
	BstNode* SearchBST(KeyType key);//查找关键字等于key的结点
	void InsertBST(DElemType e);//递归创建的二叉树传递给私有成员
	void CreatBiTree(DElemType d[], int n);//生成二叉排序树,n个数据在数组d中
	void DeleteBst(BstNode*& t, DElemType e);//删除二叉排序树中的一个结点
	void Deletep(BstNode*& p);/从二叉排序树中删除结点p,并重接它的左子树或右子树
};

🏆3.1.2二叉排序树的插入和生成

📖二叉排序树的插入操作应保证插入后仍满足二叉排序树的定义,新插入的结点总是叶子结点。其插入过程如下:

  1. 若二叉树t为空,则生成一个根结点。
  2. 将key于根结点的关键字比较,若keydata,则将key插入到根结点的左子树中,否则插入到根结点的右子树中。
    在这里插入图片描述
void BsTree::Insert(BstNode*& t, DElemType e)
{
	if (t == NULL)
	{
		t = new BstNode;
		t->lchild = t->rchild = NULL;
		t->data = e;
		return;
	}
	if (e.key < t->data.key)
		Insert(t->lchild, e);//在左子树插入结点e
	else
		Insert(t->rchild, e);//在右子树插入结点e
}
void BsTree::InsertBST(DElemType e)
{
	BstNode* t = bst;
	Insert(t, e);
	bst = t;
}
void BsTree::CreatBiTree(DElemType d[], int n)
{
	for (int i = 0; i < n; i++)
	{
		InsertBST(d[i]);
	}
}

🏆3.1.3二叉树的查找

📖由于二叉排序树按中序遍历可得有序序列,所以在二叉排序树中进行查找,与二分查找类似,也是一个逐步缩小查找范围的过程,查找的步骤如下:

  1. 若二叉树t为空,或key==t->data.key,则返回t
  2. 否则将key与根结点的关键字比较,若key<t->datda.key,则递归查找左子树,否则递归查找右子树。
    在这里插入图片描述
BstNode* BsTree::Search(BstNode* t, KeyType key)
{
	if (t == NULL || key == t->data.key)
		return t;
	else if (key < t->data.key)
		return Search(t->lchild, key);//查找左子树
	else
		return Search(t->rchild, key);//查找右子树
}
BstNode* BsTree::SearchBST(KeyType key)
{
	BstNode* t = bst;
	return Search(t, key);
}

🏆3.1.4二叉排序树的删除

二叉排序树中删除结点的原则是:删除结点后仍是二叉排序树。
🔎设在二叉排序树被删除结点是p,其双亲结点是f.不失一般性,设p的左孩子或p为根结点。分三种情况讨论:

  1. 若p为叶子结点,则直接删除。如图a所示。
  2. 若p只有左子树pl或只有右子树pr,则令pl或pr直接成为双亲结点f的子树。如图b或c所示。

在这里插入图片描述

  1. 若被删除结点p既有左子树pl又有右子树pr,则在pl中选值最大的代替p,该数据按二叉排序树的性质应在左子树的最右下结点。
    在这里插入图片描述
void BsTree::DeleteBst(BstNode*& t, DElemType e)
{
	if (!t)
		return;
	else
	{
		if (e.key == t->data.key)
			Deletep(t);
		else if (e.key < t->data.key)
			DeleteBst(t->lchild, e);
		else
			DeleteBst(t->rchild, e);
	}
}
void BsTree::Deletep(BstNode*& p)
{
	if (!p)
		return;
	BstNode* s, * q;
	if (p->rchild == NULL)
	{
		q = p;
		p = p->lchild;
		delete q;
	}
	else if (p->lchild == NULL)
	{
		q = p;
		p = p->rchild;
		delete q;
	}
	else 
	{
		q = p;
		s = p->lchild;
		while (s->rchild != NULL)
		{
			q = s;
			s = s->rchild;
		}
		p->data = s->data;
		if (q != p)
			q->rchild = s->lchild;
		else
			q->lchild = s->rchild;
		delete s;
	}
}

🔭3.2平衡二叉树

🌞平衡二叉树或者是一棵空的二叉排序树,或者是具有下列性质的二叉排序树:

  1. 它的左右子树均为平衡二叉树。
  2. 左子树和右子树的高度之差的绝对值不超过1

✅若将二叉树上结点的平衡因子定义为该结点的左子树的高度与右子树的高度之差,则平衡二叉树上的所有结点的平衡因子只可能是1,0和-1。若平衡二叉树上有一个结点的平衡因子的绝对值大于1,则该树就不是一棵平衡二叉树。

🏆3.2.1平衡二叉树的调整方法

🌞若向平衡二叉树中插入一个新结点而引起不平衡,则采用以下方法进行调整:

  1. 不涉及到不平衡点的双亲,即以不平衡点为根的子树高度应保持不变。
  2. 新结点插入后,向根结点回溯,找到第一个原平衡因子不为0的结点。
  3. 在调整中,仅涉及前面提到的最小子树。
  4. 调整后二叉树的性质不变。
🎠RR型调整

🔎RR型调整是指在A结点的右孩子(设为B结点)的右子树上插入一个结点,使得A结点的平衡因子由-1变为-2引起不平衡而产生的调整。如图所示,带阴影区域表示插入结点,h表示子树的树高。调整方法为单向左旋转平衡,具体方法如下:

  1. 把结点B变为调整后的最小子树的根结点。
  2. 把结点A变成结点B的左孩子。
  3. BL变成结点A的右子树。

在这里插入图片描述

🎠LL型调整

🔎LL型调整是指在A结点的左孩子(设为B结点)的左子树上插入一个结点,使得A结点的平衡因子由1变为2引起不平衡而产生的调整。如图所示,带阴影区域表示插入结点,h表示子树的树高。调整方法为单向右旋转平衡,具体方法如下:

  1. 把结点B变为调整后的最小子树的根结点。
  2. 把结点A变成结点B的右孩子。
  3. BR变成结点A的左子树。
    在这里插入图片描述
🎠RL型调整

🔎RL型调整是指在A结点的右孩子(设为B结点)的左子树上插入一个结点,使得A结点的平衡因子由-1变为-2引起不平衡而产生的调整。如图所示,带阴影区域表示插入结点,h表示子树的树高。调整方法为右旋转后向左旋转平衡,具体方法如下:

  1. 把结点B的左孩子(设为C)变为调整后的最小子树的根结点。
  2. 把结点A变成结点C的左孩子,结点B变为结点C的右孩子。
  3. 把结点C的右子树变为结点B的左子树。
  4. 把结点C的左子树变为结点A的右子树。
    在这里插入图片描述
🎠LR型调整

🔎LR型调整是指在A结点的左孩子(设为B结点)的右子树上插入一个结点,使得A结点的平衡因子由1变为2引起不平衡而产生的调整。如图所示,带阴影区域表示插入结点,h表示子树的树高。调整方法为左旋转后向右旋转平衡,具体方法如下:

  1. 把结点B的右孩子(设为C)变为调整后的最小子树的根结点。
  2. 把结点A变成结点C的右孩子,结点B变为结点C的左孩子。
  3. 把结点C的右子树变为结点A的左子树。
  4. 把结点C的左子树变为结点B的右子树。
    在这里插入图片描述

🏆3.2.2平衡二叉树的查找分析

由于平衡二叉树关键字的查找过程与二叉排序树关键字的查找过程相同,因此,在平衡二叉树的查找过程中关键字的比较次数不超过平衡二叉树的深度。
在这里插入图片描述

好啦,关于动态查找表二叉排序树和平衡二叉树的知识到这里就先结束啦,后期会继续更新学习数据结构与算法的相关知识,欢迎大家持续关注、点赞和评论!❤️❤️❤️

  • 22
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 20
    评论
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一口⁵个团子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值