C++实现二叉排序树BSTree --插入删除摧毁查找等操作

C++数据结构-二叉排序树的查找、创建和删除 #include <iostream> #define TRUE 1 #define FALSE 0 using namespace std; typedef int Status; typedef struct BtNode { int data; //数据域 struct BtNode *lchild,*rchild; }BtNode,*BTree; //二叉... 阅读详情
一:二叉排序树定义

二叉排序树(Binary Sort Tree)又称二叉查找树(Binary Search Tree),亦称二叉搜索树。

二叉排序树是这样一棵树:
(1)若左子树不空,则左子树上所有结点的值均小于它的 根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;

(4)没有键值相等的结点。


二:删除算法(重点)
该树只有删除算法比较难,大概分为以下两种情况:
(1)删除最多只有一棵子树的结点
         此种情况,可用该节点的子树替代该节点的位置,如不存在子树,该节点为叶子结点,直接删除即可。
(2)删除存在两棵子树的节点
         有两种解决方案,如下图:
我们发现有两种解决方案:
    I.用该节点的右子树的最左边一个叶子结点的值覆盖掉要删除的节点的值,由于该改动不会违背二叉排序树的根大于左,根小于右的性质,只需要将该叶子节点删除即可。
    ii.用该节点的左子树的最右边一个叶子结点的值覆盖掉要删除的节点的值,同样删除该叶子节点即可。
不难发现,不论采用哪种方案,用来替换的节点正是要删除节点中序遍历的直接前驱或直接后继,这才导致了替换后整个二叉排序树依然是有序的,这种方案能够有效提高效率。

二:二叉排序树实现代码
#ifndef _BSTREE_H
#define _BSTREE_H

#include <iostream>
#include <assert.h>
using namespace std;

template <typename T>
class BSTree;

template <typename T>
class TreeNode{
	friend class BSTree<T>;
public:
	TreeNode() : m_data(T()), leftChild(NULL), rightChild(NULL)
	{}
	TreeNode(T data, TreeNode<T> *left = NULL, TreeNode<T> *right = NULL)
			: m_data(data), leftChild(left), rightChild(right)
	{}
	~TreeNode() = default;
private:
	T m_data;
	TreeNode<T> *leftChild;
	TreeNode<T> *rightChild;
};

template <typename T>
class BSTree{
	typedef TreeNode<T> node_type;
public:
	BSTree() :root(NULL)
	{}
	~BSTree();
public:
	BSTree<T>& operator=(const BSTree<T>&);

	void insert_elem(const T&);
	bool remove_elem(const T&);
	void inorder_traverse()const;

	T find_max()const;
	T find_min()const;
	node_type *search_elem(const T&)const;
protected:
	node_type *copy_tree(node_type *);

	void insert_elem(node_type *&, const T&);
	bool remove_elem(node_type *&, const T&);
	void inorder_traverse(node_type *)const;
	void destroy_tree(node_type *&);

	T find_max(node_type *)const;
	T find_min(node_type *)const;
	node_type *search_elem(node_type *, const T&)const;
private:
	node_type *root;
};

//public interface 

template <typename T>
BSTree<T>& BSTree<T>::operator=(const BSTree<T>& bst)
{
	if(this != &bst){
		root = copy_tree(bst.root);
	}
	return *this;
}

template <typename T>
BSTree<T>::~BSTree()
{
	destroy_tree(root);
}

template <typename T>
void BSTree<T>::insert_elem(const T& val)
{
	insert_elem(root, val);
}

template <typename T>
bool BSTree<T>::remove_elem(const T& val)
{
	remove_elem(root, val);
}

template <typename T>
void BSTree<T>::inorder_traverse()const
{
	inorder_traverse(root);
}

template <typename T>
T BSTree<T>::find_max()const
{
	return find_max(root);
}

template <typename T>
T BSTree<T>::find_min()const
{
	return find_min(root);
}

template <typename T>
TreeNode<T>* BSTree<T>::search_elem(const T& target)const
{
	search_elem(root, target);
}

//protected interface

template <typename T>
TreeNode<T>* BSTree<T>::copy_tree(node_type *t)
{
	node_type *tmp;
	if(t != NULL){
		tmp = new node_type(t->m_data);
		tmp->leftChild = copy_tree(t->leftChild);  //不能用tmp = copy_tree(t->leftChild)这样会导致新生成二叉树只挂有一个根节点
		tmp->rightChild = copy_tree(t->rightChild);
	}
	return tmp;
}

template <typename T>
void BSTree<T>::insert_elem(node_type *&t, const T& val)
{
	if(t == NULL){
		t = new node_type(val);
		return ;
	}
	
	if(t->m_data > val)
		insert_elem(t->leftChild, val);
	else if(t->m_data < val)
		insert_elem(t->rightChild, val);
	else 
		return ;
}

template <typename T>
void BSTree<T>::inorder_traverse(node_type *t)const
{	
	if(t != NULL){
		inorder_traverse(t->leftChild);
		cout << t->m_data << " ";
		inorder_traverse(t->rightChild);
	}
}

template <typename T>
bool BSTree<T>::remove_elem(node_type *&t, const T& val)
{
	if(t == NULL)
		return false;

	if(t->m_data > val)
		remove_elem(t->leftChild, val);
	else if(t->m_data < val)
		remove_elem(t->rightChild, val);
	else{
		if(t->leftChild != NULL && t->rightChild != NULL){
			node_type *tmp = t;
			tmp = t->rightChild;
			while(tmp->leftChild != NULL)
				tmp = tmp->leftChild; //选择右子树的最左边叶子结点替换方式
			t->m_data = tmp->m_data;
			remove_elem(t->rightChild, t->m_data);
			//delete tmp;           //error,此处不能直接delete,否则只能释放该节点,但该节点仍旧链接在二叉树上,需通过t指针释放并更改二叉树,另外一个原因是如果tmp元素有一个孩子,Remove递归会调用删除有一个孩子节点的情况,下面的else。例:上面图中38元素若存在一个右孩子39元素,就属于此类情况
		}
		else{
			node_type *tmp = t;
			if(t->leftChild != NULL)
				t = t->leftChild;
			else 
				t = t->rightChild;
			delete tmp;
		}
		return true;
	}
}

template <typename T>
void BSTree<T>::destroy_tree(node_type *&t)
{
	if(t != NULL){
		destroy_tree(t->rightChild);
		destroy_tree(t->leftChild);
		delete t;
	}
}

template <typename T>
T BSTree<T>::find_max(node_type *t)const
{
	while(t->leftChild != NULL)
		t = t->leftChild;
	return t->m_data;
}

template <typename T>
T BSTree<T>::find_min(node_type *t)const
{
	while(t->rightChild != NULL)
		t = t->rightChild;
	return t->m_data;
}

template <typename T>
TreeNode<T>* BSTree<T>::search_elem(node_type *t, const T& target)const
{
	if(t == NULL)
		return NULL;	
	else if(t->m_data > target)
		search_elem(t->leftChild, target);
	else if(t->m_data < target)
		search_elem(t->rightChild, target);
	else
		return t;
}

#endif /*BSTree.h*/

三:测试代码

测试代码如下:

#include "BSTree.h"

int main()
{
	int array[] = {32, 43, 1, 76, 54, 13, 42, 18, 139, 4};
	BSTree<int> bst;

	int len = sizeof(array) / sizeof (int);
	for(int i=0; i<len; ++i){
		bst.insert_elem(array[i]);
	}

	bst.inorder_traverse();
	cout << endl;	

	cout << bst.find_max() << endl;
	cout << bst.find_min() << endl;
	
	cout << bst.search_elem(139) << endl;

	bst.remove_elem(32);
	bst.inorder_traverse();
	cout << endl;

	BSTree<int> bst_;
	bst_ = bst;
	bst_.inorder_traverse();
	cout << endl;

	return 0;
}
测试结果如图:




全球最大光伏电池缺陷异常检测数据集PVELAD【发布】 下载地址 1:GitHub - binyisu/PVEL-AD 下载地址 2:http://aihebut.com/col.jsp?id=118 下载地址 3:NAVEDownload 竞赛测试系统:Photovoltaic cell anomaly detection | Kaggle 一、简介 PVEL-AD 数据集又叫做EL2021数据集是用于对光伏电池异常缺陷检测方法进行基准测试的数据集,重点是光伏电池工业检测。PVEL-AD包含 36,543 张具有各种内部缺陷和异构背... 阅读详情

相关推荐

隐语第四课:快速上手-SecretFlow的安装和部署

隐语课程,继续学习隐私计算技术

weixin_41467180的博客 2509

二叉排序树的删除算法

关于二叉排序树的定义以及如何查找指定关键字的结点不再赘述,本篇文章主要讨论二叉排序树如何删除一个指定的结点。

qq_43152622的博客 3805

本地化搭建DeepSeek+RAGFlow,构建个人知识库

本地化搭建DeepSeek+RAGFlow,构建个人知识库。至少32G以上内存、500G以上空余磁盘空间。

gogospecter的专栏 7428

二叉排序树,建立,查找,删除等操作

/*输入互不相同的一组整数,构造一棵二叉排序树,要求: ① 按递减有序的顺序输出; ② 输入一个整数,查找该整数是否在该二叉排序树中,查找成功返回1,否则返回0; ③ 在②中,若查找成功,则将该结点从二叉排序树中删除。*/ #include #include typedef struct{ int key; }ElemType; typedef struct BiTNode{ ElemTyp

优快云_buyi的博客 1220

【Azure 架构师学习笔记】- Azure Databricks (1) - 环境搭建

Databricks 已经成为了数据科学的必备工具,今时今日你已经很难抛开它来谈大数据,它常用于做复杂的ETL中的T, 数据分析,数据挖掘等,特别适用于做数据建模,机器学习等。那么顺应时代,现在也来看看这个工具的内容。首先要有一个环境,基于Azure 的Databricks简称ADB。托管在Azure 上的Databricks已经被Azure进行了很大的优化, 在搭建时只需要简单的几步即可拥有一个环境,不过要提醒一句ADB的集群并不便宜,用完马上删掉或停止, 否则一晚过百美金就会烧掉。

MVP黄钊吉(發糞塗牆) 2298

Unity 游戏实例开发集合 之 Car Racing 2D (2D赛车) 休闲小游戏快速实现

Unity 游戏实例开发集合 之 Car Racing 2D (2D赛车) 休闲小游戏快速实现 目录 Unity 游戏实例开发集合 之 Car Racing 2D (2D赛车) 休闲小游戏快速实现 一、简单介绍 二、Car Racing 2D (2D赛车) 游戏内容与操作 三、相关说明 四、游戏代码框架 五、知识点 六、游戏效果预览 七、实现步骤 八、工程源码地址 九、延伸扩展 一、简单介绍 Unity 游戏实例开发集合,使用简单易懂的方式,讲解常见游戏的开发实现过程,方便

仙魁XAN 7702

二叉排序树建立及前中后序遍历

题目描述 输入一系列整数,建立二叉排序树,并进行前序,中序,后序遍历。 输入描述: 输入第一行包括一个整数n(1&lt;=n&lt;=100)。 接下来的一行包括n个整数。 输出描述: 可能有多组测试数据,对于每组数据,将题目所给数据建立一个二叉排序树,并对二叉排序树进行前序、中序和后序遍历。 每种遍历结果输出一行。每行最后一个数据之后有一个空格。 输入中可能有重复元素,但是输出的...

Xiao_Chen_L的博客 1163

基于Simulink的占空比调制DTC降低转矩脉动

修改传统SVPWM模块,输入占空比d和有效矢量索引,计算Ton​=d∗Tc​、Toff​=(1−d)∗Tc​,生成对称PWM波形(替代开关表直接输出)。:低速时(n<500rpm)减小dmax​=0.6(避免磁链畸变),高速时(n>2000rpm)增大dmax​=0.8(提升动态响应);kT​/kψ​:转矩/磁链误差增益(需整定,如kT​=0.02/(N⋅m),kψ​=0.1/Wb);(θ为电压矢量与磁链夹角)。② SVM-DTC(占空比计算模块启用,d0​=0.5,kT​=0.02,kψ​=0.1)。

amy_mhd的博客 87

C语言实现 二叉排序树 的插入、删除、查找(详细图解)

1 二叉排序树: 如果它的左子树不为空,那么左子树上所有节点的值均小于它的根节点的值 如果它的右子树不为空,那么右子树上所有节点的值均大于它的根节点的值 根节点的左子树和右子树均是二叉排序树 (二叉排序树可能退化为链表,所以有平衡二叉树的概念) ...

jakercl的博客 1万+

结构力学本构模型:复合材料模型:复合材料热力学行为技术教程_2024-08-07_06-54-53.Tex

热塑性复合材料是一种由热塑性树脂基体和增强纤维组成的复合材料。与热固性复合材料不同,热塑性复合材料在加热时可以软化,冷却时硬化,这一过程可以重复进行,因此它们具有可回收和可再加工的特性。热塑性树脂,如聚酰胺(尼龙)、聚碳酸酯、聚醚醚酮(PEEK)等,与碳纤维、玻璃纤维等增强材料结合,可以制备出具有高强度、高刚度和良好耐热性的复合材料。热粘弹性理论是研究材料在温度变化和时间依赖性载荷作用下的变形和应力响应。复合材料,由于其独特的微观结构,展现出复杂的热粘弹性行为。

808

ARM与PC共享文件方式【samba】移植与配置

方式推荐指数适用平台优点缺点⭐⭐⭐⭐⭐全平台 (Win/Mac/Linux)兼容性最强,操作像本地文件配置稍繁琐,协议开销略大NFS⭐⭐⭐⭐Linux/Mac (Win支持一般)速度极快,CPU占用低Windows配置复杂,权限管理较难SFTP (SSH)⭐⭐⭐⭐全平台 (需客户端)安全加密,无需额外配置服务需使用FileZilla/Xftp等专用软件物理U盘⭐⭐⭐全平台无需网络,速度取决于接口需要人工插拔,不适合自动化Syncthing⭐⭐⭐⭐全平台自动同步,支持远程。

浩瀚之水的专栏 263

二叉排序树整理(创建,插入,查找,删除)

二叉排序树 查找表分为静态查找表和动态查找表,其中动态查找表的含义就是表结构本身是在查找过程中动态生成的。即若表中存在其关键字等于给定值keykeykey的记录,表明查找成功,否则插入关键字等于keykeykey的记录。 ​而动态查找表中最为典型的就是二叉排序树和哈希表,接下来重点对于二叉排序树的内容进行学习。 文章目录二叉排序树二叉排序树-定义二叉排序树-查找二叉排序树-插入二叉排序树-建立二叉排序树-遍历二叉排序树-删除二叉排序树-性能分析 二叉排序树-定义 ​ 空树或者是具有如下特性的二叉树被称为二叉

weixin_44267007的博客 9072

EPLAN中2D安装板的绘制方法示例

EPLAN中2D安装板的绘制方法示例

Robot_PLC_HMI_Automation 3221

算法其实很简单—二叉排序树的构建

1.什么是二叉排序树 二叉排序树(Binary Sort Tree),又称二叉查找树(Binary Search Tree),亦称二叉搜索树。是数据结构中的一类。在一般情况下,查询效率比链表结构要高。 二叉排序树特点: (1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值; (2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值; (3)左、右子树也分别为二叉排序树; (4)没有键值相等的结点。 简单说,就是每个父节点大于当前节点的左子节点,小于当前节点的右子节点。 2.构

我愿随风而行 的博客 2753

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

二叉排序树的CURD

什么是二叉排序树? 二叉排序树(Binary Search Tree)又称二叉查找树,是一种高效的数据结构。它是满足以下性质的特殊二叉树。        1.若他的左子树不空,则左子树上的所有节点值均小于根节点的值;        2.若它的右子树不为空,则右子树上所有节点的值均大于根节点的值;        3.它的左右子树都分别是二叉排序数   我们可以看出,其实二叉排序树的定义是...

sdp1103285470的博客 319

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

数据结构实验9----二叉排序树

二叉排序树。任意给定一组数据,设计一个算法,建立一棵二叉排序树,对它进行查找、插入、删除操作。

qq_60737285的博客 1390

顺序数组,二叉链表创建二叉排序树,及遍历方法(数据结构c++)

对于任意节点,它的左子树上的所有节点的值都小于该节点的值;对于任意节点,它的右子树上的所有节点的值都大于该节点的值;左、右子树都是二叉排序树。这个性质保证了二叉排序树的中序遍历是有序的,因此也被称为二叉查找树。二叉排序树可以进行高效的查找、插入、删除操作,时间复杂度为O(log n)。

weixin_73748464的博客 2253

二叉排序树删除某一指定结点

二叉排序树中删除一个结点对其祖先是没有影响的,但是对其子孙有影响.先回顾下二叉排序树的定义: 空树是二叉排序树; 左子树所有结点的值小于根节点,右子树所有结点的值大于根节点,递归定义. 设删除的那个结点为root,那么就要在左子树中找一个最大的结点来替换root或者在右子树中找一个最小的结点来替换root看图:这是一颗二叉排序树,我们删除73这个结点,就会得到下面这张图:可以看到

FlushHip 6766

二叉排序树的建立、查找和删除

1.二叉排序树的概念: 二叉排序树是一种动态树表. 二叉排序树的定义:二叉排序树或者是一颗空树,或者是一颗具有如下性质的二叉树: 若它的左子树非空,则左子树上的所有的节点的值均小于根节点的值. 若它的右子树非空, 则右子树上的所有节点的值均大于根节点的值. 左右子树本身又各是一颗二叉排序树,二叉排序树的性质:按中序遍历二叉排序树,得到的中序遍历是一个递增有序序列.

杨龙飞的博客 2009

二叉树的建立,删除,查找,插入,输出(数据结构)

1. 建立二叉树 void pre_crt(tree &bt)//按先序顺序输入二叉树中节点的值,生成 { char ch; ch=getchar();//二叉树的单链表存储结构,bt为指向根节点的指针,,'$'表示空树 if(ch!='$') { bt=new node;//建根节点 bt->data=ch; pre_crt(bt->lchild); p

yanyanwenmeng的博客 1915

二叉排序树(二叉链表实现)

二叉排序树(二叉查找树)的定义: 二叉排序树或者是一棵空树,或者是一棵具有以下性质的二叉树: (1)若它的左子树不为空,则左子树上所有结点的值均小于根结点的值; (2)若它的又子树 不为空,则右子树上所有结点的值均大于根结点的值; (3)它的左、右子树都是二叉排序树。 二叉排序树的定义是递归的。由此可得到二叉排序树的一个重要性质:中序遍历一棵二叉排序树可得到有序递增序列。 二叉排序树结点数据结构的定义(包括关键字项和其他数据项): //每个结点数据域的数据类型 typedef struct

千言万语ROOM 5229

二叉树(排序树)的创建、遍历、插入、删除以及查找

二叉树(排序树)的创建、遍历、插入、删除以及查找 原理:二叉树的先序创建(递归)按先序遍历的顺序,依次 输入结点的信息建成立二叉链表的算法。该算法的基本思想是:首先对一般的二叉树添加若干个虚结点,使每一个节点都有左右两个孩子,然后依次输入结点信息。若输入的结不是虚结点,则建立一个新结点;先序创建左子树;先序创建右子树 在这里插入代码片 ...

weixin_43126491的博客 3761

实现二叉排序树的基本运算算法

二叉排序树或者是一棵空树;或者是具有下列性质的二叉树: 1、若左子树不空,则左子树上所有结点的值均小于它的根结点的值 2、若右子树不空,则右子树上所有结点的值均大于它的根结点的值 3、左、右子树也分别为二叉排序树 /** *    实验题目: *        实现二叉排序树的基本运算算法 *    实验目的: *        领会二叉排序树的定义、创建、查找和删除过程及其算法设计 *    ...

xiezhi123456的博客 6205

二叉搜索树(二叉排序树)及其基本操作(查找,插入,删除)C++代码表示(含递归与非递归)看完别告诉我你还不会!

前言 查找问题: 静态查找:我们要找的元素是不动的,我们要做的只有 find 操作,没有 delete 和 insert 操作 动态查找:我们要找的集合会发生动态的变化,不仅有 find 操作,还有delete、find操作 针对静态问题,除了O(n)的顺序查找,还有O(nlogn)的二分查找,为什么二分查找效率这么高,是因为我们事先对数据进行了有效的组织,变成有序化,这样我们可以形成一个叫做判定树的这样一种结构,把线性的查找过程,转化成在树上的查找过程,查找效率,就是树的高度,所以我们就想,能不能把数

chenyu-max 1622

C++数据结构:二叉排序树实现及相关操作

二叉排序树的插入删除等操作

lcadna的博客 225

C语言实现二叉排序树(二叉搜索树、二叉查找树)的插入与删除操作

可以这样理解,当我层层往下递,不断向下查找完成之后,就来到了递归出口,即ro==NULL,注意这里的ro指向的位置正是我们应该把k插入的位置。当k < ro -> data时,就在以ro的左子树为根的树中插入k,插入完成后将函数返回值赋值给ro->left,这样就能在最后两层递归调用时,将k所在节点s插入到合适位置。以该函数为例,“递”表现在不断查找所要插入的位置,直到满足递归出口的条件,之后开始“归”,即层层向上返,这里是返回指向一棵树的指针,可以理解为将树或者节点返回给上一层的递归调用。

2301_79595688的博客 1877

[pta]6-8 二叉排序树查找操作

本题要求实现二叉排序树的查找操作。 其中BSTree结构定义如下: 裁判测试程序样例: 输入样例: 输入第一行以-1结束的整数,为二叉排序树中元素初始序列,第二行为一个整数n,代表要查询的元素个数,第三行为n个整数,代表要查询的元素值。 例如创建如下二叉排序树,输入为: 输出样例: 参考代码:

wzj05467的博客 1953
上一篇: Valgrind内存泄漏工具的安装与使用 -- Linux
下一篇: AVL树插入删除算法详解(有图) -- C++语言实现
FreeeLinux
博客等级 码龄11年 421粉丝 356原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值