【数据结构】二叉搜索树——二叉搜索树的概念和介绍、二叉搜索树的简单实现、二叉搜索树的增删查改

news2024/11/24 17:31:44

文章目录

  • 二叉搜索树
    • 1. 二叉搜索树的概念和介绍
    • 2. 二叉搜索树的简单实现
      • 2.1二叉搜索树的插入
      • 2.2二叉搜索树的查找
      • 2.3二叉搜索树的遍历
      • 2.4二叉搜索树的删除
      • 2.5完整代码和测试

二叉搜索树

1. 二叉搜索树的概念和介绍

  二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

  (1)若它的左子树不为空,则左子树上所有节点的值都小于根节点的值

  (2)若它的右子树不为空,则右子树上所有节点的值都大于根节点的值

  (3)它的左右子树也分别为二叉搜索树

在这里插入图片描述

  二叉搜索树(Binary Search Tree)的每个节点包含三个属性:键(key)、左孩子(lchild)和右孩子(rchild)。 键用于存储节点的值,左孩子和右孩子分别指向左子树和右子树的根节点。

  二叉搜索树的结构类似于一个倒置的树,最底层的节点位于树的顶部,每个节点都有一个键值,并且每个节点的左子树上的所有节点的键值都小于该节点的键值,而右子树上的所有节点的键值都大于该节点的键值。这种结构使得二叉搜索树在处理有序数据时非常高效。

  基于以上性质,二叉搜索树在查找、插入和删除操作上具有较好的效率,时间复杂度为O(logn)。

  基于二叉搜索树的特殊结构,二叉搜索树的中序遍历(Inorder Traversal)按照左子树、根节点、右子树的顺序遍历二叉树,它会按照从大到小的顺序输出二叉树中的所有元素。

  以下这颗二叉搜索树的中序遍历结果:1 3 4 6 7 8 10 13 14
在这里插入图片描述
             

2. 二叉搜索树的简单实现

  和之前的二叉树实现类似,二叉搜索树的实现只需要在二叉树的实现基础上,将左右元素根据和根节点的大小,重新考虑排列顺序即可。

  定义二叉搜索树的节点:

//搜索二叉树创建节点
template<class K>
struct BSTreeNode
{
	//左右节点和节点值key
	BSTreeNode<K>* _left;
	BSTreeNode<K>* _right;
	K _key;

	//二叉树节点构造函数
	BSTreeNode(const K& key)
		:_left(nullptr)
		, _right(nullptr)
		, _key(key)
	{}
};

  定义二叉搜索树类:

//创建二叉搜索树
template<class K>
class BSTree
{
	//便于书写BNode节点
	typedef BSTreeNode<K> BNode;

public:
	//二叉搜索树构造函数
	BSTree()
		:_root(nullptr)
	{}

private:
	BNode* _root;
};

             

2.1二叉搜索树的插入

  二叉搜索树的插入过程可以分为以下步骤:

  (1)如果二叉搜索树为空,创建一个新的节点,并将待插入关键字放入新节点的数据域。将新节点作为根节点,左右子树均为空。

  (2)如果二叉搜索树非空,将待查找关键字与根节点关键字进行比较。如果小于根节点关键字,则将待查找关键字插入左子树中;如果大于根节点关键字,则将待查找关键字插入右子树中。

  重复上述步骤,直到找到合适的位置插入待插入的关键字。

  在插入过程中,需要保持二叉搜索树的性质:任意节点的左子树的所有节点的值都小于该节点的值,右子树的所有节点的值都大于该节点的值。如果插入后破坏了这种性质,需要进行调整。

在这里插入图片描述

  非递归的实现:

//二叉树插入节点
bool BSInsert(const K& key)
{
	//如果该树为空树,直接创建节点
	if (_root == nullptr)
	{
		_root = new BNode(key);
		return true;
	}
	
	//找到二叉树所在的节点
	BNode* parent = nullptr;
	BNode* 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 BNode(key);
	if (parent->_key > key)
	{
		parent->_left = cur;
	}
	else 
	{
		parent->_right = cur;
	}

	return true;
}


  递归的实现:

bool _BSInsertR(BNode*& root, const K& key)//这里传&,直接可以得到地址
{
	if (root == nullptr)
	{
		root = new BNode(key);
		return true;
	}

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

             

2.2二叉搜索树的查找

  二叉搜索树的查找实现过程可以分为以下步骤:

  (1)将待查找关键字与根节点关键字进行比较。如果相等,则找到了目标关键字,查找结束。

  (2)如果待查找关键字小于根节点关键字,则将待查找关键字放入左子树中继续查找。

  (3)如果待查找关键字大于根节点关键字,则将待查找关键字放入右子树中继续查找。

  重复上述步骤,直到找到目标关键字,或者搜索到了空节点(表示未找到目标关键字)。

  在查找过程中,由于二叉搜索树是基于二分的思想,所以每次比较都可以排除一半的搜索空间,因此时间复杂度为O(logn)。

在这里插入图片描述

  非递归实现:

//查找二叉树的节点
bool BSFind(const K& key)
{
	BNode* cur = _root;
	while (cur)
	{
		if (cur->_key > key)
		{
			cur = cur->_left;
		}
		else if (cur->_key < key)
		{
			cur = cur->_right;
		}
		else
		{
			return true;
		}
	}

	return false;
}

  递归实现:

bool _BSFindR(BNode* root, const K& key)
{
	if (root == nullptr)
	{
		return false;
	}

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

             

2.3二叉搜索树的遍历

  二叉搜索树常使用中序遍历,而不是前序遍历和后序遍历。

  因为中序遍历的特点是先访问左子树,然后访问根节点,最后访问右子树。 在访问左子树时,先访问左子树的左子树,再访问左子树的右子树;在访问右子树时,先访问右子树的左子树,再访问右子树的右子树。

  二叉搜索树中序遍历的结果是按照从小到大的顺序输出二叉搜索树中的所有元素。

  二叉搜索树的中序遍历过程可以分为以下步骤:

  (1)首先遍历左子树,访问左子树中的所有节点,并按照中序遍历的顺序递归地访问它们的右子树。

  (2)然后访问根节点。

  (3)最后遍历右子树,访问右子树中的所有节点,并按照中序遍历的顺序递归地访问它们的左子树。

  递归实现:

void _BSInOrder(BNode* root)
{
	if (root == nullptr)
	{
		return;
	}

	_BSInOrder(root->_left);
	printf("%d ", root->_key);
	_BSInOrder(root->_right);
}

             

2.4二叉搜索树的删除

  二叉搜索树的删除操作可以按照以下步骤实现:

  (1)首先,找到要删除的节点。可以通过中序遍历或者二分查找等方式找到要删除的节点。

  (2)如果要删除的节点是叶子节点(没有子节点),直接将该节点从二叉搜索树中删除即可。

  (3)如果要删除的节点只有一个子节点,将该节点的子节点与其父节点相连,删除该节点即可。

  (4)如果要删除的节点有两个子节点,需要找到该节点的左子树中的最大节点(或者右子树中的最小节点),用该节点代替要删除的节点的位置,然后删除该最小(或最大)节点。

  在实现删除操作时,需要注意保持二叉搜索树的性质,即任意节点的左子树的所有节点的值都小于该节点的值,右子树的所有节点的值都大于该节点的值。同时,删除操作可能会导致二叉搜索树的平衡被破坏,需要进行相应的调整操作。

  (1)当没有叶子结点,或者只有一个子节点的情况:
在这里插入图片描述

  (2)当左右都有子节点的情况:
在这里插入图片描述

  非递归实现:

//删除二叉树中的节点
bool BSErase(const K& key)
{
	BNode* cur = _root;
	BNode* parent = nullptr;
	//先要找到所删除的节点
	while (cur)
	{
		if (cur->_key > key)
		{
			parent = cur;
			cur = cur->_left;
		}
		else if (cur->_key < key)
		{
			parent = cur;
			cur = cur->_right;
		}
		else//找到了所要删除的节点
		{
			if (cur->_left == nullptr)//当左节点为空节点
			{
				if (cur == _root)//cur为根节点
				{
					_root = cur->_right;
				}
				else//cur不为空节点
				{
					if (parent->_right == cur)
					{
						parent->_right = cur->_right;
					}
					else
					{
						parent->_left = cur->_right;
					}
				}
			}
			else if(cur->_right==nullptr)//当右节点为空节点
			{
				if (cur == _root)//cur为空节点
				{
					_root = cur->_left;
				}
				else//cur不为空节点
				{
					if (parent->_right == cur)
					{
						parent->_right = cur->_left;
					}
					else
					{
						parent->_left = cur->_left;
					}
				}
			}
			else//当左右节点都不为空节点
			{
				//找代替节点
				BNode* parent = cur;
				BNode* leftMax = cur->_left;
				while (leftMax->_right)
				{
					parent = leftMax;
					leftMax = leftMax->_right;
				}

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

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

				cur=leftMax;
			}

			delete cur;
			return true;
		}
	}

	return false;
}

  递归实现:

bool _BSEraseR(BNode* &root, const K& key)
{
	if (root == nullptr)
	{
		return false;
	}

	if (root->_key < key)
	{
		_BSEraseR(root->_right, key);
	}
	else if (root->_key > key)
	{
		_BSEraseR(root->_left, key);
	}
	else
	{
		BNode* del = root;
		//1.左为空
		//2.右为空
		//3.左右都不为空
		if (root->_left == nullptr)
		{
			root = root->_right;
		}
		else if (root->_right == nullptr)
		{
			root = root->_left;
		}
		else
		{
			BNode* leftMax = root->_left;
			while (leftMax->_right)
			{
				leftMax = leftMax->_right;
			}

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

			return _BSEraseR(root->_left, key);
		}

		delete del;
		return true;
	}
}

             

2.5完整代码和测试

  完整代码:

#pragma once

//搜索二叉树创建节点
template<class K>
struct BSTreeNode
{
	//左右节点和节点值key
	BSTreeNode<K>* _left;
	BSTreeNode<K>* _right;
	K _key;

	//二叉树节点构造函数
	BSTreeNode(const K& key)
		:_left(nullptr)
		, _right(nullptr)
		, _key(key)
	{}
};

//创建搜索二叉树
template<class K>
class BSTree
{
	//便于书写BNode节点
	typedef BSTreeNode<K> BNode;

public:
	//搜索二叉树构造函数
	BSTree()
		:_root(nullptr)
	{}

	//二叉树插入节点
	bool BSInsert(const K& key)
	{
		//如果该树为空树,直接创建节点
		if (_root == nullptr)
		{
			_root = new BNode(key);
			return true;
		}
		
		//找到二叉树所在的节点
		BNode* parent = nullptr;
		BNode* 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 BNode(key);
		if (parent->_key > key)
		{
			parent->_left = cur;
		}
		else 
		{
			parent->_right = cur;
		}

		return true;
	}

	//查找二叉树的节点
	bool BSFind(const K& key)
	{
		BNode* cur = _root;
		while (cur)
		{
			if (cur->_key > key)
			{
				cur = cur->_left;
			}
			else if (cur->_key < key)
			{
				cur = cur->_right;
			}
			else
			{
				return true;
			}
		}

		return false;
	}

	//删除二叉树中的节点
	bool BSErase(const K& key)
	{
		BNode* cur = _root;
		BNode* parent = nullptr;
		//先要找到所删除的节点
		while (cur)
		{
			if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_key < key)
			{
				parent = cur;
				cur = cur->_right;
			}
			else//找到了所要删除的节点
			{
				if (cur->_left == nullptr)//当左节点为空节点
				{
					if (cur == _root)//cur为根节点
					{
						_root = cur->_right;
					}
					else//cur不为空节点
					{
						if (parent->_right == cur)
						{
							parent->_right = cur->_right;
						}
						else
						{
							parent->_left = cur->_right;
						}
					}
				}
				else if(cur->_right==nullptr)//当右节点为空节点
				{
					if (cur == _root)//cur为空节点
					{
						_root = cur->_left;
					}
					else//cur不为空节点
					{
						if (parent->_right == cur)
						{
							parent->_right = cur->_left;
						}
						else
						{
							parent->_left = cur->_left;
						}
					}
				}
				else//当左右节点都不为空节点
				{
					//找代替节点
					BNode* parent = cur;
					BNode* leftMax = cur->_left;
					while (leftMax->_right)
					{
						parent = leftMax;
						leftMax = leftMax->_right;
					}

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

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

					cur=leftMax;
				}

				delete cur;
				return true;
			}
		}

		return false;
	}

	//二叉树的中序遍历
	void BSInOrder()
	{
		_BSInOrder(_root);
		cout << endl;
	}

	//递归实现二叉树的查找
	bool BSFindR(const K& key)
	{
		return _BSFindR(_root, key);
	}

	//递归实现二叉树的插入节点
	bool BSInsertR(const K& key)
	{
		return _BSInsertR(_root, key);
	}

	//递归实现二叉树的删除节点
	bool BSEraseR(const K& key)
	{
		return _BSEraseR(_root, key);
	}

private:
	//递归二叉树删除的封装实现
	bool _BSEraseR(BNode* &root, const K& key)
	{
		if (root == nullptr)
		{
			return false;
		}

		if (root->_key < key)
		{
			_BSEraseR(root->_right, key);
		}
		else if (root->_key > key)
		{
			_BSEraseR(root->_left, key);
		}
		else
		{
			BNode* del = root;
			//1.左为空
			//2.右为空
			//3.左右都不为空
			if (root->_left == nullptr)
			{
				root = root->_right;
			}
			else if (root->_right == nullptr)
			{
				root = root->_left;
			}
			else
			{
				BNode* leftMax = root->_left;
				while (leftMax->_right)
				{
					leftMax = leftMax->_right;
				}

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

				return _BSEraseR(root->_left, key);
			}

			delete del;
			return true;
		}
	}

	//递归二叉树插入的封装实现
	bool _BSInsertR(BNode*& root, const K& key)//这里传&,直接可以得到地址
	{
		if (root == nullptr)
		{
			root = new BNode(key);
			return true;
		}

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

	//递归二叉树查找的封装实现
	bool _BSFindR(BNode* root, const K& key)
	{
		if (root == nullptr)
		{
			return false;
		}

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

	//为了递归实现,进行一层封装
	void _BSInOrder(BNode* root)
	{
		if (root == nullptr)
		{
			return;
		}

		_BSInOrder(root->_left);
		printf("%d ", root->_key);
		_BSInOrder(root->_right);
	}

private:
	BNode* _root;
};


  简单测试:

#define _CRT_SECURE_NO_WARNINGS 1

#include<iostream>
using namespace std;

#include"BinarySearchTree.h"

void BSTree_test1()
{
	BSTree<int> t;
	t.BSInsert(5);
	t.BSInsert(8);
	t.BSInsert(6);
	t.BSInsert(1);
	t.BSInsert(3);
	t.BSInsert(2);
	t.BSInsert(4);

	t.BSInOrder();

	cout << "是否存在二叉树的值为1:";
	if (t.BSFind(1))cout << "存在";
	else cout << "不存在";
	cout << endl;

	int arr[] = { 5,3,1,2,4,9,8,6,7,10 };
	BSTree<int> t1;
	for (auto e : arr)
	{
		t1.BSInsert(e);
	}
	t1.BSInOrder();

	t1.BSErase(3);
	t1.BSInOrder();

	cout << "是否存在二叉树的值为1:";
	if (t1.BSFindR(1))cout << "存在";
	else cout << "不存在";
	cout << endl;

	t1.BSInsertR(11);
	t1.BSInOrder();

	t1.BSEraseR(11);
	t1.BSInOrder();

}

int main()
{
	BSTree_test1();
	return 0;
}

这里就是数据结构中二叉搜索树的基本介绍了😉
如有错误❌望指正,最后祝大家学习进步✊天天开心✨🎉

             

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

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

相关文章

机器学习入门教学——可解释性

1、前言 近年来&#xff0c;机器学习模型被广泛地应用到现实生活中的一些重要领域&#xff0c;如面部识别、自动驾驶、语言处理和智慧医疗等。然而&#xff0c;机器学习模型就像一个黑盒子&#xff0c;给予一个输入&#xff0c;就能得到一个决策结果&#xff0c;但是我们并不知…

使用ECS和RDS部署WordPress,搭建个人博客并使用域名访问

目录 一、准备工作 1、准备ECS服务器 2、创建数据库账号和密码 二、部署环境 1、远程连接 2、安装Apache服务 3、部署WordPress 三、对博客的优化并使用域名访问 1、博客的设计优化 1.1 插件的使用 1.2 博客的设计介绍 2、使用域名访问 四、个人博客部署的心得 1…

glibc2.35-通过tls_dtor_list劫持exit执行流程

前言 glibc2.35删除了malloc_hook、free_hook以及realloc_hook&#xff0c;通过劫持这三个hook函数执行system已经不可行了。 传统堆漏洞利用是利用任意地址写改上上述几个hook从而执行system&#xff0c;在移除之后则需要找到同样只需要修改某个地址值并且能够造成程序流劫持…

OpenCV的绘图函数,实力绘画篮球场

关键函数&#xff1a;cv2.line()&#xff0c;cv2.circle()&#xff0c;cv2.rectangle()&#xff0c;cv2.ellipse()&#xff0c;cv2.putText() 等。 绘制几何形状 import cv2 as cv import numpy as npcv.rectangle()&#xff0c;cv.circle()&#xff0c;cv.line()&#xff0c…

安全远控如何设置?揭秘ToDesk、TeamViewer 、向日葵安全远程防御大招

写在前面一、远程控制&#xff1a;安全性不可忽略二、远控软件安全设置实测◉ ToDesk◉ TeamViewer◉ 向日葵 三、远控安全的亮点功能四、个人总结与建议 写在前面 说到远程办公&#xff0c;相信大家都不陌生。远程工作是员工在家中或者其他非办公场所上班的一种工作模式&…

了解被测系统(二)接入链路--包括域名解析和Nginx代理

目录 一、接入链路示例 二、域名解析过程 1、相关概念 1.1、域的结构 1.2、DNS是什么&#xff1f; 1.3、DNS根域名服务器 1.4、顶级域名服务器 1.5、权威域名服务器 2、域名解析过程 2.1、检查Hosts文件 2.2、检查本地DNS缓存 2.3、DNS解析--本地DNS服务器 2.4、D…

基于yolov5模型的目标检测蒸馏(LD+KD)

文章目录 前言一、Distillation理解1、Knowlege distillation2、Feature distillation3、Location distillation4、其它蒸馏 二、yolov5蒸馏模型构建1、构建teacher预测模型2、构建蒸馏loss3、蒸馏模型代码图示模型初始化模型蒸馏 三、蒸馏模型实验1、工程数据测试2、voc2012开…

SpringMVC:从入门到精通,7篇系列篇带你全面掌握--二.SpringMVC常用注解及参数传递

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于SpringMVC的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.关于日志的了解 1.使用日志的好处…

ESD门禁管理系统的组成和主要功能

ESD门禁管理系统是一种用于实现企业或组织对出入口进行管理和控制的系统。ESD代表“电子门禁系统”&#xff0c;它利用先进的技术手段来确保只有授权人员可以进入特定区域&#xff0c;从而提高管理效率。 ESD门禁管理系统通常包括以下组件&#xff1a; 1. 门禁读卡器&#xf…

论文阅读《Robust Monocular Depth Estimation under Challenging Conditions》

论文地址&#xff1a;https://arxiv.org/pdf/2308.09711.pdf 源码地址&#xff1a;https://github.com/md4all/md4all 概述 现有SOTA的单目估计方法在理想的环境下能得到满意的结果&#xff0c;而在一些极端光照与天气的情况下往往会失效。针对模型在极端条件下的表现不佳问题&…

拓展世界 | “秀才”被封,千万粉丝一朝空,数字时代来临,大众情感寄托是否有新的出口?

近日&#xff0c;短视频千万粉丝博主“秀才”因违反平台相关规定被封&#xff0c;引起了不少网友的关注&#xff0c;网络上大家戏称他为“中年妇女收割机”&#xff0c;这次的封杀&#xff0c;网友开玩笑道“这得有多少阿姨伤心欲绝”。 在当今数字时代&#xff0c;网红主播已…

计算机领域期刊会议级别分类

文章目录 一、查询期刊1.1、知网1.2、letpub1.3、ccf 二、CCF2.1、CCF和SCI的区别2.2、国际学术期刊2.3、国内期刊2.4、国际会议2.5、国内会议 三、期刊会议总结 一、查询期刊 1.1、知网 查询中⽂期刊⼀般用知⽹&#xff0c;输入你想了解的期刊然后搜索&#xff0c;可以查看期…

Ab3d.DXEngine 6.0 Crack 2023

Ab3d.DXEngine 不是另一个游戏引擎&#xff08;如Unity&#xff09;&#xff0c;它强迫您使用其游戏编辑器、其架构&#xff0c;并且需要许多技巧和窍门才能在标准 .Net 应用程序中使用。Ab3d.DXEngine 是一个新的渲染引擎&#xff0c;它是从头开始构建的&#xff0c;旨在用于标…

计算机视觉的应用13-基于SSD模型的城市道路积水识别的应用项目

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下计算机视觉的应用13-基于SSD模型的城市道路积水识别的应用项目。今年第11号台风“海葵”后部云团的影响&#xff0c;福州地区的降雨量突破了历史极值&#xff0c;多出地方存在严重的积水。城市道路积水是造成交通拥…

关于ThreadPoolTaskExecutor线程池的配置

说明&#xff1a; 1、线程池分类、其他 1.1、分类 IO密集型 和 CPU密集型 任务的特点不同&#xff0c;因此针对不同类型的任务&#xff0c;选择不同类型的线程池可以获得更好的性能表现。 1.1. IO密集型任务 ​ IO密集型任务的特点是需要频繁读写磁盘、网络或者其他IO资源&a…

Netty—Channel

文章目录 一、Channel 是什么&#xff1f;&#x1f914;️二、 Channel 的继承体系&#x1f46a;三、Channel 的初始化过程 &#x1f50d;首先&#xff0c;channel() 指定 ChannelFactory 类型其次&#xff0c;Channel 实例化 一、Channel 是什么&#xff1f;&#x1f914;️ …

初识Java 5-1 实现隐藏

目录 库单元&#xff1a;package 代码组织 独一无二的包名 Java访问权限修饰符 包访问权限 接口访问权限&#xff08;public&#xff09; 不可访问&#xff08;private&#xff09; 继承访问权限&#xff08;protected&#xff09; 包访问权限与公共构造器 接口与实现…

基于Java+SpringBoot+Vue前后端分离医疗挂号管理系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

pdf怎么转cad?几个简单方法分享给你

pdf怎么转cad&#xff1f;PDF文件转换为CAD文件是一项非常重要的任务&#xff0c;特别是对于那些需要进行工程、建筑和设计的专业人士来说。在过去&#xff0c;这项任务可能需要耗费大量时间和精力&#xff0c;但现在&#xff0c;随着技术的不断发展&#xff0c;已经有很多工具…

华为云云服务器评测| 之性能测试

文章目录 前言软件安装扩展知识 收集服务器负载信息指令解析开始压测后台运行 stress 运行 sysbench 测试网络带宽总结 测试磁盘 I/O 性能I/O 性能评估总结 前言 在当今数字化时代&#xff0c;云计算作为一种高效、灵活的计算方式&#xff0c;正日益受到企业和个人用户的广泛关…