二叉排序树,又称二叉查找树,其或者是一棵空树,或者是满足下列性质的二叉树:
上述定义要求查找表中没有相同关键字的数据元素。
根据二叉排序树的定义可知,对二叉排序树进行中序遍历可以得到一个有序序列。因此对于任意一个关键字序列构造一棵二叉排序树,其实质是对此关键字序列进行排序,使其变成有序序列。
#define _CRT_SECURE_NO_WARNINGS 1
#include
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,并重接它的左子树或右子树
};
二叉排序树的插入操作应保证插入后仍满足二叉排序树的定义,新插入的结点总是叶子结点。其插入过程如下:
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]);
}
}
由于二叉排序树按中序遍历可得有序序列,所以在二叉排序树中进行查找,与二分查找类似,也是一个逐步缩小查找范围的过程,查找的步骤如下:
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);
}
二叉排序树中删除结点的原则是:删除结点后仍是二叉排序树。
设在二叉排序树被删除结点是p
,其双亲结点是f
.不失一般性,设p
的左孩子或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;
}
}
平衡二叉树或者是一棵空的二叉排序树,或者是具有下列性质的二叉排序树:
1
。✅若将二叉树上结点的平衡因子定义为该结点的左子树的高度与右子树的高度之差,则平衡二叉树上的所有结点的平衡因子只可能是1,0和-1。若平衡二叉树上有一个结点的平衡因子的绝对值大于1,则该树就不是一棵平衡二叉树。
若向平衡二叉树中插入一个新结点而引起不平衡,则采用以下方法进行调整:
RR型
调整是指在A
结点的右孩子(设为B结点)的右子树上插入一个结点,使得A
结点的平衡因子由-1
变为-2
引起不平衡而产生的调整。如图所示,带阴影区域表示插入结点,h
表示子树的树高。调整方法为单向左旋转平衡,具体方法如下:
B
变为调整后的最小子树的根结点。A
变成结点B
的左孩子。BL
变成结点A
的右子树。LL型
调整是指在A
结点的左孩子(设为B结点)的左子树上插入一个结点,使得A
结点的平衡因子由1
变为2
引起不平衡而产生的调整。如图所示,带阴影区域表示插入结点,h
表示子树的树高。调整方法为单向右旋转平衡,具体方法如下:
RL型
调整是指在A
结点的右孩子(设为B结点)的左子树上插入一个结点,使得A
结点的平衡因子由-1
变为-2
引起不平衡而产生的调整。如图所示,带阴影区域表示插入结点,h
表示子树的树高。调整方法为右旋转后向左旋转平衡,具体方法如下:
LR型
调整是指在A
结点的左孩子(设为B结点)的右子树上插入一个结点,使得A
结点的平衡因子由1
变为2
引起不平衡而产生的调整。如图所示,带阴影区域表示插入结点,h
表示子树的树高。调整方法为左旋转后向右旋转平衡,具体方法如下:
由于平衡二叉树关键字的查找过程与二叉排序树关键字的查找过程相同,因此,在平衡二叉树的查找过程中关键字的比较次数不超过平衡二叉树的深度。
好啦,关于动态查找表二叉排序树和平衡二叉树的知识到这里就先结束啦,后期会继续更新学习数据结构与算法的相关知识,欢迎大家持续关注、点赞和评论!❤️❤️❤️