二叉排序树的创建和基本操作---C++实现

我们已经在之前的文章里将了树和二叉树,今天讲的二叉排序树也是二叉树的一种,不过具有以下性质

1.左子树上所有结点的关键字均小于根结点的关键字;

2.右子树上所有结点的关键字均大于根结点的关键字。

3.左子树和右子树又各是一棵二叉排序树

简单来说就是根结点的左子树都是比根结点的元素值要小,根结点右边的元素都比根结点要大

代码实现如下:

二叉排序树的结点信息和初始化

cpp 复制代码
#include<iostream>
#include<stdlib.h>
#include<stdbool.h>
using namespace std;
//二叉排序树结点
typedef struct BSTNode
{
	int key;//数据域
	struct BSTNode* lchild, * rchild;//指针域
}*BSTree,BSTNode;//BSTree表示整棵树 BSTNode表示结点
//初始化
void InitTree(BSTree* T)
{
	(*T) = NULL;
}

二叉排序树的插入和构建二叉树

1.若原二叉树为空,则直接插入结点;

2.如果关键字k小于根结点值,则插入左子树

3.如果关键字k大于根结点值,则插入右子树

cpp 复制代码
//插入操作
int BST_Insert(BSTree* T, int k)
{
	//空树,直接插入结点
	if ((*T) == NULL)
	{
		(*T) = (BSTNode*)malloc(sizeof(BSTNode));
		if (*T == NULL)
			return -1;//插入失败
		(*T)->key = k;
		(*T)->lchild = NULL; //左孩子为空
		(*T)->rchild = NULL; //右孩子为空
		return 1;//插入成功
	}
	else if (k == (*T)->key)
		return -1; //如果插入相同的则直接返回
	else if (k > (*T)->key)
		return BST_Insert(&(*T)->rchild, k);//因为是要修改右子树,所以要取地址
	else
		return BST_Insert(&(*T)->lchild, k);
	return -1;
}
//构建二叉树
bool Creat_BSTree(BSTree* T, int arr[], int len)
{
	int i = 0;
	while (i < len)
	{
		BST_Insert(T, arr[i]);
		i++;
	}
	return true;
}

二叉排序树的查找(递归方式)

cpp 复制代码
//查找二叉树
BSTree BST_Search(BSTree T,int k)
{
	if (T == NULL)
		return NULL;//空树查找失败
	while (T != NULL && T->key != k)
	{
		if (k > T->key) //k大于根结点
			T = T->rchild;
		else
			T = T->lchild;
	}
	return T;
}

二叉排序树的删除

思想:

先搜索找到目标结点

1.如果被删除的结点z是叶子结点,则直接删除,不回破坏二叉排序树的性质

2.如果结点z只有一棵左子树或右子树,则让z的子树称为z父结点的子树,代替z的位置

3.如果结点z有左、右两棵子树,则令z的直接后继(或直接前驱)代替z,然后从二叉排序树中删去这个直接后继(或直接前驱),这样就转换成了第一后第二种情况

注意:

z的前驱:z的左子树中最右下的结点(该结点在左子树中一定最大)

z的后继:z的右子树中最左下的结点(该结点在右子树中一定最小)

cpp 复制代码
//删除二叉树
int Delete_BSTNode(BSTree* T, int k)
{
	if (*T == NULL)
		return -1;//空树无法删除

	BSTNode* p = BST_Search(*T, k);//查找当前元素
	BSTNode* parent = BST_SearchF((*T), k);//当前元素的父结点

	if (p == NULL)//没有该元素
		return -1;

	else if (p->lchild == NULL && p->rchild == NULL)//如果要删除叶子结点
	{
		if (parent == NULL)//如果只有一个结点
		{
			free(*T);
			*T = NULL;
		}
		else if (parent->lchild == p)//删除p
		{
			parent->lchild = NULL;
			free(p);
		}
		else
		{
			parent->rchild = NULL;
			free(p);
		}
		return 1;//删除成功
	}
	else if (p->lchild == NULL || p->rchild == NULL)//如果要删除单支结点(只有左孩子或者只有右孩子)
	{
		if (parent->lchild == p)//如果p为父结点的左孩子
		{
			if (p->lchild == NULL && p->rchild != NULL)//左孩子为空,右孩子不为空
			{
				parent->lchild = p->rchild;
				free(p);
				return 1;//删除成功
			}
			else if (p->lchild != NULL && p->rchild == NULL)//左孩子不为空,右孩子为空
			{
				parent->lchild = p->lchild;
				free(p);
				return 1;//删除成功
			}
		}
		if (parent->rchild == p)//如果p为父结点的右孩子
		{
			if (p->lchild == NULL && p->rchild != NULL)//左孩子为空,右孩子不为空
			{
				parent->rchild = p->rchild;
				free(p);
				return 1;//删除成功
			}
			else if (p->lchild != NULL && p->rchild == NULL)//左孩子不为空,右孩子为空
			{
				parent->rchild = p->lchild;
				free(p);
				return 1;//删除成功
			}
		}
	}
	else if (p->lchild != NULL && p->rchild != NULL)//如果要删除的结点有左右孩子
	{
		//查找要删除结点的直接后继(右孩子的第一个访问元素)
		BSTNode* q = p->rchild;
		while (q->lchild != NULL)
			q = q->lchild;
		p->key = q->key;

		//当前结点的直接后继的父结点
		BSTNode* currpar = BST_SearchF(*T, q->key);
		if (currpar->lchild == q)
		{
			if (q->rchild != NULL)
				currpar->lchild = q->rchild;
			else
				currpar->lchild = NULL;
			free(q);
		}
		else if (currpar->rchild == q)
		{
			if (q->rchild != NULL)
				currpar->rchild = q->rchild;
			else
				currpar->rchild = NULL;
			free(q);
		}
		return 1;//删除成功
	}
	return -1;//删除失败
}

main函数

cpp 复制代码
int main()
{
	//二叉树元素
	int arr[10] = { 60,58,98,45,65,24,37,49,86,82 };
	int len = sizeof(arr) / sizeof(arr[0]);//数组的长度
	//定义二叉树
	BSTree T;
	InitTree(&T);//初始化二叉树
	//构建二叉树
	Creat_BSTree(&T, arr,len);
	
	//查找二叉树结点(非递归算法)
	BSTNode * p = BST_Search(T,arr[9]);
	cout << "key = " << p->key << endl;//打印测试

	//删除二叉树结点
	Delete_BSTNode(&T, arr[9]);

	return 0;
}

查找效率分析:

1.若树高h,找到最下层的一个结点需要对比h次

2.最好情况:n个结点的二叉树最小高度为log2n + 1,平均查找长度为O(log2n)

3.最坏情况:每个结点只有一个分支,树高h=结点数n。则平均查找长度为O(n)

相关推荐
你撅嘴真丑6 小时前
第九章-数字三角形
算法
在路上看风景6 小时前
19. 成员初始化列表和初始化对象
c++
uesowys7 小时前
Apache Spark算法开发指导-One-vs-Rest classifier
人工智能·算法·spark
zmzb01037 小时前
C++课后习题训练记录Day98
开发语言·c++
ValhallaCoder7 小时前
hot100-二叉树I
数据结构·python·算法·二叉树
董董灿是个攻城狮7 小时前
AI 视觉连载1:像素
算法
念风零壹7 小时前
C++ 内存避坑指南:如何用移动语义和智能指针解决“深拷贝”与“内存泄漏”
c++
智驱力人工智能7 小时前
小区高空抛物AI实时预警方案 筑牢社区头顶安全的实践 高空抛物检测 高空抛物监控安装教程 高空抛物误报率优化方案 高空抛物监控案例分享
人工智能·深度学习·opencv·算法·安全·yolo·边缘计算
孞㐑¥8 小时前
算法——BFS
开发语言·c++·经验分享·笔记·算法
月挽清风8 小时前
代码随想录第十五天
数据结构·算法·leetcode