树表查找 - 二叉排序树(C语言)

本文介绍了二叉排序树的概念和结构,包括递归查找、插入和删除节点的算法。当面临频繁的插入和删除操作时,二叉排序树在最坏情况下性能下降,平均查找长度与树形态相关。为解决这一问题,提出了平衡二叉树如AVL树作为优化策略。
摘要由CSDN通过智能技术生成


当表插入,删除操作频繁时,我们可以采用动态查找表

二叉排序树

概念:二叉排序树(Binary Sort Tree),又称为二叉查找树。它或者是一棵空树,或是具有下列性质的二叉树。
• 如果它的左子树为空,则左子树所有结点的值均小于它的根结点的值
• 如果它的右子树为空,则右子树所有结点的值均大于它的根结点的值
• 它的左子树,右子树也分别为二叉排序树

结构定义

#include<stdio.h>
#include<stdlib.h>
#define OK 1
#define ERROR 0
typedef int Status;

typedef struct BiTNode {
	int data;                //结点数据
	struct BiTNode* lchild, * rchild;    //左右孩子指针
}BiTNode, *BiTree;

递归查找

算法思想:

(1) 若二叉排序树为空,则查找失败,返回空指针
(2) 若二叉排序树非空,将给定值key与根结点的关键字T->data进行比较:
若key == T->data,返回根结点地址
若key < T->data,进一步查找左子树
若key > T->data,进一步查找右子树

查找不成功,指针指向查找路径上访问的最后一个结点并返回ERROR.
查找成功,指针p指向该数据元素结点,返回OK.

/* 递归查找二叉树是否存在key */
Status SearchBST(BiTree T, int key, BiTree f, BiTree* p)
{
	if (!T)     //查找不成功,指针指向查找路径上访问的最后一个结点并返回ERROR
	{
		*p = f;
		return ERROR;
	}
	else if (key == T->data)  //查找成功,指针p指向该数据元素结点,返回OK
	{
		*p = T;
		return OK;
	}
	else if (key < T->data)
		return SearchBST(T->lchild, key, T, p);  //在左子树中查找
	else
		return SearchBST(T->rchild, key, T, p);  //在右子树中查找

}

插入

/* 插入*/
Status InsertBST(BiTree *T, int key)
{
	BiTree p, s;
	if (!SearchBST(*T, key, NULL, &p))  //查找不成功
	{
		s = (BiTree)malloc(sizeof(BiTNode));
		s->data = key;
		s->lchild = s->rchild = NULL;
		if (!p)
			*T = s;      //插入新的根结点
		else if (key < p->data)
			p->lchild = s;       //插入 s为左孩子
		else
			p->rchild = s;      //插入 s为右孩子
		return OK;
	}
	else       //已有key值
		return ERROR;
}

构建

循环插入操作即可,但是 T 需初始化为 NULL.

删除

/* 若二叉排序树T中存在key值的元素,删除该数据元素结点 */
Status DeleteBST(BiTree* T, int key)
{
	if (!*T)           //不存在值 =key的元素
		return ERROR;
	else
	{
		if (key == (*T)->data)
			return Delete(T);
		else if (key < (*T)->data)
			return DeleteBST(&(*T)->lchild, key);
		else
			return DeleteBST(&(*T)->rchild, key);
	}
}

/* 删除结点p,并重新连接它的左子树或右子树 */
Status Delete(BiTree* p)
{
	BiTree 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;   //被删结点前驱的值取代被删结点的值)
		if (q != *p)
			q->rchild = s->lchild;   //重新连接q的右子树
		else
			q->lchild = s->lchild;   //重新连接q的左子树
		free(s);
	}
	return OK;
}

二叉排序树不足

含有 n 个结点的二叉排序树的平均查找长度和树的形态有关.

最好情况(形态均匀):ASL = log (n + 1) - 1; O(log n)
最坏情况(单子树形态):ASL = (n + 1)/ 2; O( n)

我们需要尽量让二叉树的形态均匀,
所以我们可以做平衡化处理

大家支持一下(^ ▽ ^)
树表查找-平衡二叉树(AVL树)(C语言)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mirror_zz

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

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

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

打赏作者

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

抵扣说明:

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

余额充值