当前位置: 首页 > article >正文

C++:搜索二叉树

文章目录

    • 一、二叉搜索树的概念
    • 二、二叉搜索树的性能分析
    • 三、二叉搜索树的插入
    • 四、二叉搜索树的查找
    • 五、二叉搜索树的删除
    • 六、二叉搜索树的代码实现

一、二叉搜索树的概念

它如果不是一颗空树,那么就要具有以下的性质:

  • 若它的左子树不为空,则左子树上所有结点的值都小于等于根结点的值
  • 若它的右子树不为空,则右子树上所有结点的值都大于等于根结点的值
  • 它的左右子树也都满足二叉搜索树的性质

功能用来:查找,其次中序遍历可是完成排序。
类似二分查找,但二分查找有缺陷:
1、要求有序
2、底层结构要求是数组,头部或中间插入删除数据效率很低

二、二叉搜索树的性能分析

在这里插入图片描述
在这里插入图片描述

三、二叉搜索树的插入

插入过程:
1、树为空,则直接新增结点,赋值给root指针
2、树不空,按二叉搜索树性质,插入值比当前节点大往右走,插入值比当前结点小往左走,找到空位置,插入新结点。
3、如果⽀持插⼊相等的值,插⼊值跟当前结点相等的值可以往右⾛,也可以往左⾛,找到空位置,插⼊新结点。(要注意的是要保持逻辑⼀致性,插⼊相等的值不要⼀会往右⾛,⼀会往左⾛)

四、二叉搜索树的查找

  1. 从根开始⽐较,查找x,x⽐根的值⼤则往右边⾛查找,x⽐根值⼩则往左边⾛查找。
  2. 最多查找⾼度次,⾛到到空,还没找到,这个值不存在。
  3. 如果不⽀持插⼊相等的值,找到x即可返回
  4. 如果⽀持插⼊相等的值,意味着有多个x存在,⼀般要求查找中序的第⼀个x。如下图,查找3,要找到1的右孩⼦的那个3返回

在这里插入图片描述

五、二叉搜索树的删除

首先查找要删除的元素是否存在二叉搜索树中,如果不存在,则返回false。
如果查找元素存在则分以下四种情况分别处理:(假设要删除的结点为N)
1、要删除结点N左右孩子均为空
2、要删除的结点N左孩子为空,右孩子结点不为空
3、要删除的结点N右孩子为空,左孩子结点不为空
4、要删除的结点N左右孩子结点均为空
对应以上四种情况的解决方案:
1、把N结点的父亲对应孩子指针指向空,直接删除N结点(情况1可以当成情况2或者3处理,效果是一样的)
2、把N结点的父亲对应孩子指针指向N的右孩子,直接删除N结点
3、把N结点的父亲对应孩子指针指向N的左孩子,直接删除N结点
4、无法直接删除N结点,因为N的两个孩子无处安放只能用替代法删除。找到N左子树的最大结点R(最右结点)或者N右子树的值最小结点R(最左结点)代替N,因为这两个结点任意一个放到N的位置,都满足二叉搜索树的规则。替代N的意思就是N和R这两个结点的值交换,转而变成删除R结点,R结点符合情况2或情况3,可以直接删除。

六、二叉搜索树的代码实现

#pragma once
#include <iostream>
#include <stdbool.h>

template<class K>
struct BSTNode
{
	K _key;
	BSTNode<K>* _left;
	BSTNode<K>* _right;

	BSTNode(const K& key)
		:_key(key)
		,_left(nullptr)
		,_right(nullptr)
	{

	}
};

template<class K>
class BSTree
{
	typedef BSTNode<K> Node;
public:
	bool Insert(const K& key)
	{
		if (_root == nullptr)
		{
			_root = new Node(key);
			return true;
		}
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				parent = cur;
				cur = cur->_left;
			}
		}
		cur = new Node(key);
		if (parent->_key >= key)
		{
			parent->_left = cur;
		}
		else
		{
			parent->_right = cur;
		}
		return true;
	}
	
	void Inorder()
	{
		Inorder(_root);
	}

	Node* find(const K& key)
	{
		Node* cur = _root;
		Node* ret = nullptr;
		while (cur)
		{
			if (cur->_key > key)
			{
				cur = cur->_left;
			}
			else if (cur->_key < key)
			{
				cur = cur->_right;
			}
			else
			{
				ret = cur;
				cur = cur->_left;
			}
		}
		return ret;
	}


	bool Ereas(const K& key)
	{
		Node* cur = _root;
		Node* ret = nullptr;
		Node* parent = nullptr;
		Node* retparent = nullptr;
		while (cur)
		{
			
			if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				ret = cur;
				retparent = parent;
				parent = cur;
				cur = cur->_left;
			}
		}

		if (ret == nullptr)
			return false;
		
		if (retparent != NULL)
		{
			if (ret->_left == nullptr)
			{
				if (retparent->_left == ret)
				{
					retparent->_left = ret->_right;
				}
				else
				{
					retparent->_right = ret->_right;
				}
				delete ret;
			}
			else if (ret->_right == nullptr)
			{
				if (retparent->_left == ret)
				{
					retparent->_left = ret->_left;
				}
				else
				{
					retparent->_right = ret->_left;
				}
				delete ret;

			}
			else
			{
				Node* minRight = ret->_right;
				Node* minRightParent = nullptr;
				while (minRight->_left)
				{
					minRightParent = minRight;
					minRight = minRight->_left;
				}
				if (minRightParent != nullptr)
				{
					ret->_key = minRight->_key;
					minRightParent->_left = minRight->_right;
					delete minRight;
				}
				else
				{
					ret->_key = minRight->_key;
					ret->_right = minRight->_right;
					delete minRight;
				}
			}
		}
		else
		{
			if (ret->_left == nullptr)
			{
				_root = ret->_right;
				delete ret;
			}
			else if (ret->_right == nullptr)
			{
				_root = ret->_left;
				delete ret;
			}
			else
			{
				Node* minRight = ret->_right;
				Node* minRightParent = nullptr;
				while (minRight->_left)
				{
					minRightParent = minRight;
					minRight = minRight->_left;
				}
				if (minRightParent != nullptr)
				{
					ret->_key = minRight->_key;
					minRightParent->_left = minRight->_right;
					delete minRight;
				}
				else
				{
					ret->_key = minRight->_key;
					ret->_right = minRight->_right;
					delete minRight;
				}
			}
		}

		return true;
	}
	 
private:

	void Inorder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
		Inorder(root->_left);
		std::cout << root->_key << " ";

		Inorder(root->_right);
	}
	Node* _root = nullptr;

};

http://www.kler.cn/a/390261.html

相关文章:

  • 使用Docker快速部署FastAPI Web应用
  • 【Golang】Channel的ring buffer实现
  • 蓝桥杯每日真题 - 第7天
  • docker镜像源,亲测可用,时间2024-11-14
  • Scala入门基础(17.1)Set集习题
  • 「Mac玩转仓颉内测版7」入门篇7 - Cangjie控制结构(下)
  • 第十七章 TCP 客户端 服务器通信 - 使用OPEN命令
  • 使用 VueJS 构建 VS Code 扩展
  • 【QT常用技术讲解】任务栏图标+socket网络服务+开机自启动
  • mysql数据库(四)单表查询
  • 【idea】idea2024版本创建项目时没有java 8的版本选择
  • TOEIC 词汇专题:科技硬件篇
  • 【AI新领域应用】AlphaFold 2,原子级别精度的蛋白质3D结构预测,李沐论文精读(2021Nature封面,2024诺贝尔奖)
  • Python——飞机大战
  • 如何在 FastReport VCL 中创建报告时使用样式
  • Springboot 使用EasyExcel导出含图片并设置样式的Excel文件
  • 第四十二章 Vue中使用mutations修改Vuex仓库数据
  • 【JAVA】-Springboot核心机制
  • 智能量化模型在大数据下的中阳策略发展
  • 基于Python的高校成绩分析管理系统
  • 计算机新手练级攻略——如何搜索问题
  • 软考知识备忘
  • 【Linux进程篇3】说白了,Linux创建进程(fork父子进程)也就那样!!!
  • MySQL基础篇总结
  • vue/react前端项目自定义js脚本实现自定义部署等操作
  • 高级java每日一道面试题-2024年11月01日-Redis篇-Redis支持的数据类型有哪些?