二叉搜索树的介绍、模拟实现二叉搜索树、leetcode---根据二叉树创建字符串、leetcode---二叉树的最近公共祖先等的介绍

news2024/9/29 6:36:46

文章目录

  • 前言
  • 一、二叉搜索树的介绍
  • 二、模拟实现二叉搜索树
  • 三、leetcode---根据二叉树创建字符串
  • 四、leetcode---二叉树的最近公共祖先
  • 总结


前言

二叉搜索树的介绍、模拟实现二叉搜索树、leetcode—根据二叉树创建字符串、leetcode—二叉树的最近公共祖先等的介绍


一、二叉搜索树的介绍

在这里插入图片描述

  • 如上图所示,搜索二叉树就是比当前节点大的存放在右子树,比当前节点小的存放在左子树中。

二、模拟实现二叉搜索树

#pragma once

template<class K>
struct BSTreeNode
{
	BSTreeNode(const K& key)
		: _left(nullptr)
		, _right(nullptr)
		, _key(key)
	{}

	BSTreeNode<K>* _left;
	BSTreeNode<K>* _right;
	K _key;
};


template <class K>
class BSTree
{
	typedef BSTreeNode<K> Node;
public:
	BSTree()
		:_root(nullptr)
	{}

	BSTree(const BSTree<K>& tree)
	{
		_root = copy(tree._root);
	}

	BSTree<K>& operator=(BSTree<K> tree)
	{
		swap(_root, tree._root);
		return *this;
	}

	~BSTree()
	{
		Destroy(_root);
	}

	bool Insert(const K& key)
	{
		if (_root == nullptr)
		{
			_root = new Node(key);
			return true;
		}

		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				return false;
			}


		}

		cur = new Node(key);
		if (parent->_key < key)
		{
			parent->_right = cur;
		}
		else
		{
			parent->_left = cur;
		}
	}


	bool Erase(const K& key)
	{
		Node* parent = nullptr;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else
			{
				// 找到了
				if (cur->_left == nullptr) // 找到的节点左树为空
				{
					if (cur == _root)
					{
						_root = _root->_right;
					}
					else
					{
						if (parent->_left == cur)
						{
							parent->_left = cur->_right;
						}
						else
						{
							parent->_right = cur->_right;
						}
					}


				}
				else if(cur->_right == nullptr) // 找到的节点右树为空
				{
					if (cur == _root)
					{
						_root = _root->_left;
					}
					else
					{
						if (parent->_left == cur)
						{
							parent->_left = cur->_left;
						}
						else
						{
							parent->_right = cur->_left;
						}
					}

					
				}
				else // 左右节点都不为空
				{
					// 找左子树的最大节点(最右)
					Node* parent = cur;
					Node* leftMax = cur->_left;
					while (leftMax->_right)
					{
						parent = leftMax;
						leftMax = leftMax->_right;
					}

					swap(leftMax->_key, cur->_key);

					if (parent->_left == leftMax)
					{
						parent->_left = leftMax->_left;
					}
					else
					{
						parent->_right = leftMax->_left;
					}

					cur = leftMax;
				}
				delete cur;
				cur = nullptr;
				return true;
			}
		}
		return false;
	}

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

	void InOrder()
	{
		_InOrder(_root);
		cout << endl;
	}

	// 递归插入
	bool InsertR(const K& key)
	{
		return _InsertR(_root, key);
	}

	// 递归删除
	bool EraseR(const K& key)
	{
		return _EraseR(_root, key);
	}

	Node* findR(const K& key)
	{
		return _findR(_root, key);
	}




	
private:

	// 递归查找
	Node* _findR(Node* root, const K& key)
	{
		if (root == nullptr)
		{
			return nullptr;
		}

		if (root->_key < key)
		{
			_findR(root->_right, key);
		}
		else if (root->_key > key)
		{
			_findR(root->_left, key);
		}
		else
		{
			return root;
		}
	}


	// copy	
	Node* copy(Node* root)
	{
		if (root == nullptr)
		{
			return nullptr;
		}

		Node* copyroot = new Node(root->_key);
		copyroot->_left = copy(root->_left);
		copyroot->_right = copy(root->_right);
		return copyroot;
	}

	// 递归析构
	void Destroy(Node*& root)
	{
		if (root == nullptr)
		{
			return;
		}
		Destroy(root->_left);
		Destroy(root->_right);
		delete root;
		root = nullptr;
	}

	// 递归版本删除
	bool _EraseR(Node*& root, const K& key)
	{
		if (root == nullptr)
		{
			return false;
		}

		if (root->_key < key)
		{
			_EraseR(root->_right, key);
		}
		else if (root->_key > key)
		{
			_EraseR(root->_left, key);
		}
		else
		{
			Node* del = root;
			if (root->_left == nullptr)
			{
				root = root->_right;
			}
			else if (root->_right == nullptr)
			{
				root = root->_left;
			}
			else
			{
				Node* leftMax = root->_left;
				while (leftMax->_right)
				{
					leftMax = leftMax->_right;
				}

				swap(leftMax->_key, root->_key);

				return _EraseR(root->_left, key);

			}

			delete del;
			return true;
		}
	}

	// 递归版本插入数据
	bool _InsertR(Node*& root, const K& key)
	{
		if (root == nullptr)
		{
			root = new Node(key);
			return true;
		}
		if (root->_key < key)
		{
			_InsertR(root->_right, key);
		}
		else if(root->_key > key)
		{
			_InsertR(root->_left, key);
		}
		else
		{
			return false;
		}
	}
	void _InOrder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}

		_InOrder(root->_left);
		cout << root->_key << " ";
		_InOrder(root->_right);

	}


	Node* _root;
};

测试:

#include <iostream>
using namespace std;

#include "BinarySearchTree.h"

void test1()
{
	BSTree<int> t;

	int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };

	for (auto e : a)
	{
		t.Insert(e);
	}

	t.InOrder();

	t.Erase(8);
	t.InOrder();
	t.Erase(4);
	t.InOrder();
	t.Erase(6);
	t.InOrder();
	t.Erase(7);
	t.InOrder();
}

void test2()
{
	BSTree<int> t;

	int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };
	
	for (auto e : a)
	{
		t.InsertR(e);
	}

	t.InOrder();

	t.EraseR(8);
	t.InOrder();
	t.EraseR(4);
	t.InOrder();
	t.EraseR(6);
	t.InOrder();
	t.EraseR(7);
	t.InOrder();
}

void test3()
{
	BSTree<int> t;

	int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };

	for (auto e : a)
	{
		t.InsertR(e);
	}

	t.InOrder();

	BSTree<int> t1(t);
	t1.InOrder();

	BSTree<int> t2;

	t2 = t1;
	t2.InOrder();

}


void test4()
{
	BSTree<int> t;

	int a[] = { 8, 3, 1, 10, 6, 4, 7, 14, 13 };

	for (auto e : a)
	{
		t.InsertR(e);
	}

	t.InOrder();

	cout << t.find(10) << endl;
	cout << t.findR(100) << endl;

}
int main()
{
	test1();
	test2();
	test3();
	test4();
	
	return 0;
}

在这里插入图片描述

三、leetcode—根据二叉树创建字符串

leetcode—根据二叉树创建字符串

在这里插入图片描述

class Solution {
public:
    string tree2str(TreeNode* root) {
        if(root == nullptr)
        {
            return "";
        }
        string str;

        str += to_string(root->val);
        if(root->left || root->right)
        {
            str += '(';
            str += tree2str(root->left);
            str += ')';
        }

        if(root->right)
        {
            str += '(';
            str += tree2str(root->right);
            str += ')';
        }

        return str;

    }
};

四、leetcode—二叉树的最近公共祖先

leetcode—二叉树的最近公共祖先

在这里插入图片描述

class Solution {
public:
    bool Find(TreeNode* root, TreeNode* x)
    {
        if(root == nullptr)
        {
            return false;
        }

        return root == x || Find(root->left,x) || Find(root->right, x);
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        
        if(root == nullptr)
        {
            return nullptr;
        }

        if(root == p || root == q)
        {
            return root;
        }

        bool pInLeft, pInRight, qInLeft, qInRight;

        pInLeft = Find(root->left, p);
        pInRight = !pInLeft;

        qInLeft = Find(root->left, q);
        qInRight = !qInLeft;


        if(pInLeft && qInLeft)
        {
            return lowestCommonAncestor(root->left, p, q); 
        }
        else if(pInRight && qInRight)
        {
            return lowestCommonAncestor(root->right, p, q); 
        }
        else
        {
          return root;
        } 
    }
};

总结

二叉搜索树的介绍、模拟实现二叉搜索树、leetcode—根据二叉树创建字符串、leetcode—二叉树的最近公共祖先等的介绍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2176076.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

57 长短期记忆网络(LSTM)_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录长短期记忆网络&#xff08;LSTM&#xff09;门控记忆元输入门、忘记门和输出门候选记忆元 (相当于RNN中计算 H t H_t Ht​)记忆元隐状态 从零开始实现初始化模型参数定义模型训练和预测 简洁实现小结练习 长短期记忆网络&#xff08;LSTM&a…

0基础学习CSS(六)字体

CSS 字体 CSS字体属性定义字体&#xff0c;加粗&#xff0c;大小&#xff0c;文字样式。 serif和sans-serif字体之间的区别 在计算机屏幕上&#xff0c;sans-serif字体被认为是比serif字体容易阅读 CSS字型 在CSS中&#xff0c;有两种类型的字体系列名称&#xff1a; 通用字体…

Java | Leetcode Java题解之第443题压缩字符串

题目&#xff1a; 题解&#xff1a; class Solution {public int compress(char[] chars) {int n chars.length;int write 0, left 0;for (int read 0; read < n; read) {if (read n - 1 || chars[read] ! chars[read 1]) {chars[write] chars[read];int num read …

解读文本嵌入:语义表达的练习

【引子】近来在探索并优化AIPC的软件架构&#xff0c;AI产品经理关于语义搜索的讨论给了自己较多的触动&#xff0c;于是重新梳理嵌入与语义的关系&#xff0c;遂成此文。 文本转换成机器可理解格式的最早版本之一是 ASCII码&#xff0c;这种方法有助于渲染和传输文本&#xff…

win10系统K8S安装教程

准备工作 电脑硬件&#xff1a;支持虚拟化的CPU&#xff0c;内存最好在32G以上&#xff0c;16G也可以操作系统&#xff1a;window10 专业版 1 开启虚拟化 1.1 BIOS 由于主板和CPU的品牌不太一样&#xff0c;这里的操作仅供参考&#xff0c;以Intel的平台为例&#xff1a; …

【刷点笔试面试题试试水】有符号变量与无符号变量的值的转换

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: 注意无符号类型与有符合类型参与计算会做类型提升,有符合的变为无符号…

加法器以及标志位

加法器的结构&#xff1a; OF&#xff08;溢出标志位&#xff09;&#xff0c;SF&#xff08;符号标志位&#xff09;&#xff0c;ZF&#xff08;0标志位&#xff09;&#xff0c;ZF&#xff08;进位/借位标志位&#xff09; 有符号数看标志位&#xff1a;OF&#xff0c;SF 无符…

ubuntu 不用每次输入sudo的四种方式

在Ubuntu系统中&#xff0c;如果不希望每次执行需要管理员权限的命令时都输入sudo&#xff0c;有几种方法可以实现这一目标。以下是一些详细的方法&#xff1a; 第一种方式: 切换root用户 (如果你有足够的权限) # 修改root密码命令(没有设置的用户需要设置一下) consolaadmin…

面试中顺序表常考的十大题目解析

在数据结构与算法的面试中&#xff0c;顺序表是一个常见的考点。它作为一种基础的数据结构&#xff0c;涵盖了多种操作和概念&#xff0c;以下将详细介绍面试中关于顺序表常考的十大题目。 &#x1f49d;&#x1f49d;&#x1f49d;如果你对顺序表的概念与理解还存在疑惑&#…

【Threejs进阶教程-着色器篇】8. Shadertoy如何使用到Threejs-基础版

【Threejs进阶教程-着色器篇】8. Shadertoy如何使用到Threejs - 基础版 前七篇地址,建议按顺序学习致谢带我入门的[X01动力装甲]大佬本文适用范围怎么样在Shadertoy中画出正圆形shadertoy中的坐标系比例转换理解Shadertoy的fragCoord理解Shadertoy中的iResolution 转移Shaderto…

SigmaStudio淡入淡出增益控件(Single SW slew vol(adjustable))延时分析

斜率范围1~23&#xff0c;参考12khz正弦波&#xff08;-17.99db,调减15.2db&#xff09;作为分析依据 一、淡入时间与斜率关系 斜率1-----淡入延时时间大概0.08毫秒 斜率2—淡入延时时间大概0.2毫秒 斜率3–淡入延时时间按大概0.5毫秒 斜率4–淡入延时时间大概1毫秒 斜率5–淡…

C++学习笔记之结构体

C学习笔记之结构体 https://www.runoob.com/cplusplus/cpp-struct.html 结构体是C中一种由用户自定义的数据类型&#xff0c;允许存储不同类型的数据项 1、定义结构体 使用struct语句定义结构体 结构体与C中的类看起来结构相似&#xff0c;同样是可以在其中定义成员变量和成员…

picgo + typora + gitee图床

Picgo打造个人图床&#xff0c;稳定又安全 解决Typora笔记上传到CSDN图片无法显示的问题 typora中

完全二叉树的节点个数 C++ 简单问题

完全二叉树 的定义如下&#xff1a;在完全二叉树中&#xff0c;除了最底层节点可能没填满外&#xff0c;其余每层节点数都达到最大值&#xff0c;并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层&#xff0c;则该层包含 1~ 2h 个节点。 示例 1&#xff…

蓝桥杯—STM32G431RBT6(RTC时钟获取时间和日期)

一、RTC是什么&#xff0c;有什么用&#xff1f; 在 STM32 中&#xff0c;RTC&#xff08;Real-Time Clock&#xff0c;实时时钟&#xff09;主要有以下作用&#xff1a; 时间保持&#xff1a;即使在系统断电情况下&#xff0c;也能持续记录时间。&#xff08;需要纽扣电池供电…

解决银河麒麟V10密码过期无法登录的问题

解决银河麒麟V10密码过期无法登录的问题 1、问题描述2、 解决方法步骤一&#xff1a;更改密码步骤二&#xff1a;调整密码策略&#xff08;可选&#xff09; 3、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在使用银河麒麟桌面操作系…

Java:选择排序

目录 直接选择排序 堆排序 基本思想&#xff1a; 每一次从待排序的数据元素中选出最小(或最大)的一个元素&#xff0c;存放在序列的起始位置&#xff0c;直到全部待排序的数据元素排完。 直接选择排序 思路1&#xff1a; 在元素集合array[i]--array[n-1]中选择关键码最大(小…

【论文阅读】视觉里程计攻击

Adversary is on the Road: Attacks on Visual SLAM using Unnoticeable Adversarial Patch 一、视觉SLAM的不安全因素 根据论文的分析&#xff0c;视觉SLAM由于完全依赖于特征&#xff0c;缺少验证机制导致算法不安全。前端在受到干扰的情况下&#xff0c;会导致误匹配增加&…

算法工程师重生之第十八天(修剪二叉搜索树 将有序数组转换为二叉搜索树 把二叉搜索树转换为累加树 总结篇 )

参考文献 代码随想录 一、修剪二叉搜索树 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在[low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;如果没有被移除…

【Sentinel-2简介】

Sentinel-2简介 Sentinel-2是欧洲空间局&#xff08;European Space Agency, ESA&#xff09;全球环境和安全监视&#xff08;即哥白尼计划&#xff09;系列卫星的重要组成部分&#xff0c;由Sentinel-2A和Sentinel-2B两颗卫星组成。以下是关于Sentinel-2的详细介绍&#xff1…