平衡二叉树之二叉排序树

最近写了点题目,用到平衡二叉树,以后看过,但是现在完全不记得了......可能以后去面试也要写到平衡二叉树的....重新学习一下.....

平衡二叉树是在二叉排序树的基础上成立的,所以先来弄一下二叉排序树。


二叉排序树或者是一棵空树,或者是具有下列性质的 二叉树:(其实就是子节点比结点大或等于的就放结点右边,小的放左边)
(1)若左子树不空,则左子树上所有结点的值均小于它的 根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于或 等于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的节点。

图示为一个二叉排序树




#include "stdio.h"
#include "stdlib.h"


//定义二叉排序树的结构
typedef struct BNODE 
{
int data;//结点的数据
struct BNODE *lchild, *rchild;//左子树指针和右子树指针


}BNODE,*BTree;






//二叉排序树的查找
bool FindTree(BTree T, int key, BTree f, BTree *p)//指针f指向T的父结点,如果查找成功,p指向该查找的结点,返回true。查找失败p就指向查找路径上时所访问的最后一个结点,返回false
{
if (!T)//查找不成功
{
*p = f;
return false;
}
else if (T->data == key)//查找成功
{
*p = T;
return true;
}
else if (T->data>key)
{
FindTree(T->lchild, key, T, p);//大于就在左子树继续查找
}
else
{
FindTree(T->rchild, key, T, p);//小于就在右子树继续查找
}

}






//二叉排序树的插入操作
bool InsetTree(BTree T, int key)//当二叉排序树T中不存在关键字等于key的数据时,插入key并返回true,否则返回false
{
BTree s, p;
if (!FindTree(T, key, NULL, &p))//查找不成功,插入
{
s = (BTree)malloc(sizeof(BNODE));//创建结点s
s->data = key;
s->lchild = s->rchild = NULL;
if (!p)
T = s;
else if (p->data > key)
p->lchild = s;//插入s为左结点
else
{
p->rchild = s;//插入s为右结点
}
return true;


}
return false;
}




//创建一个二叉排序树,这样就可以创建出上图所示的那个二叉排序树了,各位自己抽象地想象一下
void main()
{
int i;
int a[9] = { 8, 3, 1, 6, 4, 7, 10, 14, 13 };
BTree T = NULL;
for (i = 0; i < 9;i++)
{
InsetTree(T, a[i]);
}
}





//从查找到创建二叉排序树挺简单的,但请神容易送神难,二叉排序树的删除操作就难了
//因为根据二叉排序树的结构特点,小的插左边,大的插右边,随便删除一个数据都会导致结构混乱
//解决的方法就是寻找被删除结点数据的前驱或后继来继承被删除结点(就是和被删除结点数据的最接近的那两个结点数据,一大一小)
//最近的结点说我继承了遗产,哇哈哈哈哈



//好了,废话不多说,下面是二叉排序树的删除操作
//如果二叉排序树中存在和key相等的结点,就删除该结点并返回true,否则返回false

bool DeleteTree(BTree *T, int key)
{
if (!*T)//不存在和key相等的数据
{
return false;
}
else
{
if ((*T)->data == key)//找到和key相等的数据了,删除掉
return Delete(T);
else if ((*T)->data > key)
return DeleteTree(&(*T)->lchild, key);
else
{
return DeleteTree(&(*T)->rchild, key);
}
}


}


//删除操作的具体代码
//删除结点p,并重接它的左子树或者右子树

bool Delete(BTree *p)
{
BTree q, s;
if ((*p)->rchild == NULL)//右子树空就只需要重接它的左子树
{
q = *p; *p = (*p)->lchild; free(q);
}
else if ((*p)->lchild == NULL)//左子树空就只需要重接它的右子树
{
q = *p; *p = (*p)->rchild; free(q);
}
else//左子树和右子树都不空的情况
{
q = *p; s = (*p)->lchild;
while (s->rchild)//转左,然后向右到尽头(找待删除结点的前驱)
{
q = s; s = s->rchild;
}
(*p)->data = s->data;//s指向被删除结点的直接前驱
if (q != *p)
{
q->rchild = s->lchild;//重接q的右子树
}
else
q->lchild = s->lchild;//重接q的左子树
free(s);
}
return true;
}




//后面的删除代码可能有点理解不了...但是时间有限...有空我在详细修改一下...见谅

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
平衡二叉树二叉排序树和平衡二叉排序树都是数据结构中用于存储有序元素的特殊类型的二叉树,它们在结构和性能上有一些关键区别: 1. **二叉排序树(Binary Search Tree, BST)**: - 它是一个二叉树,其中每个节点的左子树包含的值都小于该节点的值,右子树包含的值都大于该节点的值。 - 保证了查找、插入和删除操作的时间复杂度通常为 O(log n)(假设树是完全平衡的),但在最坏情况下(树退化成链表)可能会退化为 O(n)。 - 平衡性不是其固有属性,如果插入或删除操作导致树严重不平衡,性能会下降。 2. **平衡二叉树(Balanced Binary Tree)**: - 这是一个更宽泛的概念,包括但不限于AVL树、红黑树、B树等,这些树的设计目的是在每次插入和删除后自动调整以保持树的高度尽可能均衡。 - 它们都有自我修复的能力,即使在插入或删除操作后也能快速恢复平衡,避免极端情况下的性能退化。 - 不同的平衡二叉树在具体实现上有差异,如AVL树是高度严格平衡的,而红黑树则相对宽松一些,但总体上保证了O(log n)的操作时间。 3. **平衡二叉排序树(Balanced Binary Search Tree, BBST)**: - 这实际上是平衡二叉树二叉排序树的结合,它保持了二叉排序树排序性,同时具有平衡二叉树的特性。 - 当插入或删除后,BBST会进行适当的旋转操作来维持平衡,确保查找、插入和删除始终能在O(log n)时间内完成。 相关问题: 1. 什么是BST的平衡性? 2. AVL树和红黑树是如何保持平衡的? 3. BBST在实际应用中的优缺点是什么?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值