ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

二叉排序树与平衡二叉树(BST&AVLT)

2021-01-27 23:03:22  阅读:131  来源: 互联网

标签:左子 结点 return 删除 BST AVLT else 二叉树 key


二叉排序树的一些操作

Note:不会贴图QwQ,为了更好的理解最好是找图片并结合给出的思路和代码,自己动手做做OvO…

二叉排序树的查找:
传入参数:
待查找的BST,关键字,指向双亲的指针f,指向查找结点的指针p
思路:
递归遍历BST
查找成功->指针p指向该元素结点
查找失败->指针p指向该路径上访问的上一个结点
递归出口:1.结点空时停;2.找到时停

二叉排序树的插入
传入参数:
待操作的BST,待插入的关键字
思路:
遍历BST->
找到->返回false表示BST中有该元素
没找到->插入元素
插入元素:
两个结构体指针p,s
s为待插入的结点
p为指向待操作的结点的指针

在这些操作中删除操作相对比较复杂一些,需要考虑的情况比较多,最好是结合图片理解(自己画一个QwQ)…
二叉排序树的删除
考虑情况:
1.删除的结点是叶子结点
2.删除的结点是仅有左(右)子树的结点
3.删除的结点是既存在左子树又存在又子树
1和2可视为同一情况
传入参数:
待操作的BST,删除的关键字key
思路:
递归遍历BST如果找到做删除操作,没找到返回false表示查找失败,BST中没有要删除的元素
删除操作:
两个结构体指针q,s;q用来存放待删除结点的上个结点,s为每次迭代的结点
删除情况1:删除的结点只存在左子树,将他左孩子接上即可
删除情况2:删除的结点只存在右子树,将他右孩子接上即可
删除情况3:删除的结点既存在左子树也存在右子树
用直接前驱替换,或者用直接后继替换

BST的代码

// 二叉树的二叉链表结点结构定义
typedef struct BiTNode{
	int data;
	struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

// 递归查找二叉排序树 T 中是否存在 key
// 指针 f 指向 T 的双亲,其初始值调用值为NULL
// 若查找成功,则指针 p 指向该数据元素结点,并返回 true
// 否则指针 p 指向查找路径上访问的最后一个结点,并返回 false

Status SearchBST(BiTree T, int key, BiTree f, BiTree *p)
{
	if(!T)  // 查找不成功
	{
		*p = f;
		return false;
	}
	else if(key == T->data) // 查找成功
	{
		*p = T;
		return true;
	}
	else if(key < T->data)
	{
		return SearchBST(T->lchild, key, T, p); // 在左子树继续查找
	}
	else
	{
		return SearchBST(T->rchild, key, T, p); // 在右子树继续查找
	}
}

// 当二叉排序树 T 中不存在关键字等于 key 的数据元素时
// 插入 key 并返回 true 否则返回 false

Status InsertBST(BiTree *T, int key)
{
	BiTree p, s;
	if(!SearchBST(*T, key, NULL, &p))
	{
		s = new BiTNode;
		s->data = key;
		s->lchild = s->rchild = NULL;
		
		if(!p)
		{
			*T = s; // 插入s为新的根节点
		}
		else if(key < p->data)
		{
			p->lchild = s;  // 插入s为左孩子
		}
		else
		{
			p->rchild = s;  // 插入s为右孩子
		}
		return false;
	}
	else
		return false;   // 树中已有关键字相同的结点不再插入
}

// 二叉排序树的删除操作
Status DeleteBST(BiTree *T, int key)
{
	if(!*T)
	{
		return false;
	}
	else
	{
		if(key == (*T)->data)
		{
			return Delete(T);
		}
		else if(key < (*T)->data)
		{
			return DeleteBST(&(*T)->lchild, key);
		}
		else
		{
			return DeleteBST(&(*T)->rchild, key);
		}
	}
}

// 三种情况
// 1.删除的是叶子结点
// 2.删除的结点仅有右(做)子树
// 3.删除的结点既有左子树又有右子树

Status Delete(BiTree *p)
{
	BiTree q, s;    // q用来存放待删除结点的上一个结点(双亲节点),s为每次迭代所用到的结点
	
	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)    //s一直寻找左子树中最大的结点,也就是s走到右子树为空时的结点
		{
			q = s;  // q每次指向上一层(双亲)
			s = s->rchild;  // s继续向右走
		}

		(*p)->data = s->data;   // 将左子树中的最大值(直接前驱元素)与*p替换
		
		if(q != *p) // p和q不等的时候将s的左子树接到q的右子树
		{
			q->rchild = s->lchild;
		}
		else    // p和q相同的时候将s的左子树接到q的左子树,因为这是pq相同,相当于将s的左子树接上,替换掉s
		{
			q->lchild = s->lchild;
		}
		
		delete(s);  // 释放掉s是因为s是已经替换后的结点,s结点已无意义
	}
	
	return true;
}

结合自己的一些理解写出来的,如果有不完全或者不对的地方请指出,会改正的OuO

标签:左子,结点,return,删除,BST,AVLT,else,二叉树,key
来源: https://blog.csdn.net/weixin_45677702/article/details/113279640

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有