数据结构--二叉搜索树的实现

目录

1.二叉搜索树的概念

2.二叉搜索树的操作

二叉搜索树的插入

中序遍历(常用于排序)

二叉搜索树的查找

二叉搜索树的删除

完整二叉树代码:

二叉搜索树的应用

key/value搜索模型整体代码


1.二叉搜索树的概念

二叉搜索树又称二叉排序树,它或者是一棵空树 ,或者是具有以下性质的二叉树 :
若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
它的左右子树也分别 为二叉搜索树
注:搜索二叉树中没有重复值
二叉搜索树与其结点的代码实现
#include<iostream>
using namespace std;

template<class K>//搜索二叉树的结点
struct BSTreeNode
{
	K _key;
	BSTreeNode<K>* _left;
	BSTreeNode<K>* _right;

	BSTreeNode(const K& s = K())
		:_key(s)
		, _left(nullptr)
		, _right(nullptr)
	{}
};

template<class K>//搜索二叉树
class BSTree
{
public:
    
    BSTree()
        :_root(nullptr)
    {}

	//...各种操作二叉搜索树方法的实现
	//...
private:
	typedef BSTreeNode<K> Node;
	Node* _root;
};

2.二叉搜索树的操作

二叉搜索树的插入

这里根据二叉搜索树的概念分两种情况:

a. 树为空,则直接新增节点,赋值给 root 指针
b. 树不空,按二叉搜索树性质查找插入位置,插入新节点

非递归

bool Insert(const K & key)
	{
		if (_root == nullptr)//情况a
		{
			_root = new Node(key);
		}
		else//情况b
		{
			Node* parent = nullptr;//记录当前节点的父结点
			Node* cur = _root;
			while (cur)
			{
				if (cur->_key > key)//小于当前节点的值,向左走
				{
					parent = cur;
					cur = cur->_left;
				}
				else if (cur->_key < key)//大于当前结点的值,向右走
				{
					parent = cur;
					cur = cur->_right;
				}
				else  //数字重复插入失败
				{
					return false;
				}
			}
			cur = new Node(key);
			if (parent->_key > key)//判断插入结点是在parent的左子树还是右子树
			{
				parent->_left = cur;
			}
			else
			{
				parent->_right = cur;
			}
			return true;
		}
	}

为什么要定义parent变量记录cur的父节点?

这里我们要知道,cur=new Node(key)这行代码的真正意义是给cur赋值,并没有把结点插入到树中。

注:在向二叉搜索树插入时,一定要判断是在父节点的左子树还是右子树。

递归:

public: 
bool InsertR(const K& key)
{
	return _insertR(_root, key);
}

private:
bool _insertR(Node*& root, const K& key)
{
	if (root == nullptr)
	{
		root = new Node(key);
		return true;
	}
	else
	{
		if (root->_key > key)
		{
			return _insertR(root->_left, key);
		}
		else if (root->_key < key)
		{
			return _insertR(root->_right, key);
		}
		else
		{
			return false;
		}
	}
}

注:由于使用递归时,需要用到成员变量_root作为实参,但是在类外面无法直接调用,因此,将递归调用的函数封装到了InsertR()里面。

为什么这里不用记录父节点,就可以插入到树中。

这里我们要注意函数的第一个变量,我们使用了引用!

这里的root就是父节点的左孩子或有孩子。

那么在非递归里面可以使用引用来达到不设置parent变量来记录父节点吗?
不能,因为在C++里引用只能指向一个。之后就不能改变指向。在递归中,我们是在传参是使用的,每次引用都重新开辟了一个新的变量,而非递归中我们一直用的是一个变量。

中序遍历(常用于排序)

public:
void Inorder()
{
	_Inorder(_root);
}

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

这里根据二叉搜索树的概念我们清楚,其中序遍历相当于将树里面的数据按从小到大排序输出。

二叉搜索树的查找

查找方法:

a 、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
b 、最多查找高度次,走到到空,还没找到,这个值不存在。

注意:

为完全二叉树时间复杂度最好,为O(log n)   

树的结点全部为左孩子或右孩子时,时间复杂度最坏,为O(n)

非递归

bool Find(const K& key)
{
	if (_root == nullptr)//树为空
		return false;
	Node* cur = _root;
	while (cur)
	{
		if (cur->_key > key)
		{
			cur = cur->left;// _key>key.左走
		}
		else if (cur->_key < key)
		{
			cur = cur->_right;//_key<key.右走
		}
		else
		{
			return true;//相等,找到
		}
	}
	return false;//没有一个相等
}

递归:

public:
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->_left, key);
	}
	else if (root->_key < key)
	{
		_FindR(root->_right, key);
	}
	else
	{
		return root;
	}
}

二叉搜索树的删除

首先查找元素是否在二叉搜索树中,如果不存在,则返回 , 否则要删除的结点可能分下面四种情
况:
a. 要删除的结点无孩子结点
b. 要删除的结点只有左孩子结点
c. 要删除的结点只有右孩子结点
d. 要删除的结点有左、右孩子结点
看起来有待删除节点有 4 中情况,实际情况 a 可以与情况 b 或者 c 合并起来,因此真正的删除过程
如下:
情况 b :删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点 -- 直接删除
情况 c :删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点 -- 直接删除
情况 d :在它的右子树中寻找中序下的第一个结点 ( 关键码最小 ) ,用它的值填补到被删除节点
中,再来处理该结点的删除问题 -- 替换法删除
bool Erase(const K& key)
{
	if (_root == nullptr)
		return false;
	Node* cur = _root;
	Node* parent = nullptr;
	while (cur)
	{
		if (cur->_key > key)
		{
			parent = cur;
			cur = cur->_left;
		}
		else if (cur->_key < key)
		{
			parent = nullptr;
			cur = cur->_right;
		}
		else
		{
			if (cur->_left == nullptr)//情况a
			{
				if (cur == _root)//特殊条件,等于根节点
				{
					_root = cur->_right;
				}
				else
				{
					if (parent->_left == cur)
					{
						parent->_left = cur->_right;
					}
					else
					{
						parent->_right = cur->_right;
					}
				}
				delete cur;
			}
			else if (cur->right == nullptr)//情况b
			{
				if (cur == _root) //特殊条件,等于根节点
				{
					_root = cur->_left;
				}
				else
				{
					if (parent->_left == cur)
					{
						parent->_left = cur->_left;
					}
					else
					{
						parent->_right = cur->_left;
					}
				}
				delete cur;
			}
			else            //情况c
			{
				Node* parent = cur;
				Node* subnode = cur->_right;
				while (subnode->_left)
				{
					parent = subnode;
					subnode = subnode->_left;
				}
				swap(cur->_key, subnode->_key);
				if (parent->_right == subnode)   //当cur->_right->left==nullptr
				{
					parent->_right = subnode->_right;
				}
				else
				{
					parent->_left = subnode->_right;
				}
				delete subnode;
			}
			return true;
		}
	}
	return false;
}

递归:

public:

bool EraseR(const K& key)
{
    _EraseR(_root,key);
}

private:

bool _EraseR(Node*& root, const K& key)
{
	if (root == nullptr)
	{
		return false;
	}
	if (root->_key > key)
	{
		return _EraseR(root->_left, key);
	}
	else if (root->_key < key)
	{
		return _EraseR(root->_right, key);
	}
	else
	{
		if (root->_left == nullptr)
		{
			Node* temp = root;
			root = root->_right;
			delete temp;
		}
		else if (root->right)
		{
			Node* temp = root;
			root = root->_left;
			delete temp;
		}
		else
		{
			Node* subnode = root->_right;
			while (subnode->left)
			{
				subnode = subnode->_left;
			}
			swap(root->_key, subnode->_key);
			return _EraseR(root - right, key);
		}
	}
}

完整二叉树代码:

#include<iostream>
using namespace std;

template<class K>//搜索二叉树的结点
struct BSTreeNode
{
	K _key;
	BSTreeNode<K>* _left;
	BSTreeNode<K>* _right;

	BSTreeNode(const K& s = K())
		:_key(s)
		, _left(nullptr)
		, _right(nullptr)
	{}
};

template<class K>//搜索二叉树
class BSTree
{
public:

	BSTree()
		:_root(nullptr)
	{}

	 bool Insert(const K & key)
	{
		if (_root == nullptr)//情况a
		{
			_root = new Node(key);
		}
		else//情况b
		{
			Node* parent = nullptr;//记录当前节点的父结点
			Node* cur = _root;
			while (cur)
			{
				if (cur->_key > key)//小于当前节点的值,向左走
				{
					parent = cur;
					cur = cur->_left;
				}
				else if (cur->_key < key)//大于当前结点的值,向右走
				{
					parent = cur;
					cur = cur->_right;
				}
				else  //数字重复插入失败
				{
					return false;
				}
			}
			cur = new Node(key);
			if (parent->_key > key)//判断插入结点是在parent的左子树还是右子树
			{
				parent->_left = cur;
			}
			else
			{
				parent->_right = cur;
			}
			return true;
		}
	}

	 bool Find(const K& key)
	 {
		 if (_root == nullptr)//树为空
			 return false;
		 Node* cur = _root;
		 while (cur)
		 {
			 if (cur->_key > key)
			 {
				 cur = cur->left;// _key>key.左走
			 }
			 else if (cur->_key < key)
			 {
				 cur = cur->_right;//_key<key.右走
			 }
			 else
			 {
				 return true;//相等,找到
			 }
		 }
		 return false;//没有一个相等
	 }

	 Node* FindR(const K& key)
	 {
		 return _FindR(_root, key);
	 }


	 void Inorder()
	 {
		 _Inorder(_root);
	 }

	 bool InsertR(const K& key)
	 {
		 return _insertR(_root, key);
		 cout << endl;
	 }


	 bool Erase(const K& key)
	 {
		 if (_root == nullptr)
			 return false;
		 Node* cur = _root;
		 Node* parent = nullptr;
		 while (cur)
		 {
			 if (cur->_key > key)
			 {
				 parent = cur;
				 cur = cur->_left;
			 }
			 else if(cur->_key<key)
			 {
				 parent = nullptr;
				 cur = cur->_right;
			 }
			 else
			 {
				 if (cur->_left == nullptr)
				 {
					 if (cur == _root)
					 {
						 _root = cur->_right;
					 }
					 else
					 {
						 if (parent->_left == cur)
						 {
							 parent->_left = cur->_right;
						 }
						 else
						 {
							 parent->_right = cur->_right;
						 }
					 }
					 delete cur;
				 }
				 else if(cur->right==nullptr)
				 {
					 if (cur == _root)
					 {
						 _root = cur->_left;
					 }
					 else
					 {
						 if (parent->_left == cur)
						 {
							 parent->_left = cur->_left;
						 }
						 else
						 {
							 parent->_right = cur->_left;
						 }
					 }
					 delete cur;
				 }
				 else
				 {
					 Node* parent = cur;
					 Node* subnode = cur->_right;
					 while (subnode->_left)
					 {
						 parent = subnode;
						 subnode = subnode->_left;
					 }
					 swap(cur->_key, subnode->_key);
					 if (parent->_right == subnode)
					 {
						 parent->_right = subnode->_right;
					 }
					 else
					 {
						 parent->_left = subnode->_right;
					 }
					 delete subnode;
				 }
				 return true;
			 }
		 }
		 return false;
	 }


	 bool EraseR(const K& key)
	 {
		 return _EraseR(_root, key);
	 }

private:
	typedef BSTreeNode<K> Node;
	Node* _root;

	bool _insertR(Node*& root, const K& key)
	{
		if (root == nullptr)
		{
			root = new Node(key);
			return true;
		}
		else
		{
			if (root->_key > key)
			{
				return _insertR(root->_left, key);
			}
			else if (root->_key < key)
			{
				return _insertR(root->_right, key);
			}
			else
			{
				return false;
			}
		}
	}

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

	Node*_FindR(Node* root, const K& key)
	{
		if (root == nullptr)
			return nullptr;
		if (root->_key > key)
		{
			_FindR(root->_left, key);
		}
		else if (root->_key < key)
		{
			_FindR(root->_right, key);
		}
		else
		{
			return root;
		}
	}

	bool _EraseR(Node*& root, const K& key)
	{
		if (root == nullptr)
		{
			return false;
		}
		if (root->_key > key)
		{
			return _EraseR(root->_left, key);
		}
		else if (root->_key < key)
		{
			return _EraseR(root->_right, key);
		}
		else
		{
			if (root->_left == nullptr)
			{
				Node* temp = root;
				root = root->_right;
				delete temp;
			}
			else if (root->right)
			{
				Node* temp = root;
				root = root->_left;
				delete temp;
			}
			else
			{
				Node* subnode = root->_right;
				while (subnode->left)
				{
					subnode = subnode->_left;
				}
				swap(root->_key, subnode->_key);
				return _EraseR(root - right, key);
			}
		}
	}
};
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

二叉搜索树的应用

1. K 模型: K 模型即只有 key 作为关键码,结构中只需要存储 Key 即可,关键码即为需要搜索到
的值
比如: 给一个单词 word ,判断该单词是否拼写正确 ,具体方式如下:
以词库中所有单词集合中的每个单词作为 key ,构建一棵二叉搜索树
在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。
2. KV 模型:每一个关键码 key ,都有与之对应的值 Value ,即 <Key, Value> 的键值对 。该方式在现实生活中非常常见:
比如 英汉词典就是英文与中文的对应关系 ,通过英文可以快速找到与其对应的中文,英
文单词与其对应的中文 <word, chinese> 就构成一种键值对;
再比如 统计单词次数 ,统计成功后,给定单词就可快速找到其出现的次数, 单词与其出
现次数就是 <word, count> 就构成一种键值对

key/value搜索模型整体代码

#pragma once
// 改造二叉搜索树为KV结构
template<class K, class V>
struct BSTNode
{
	BSTNode(const K& key = K(), const V& value = V())
		: _pLeft(nullptr), _pRight(nullptr), _key(key), _Value(value)
	{}
	BSTNode<T>* _pLeft;
	BSTNode<T>* _pRight;
	K _key;
	V _value
};


template<class K, class V>
class BSTree
{
	typedef BSTNode<K, V> Node;
public:

	bool Insert(const K& key,const V& value)
	{
		if (_root == nullptr)//情况a
		{
			_root = new Node(key,value);
		}
		else//情况b
		{
			Node* parent = nullptr;//记录当前节点的父结点
			Node* cur = _root;
			while (cur)
			{
				if (cur->_key > key)//小于当前节点的值,向左走
				{
					parent = cur;
					cur = cur->_left;
				}
				else if (cur->_key < key)//大于当前结点的值,向右走
				{
					parent = cur;
					cur = cur->_right;
				}
				else  //数字重复插入失败
				{
					return false;
				}
			}
			cur = new Node(key,value);
			if (parent->_key > key)//判断插入结点是在parent的左子树还是右子树
			{
				parent->_left = cur;
			}
			else
			{
				parent->_right = cur;
			}
			return true;
		}
	}

	bool Find(const K& key)
	{
		if (_root == nullptr)//树为空
			return false;
		Node* cur = _root;
		while (cur)
		{
			if (cur->_key > key)
			{
				cur = cur->left;// _key>key.左走
			}
			else if (cur->_key < key)
			{
				cur = cur->_right;//_key<key.右走
			}
			else
			{
				return true;//相等,找到
			}
		}
		return false;//没有一个相等
	}

	bool Erase(const K& key)
	{
		if (_root == nullptr)
			return false;
		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (cur->_key > key)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (cur->_key < key)
			{
				parent = nullptr;
				cur = cur->_right;
			}
			else
			{
				if (cur->_left == nullptr)
				{
					if (cur == _root)
					{
						_root = cur->_right;
					}
					else
					{
						if (parent->_left == cur)
						{
							parent->_left = cur->_right;
						}
						else
						{
							parent->_right = cur->_right;
						}
					}
					delete cur;
				}
				else if (cur->right == nullptr)
				{
					if (cur == _root)
					{
						_root = cur->_left;
					}
					else
					{
						if (parent->_left == cur)
						{
							parent->_left = cur->_left;
						}
						else
						{
							parent->_right = cur->_left;
						}
					}
					delete cur;
				}
				else
				{
					Node* parent = cur;
					Node* subnode = cur->_right;
					while (subnode->_left)
					{
						parent = subnode;
						subnode = subnode->_left;
					}
					swap(cur->_key, subnode->_key);
					if (parent->_right == subnode)
					{
						parent->_right = subnode->_right;
					}
					else
					{
						parent->_left = subnode->_right;
					}
					delete subnode;
				}
				return true;
			}
		}
		return false;
	}
	
	void Inorder()
	{
		_Inorder(_root);
	}



private:
	Node* _root;

	void _Inorder(Node* root)
	{
		if (root == nullptr)
			return;
		_Inorder(root->_left);
		cout << root->_key << ":"<<root->_value<<endl;
		_Inorder(root->_right);
	}
};
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

亚信安慧AntDB数据并行加载工具的实现(一)

1.概述 数据加载速度是评判数据库性能的重要指标&#xff0c;能否提高数据加载速度&#xff0c;对文件数据进行并行解析&#xff0c;直接影响数据库运维管理效率。基于此&#xff0c;AntDB分布式数据库提供了两种数据加载方式&#xff1a; 一是类似于PostgreSQL的Copy命令&am…

ES6之解构赋值详解

✨ 专栏介绍 在现代Web开发中&#xff0c;JavaScript已经成为了不可或缺的一部分。它不仅可以为网页增加交互性和动态性&#xff0c;还可以在后端开发中使用Node.js构建高效的服务器端应用程序。作为一种灵活且易学的脚本语言&#xff0c;JavaScript具有广泛的应用场景&#x…

Nacos注册

一、简介 Nacos是阿里云开源的一个服务发现、配置管理和服务鉴权平台&#xff0c;它提供了一种更简单、更便捷、更开放的方式来管理服务&#xff0c;帮助开发者快速实现服务的发现、配置的管理、服务的鉴权等功能。Nacos可以帮助开发者轻松管理微服务应用中的服务提供者、服务…

《整机柜服务器通用规范》由OCTC正式发布!浪潮信息牵头编制

近日&#xff0c;中国电子工业标准化技术协会开放计算标准工作委员会&#xff08;OCTC&#xff09;正式批准发布了《整机柜服务器通用规范》&#xff0c;该标准由浪潮信息牵头&#xff0c;中国工商银行、中国质量认证中心、英特尔、中国计量科学研究院等十余家单位联合编制&…

Github 2023-12-30 开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2023-12-30统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量TypeScript项目4JavaScript项目2C项目1Python项目1Java项目1HTML项目1Dart项目1非开发语言项目1 令人惊叹的 …

一起玩儿物联网人工智能小车(ESP32)——13. 用ESP32的GPIO控制智能小车运动起来(一)

摘要&#xff1a;本文更深入的讲述了GPIO的相关知识&#xff0c;并完成了导线连接工作&#xff0c;为下一步的软件开发做好了准备。 通用输入输出端口&#xff08;GPIO&#xff1a;General Purpose Input/Output Port&#xff09;&#xff0c;在前面已经有了初步的介绍&#xf…

代码随想录-刷题第四十二天

0-1背包理论基础 0-1背包问题介绍 0-1背包问题&#xff1a;有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 0-1背包问题可以使用回溯法进…

mongoose中http server服务器解决“Access-Control-Allow-Origin mongoose”跨域问题

问题 使用mongoose做http服务器&#xff0c;自己构造的浏览器端jquery在访问server时&#xff0c;会遇到&#xff1a; Access to XMLHttpRequest at http://127.0.0.1:8000/ from origin null has been blocked by CORS policy: No Access-Control-Allow-Origin header is pr…

Android Camera

1. 相关的API Android有三套关于摄像头的API(库)&#xff0c;分别是Camera、Camera2和CameraX&#xff0c;其中Camera已废弃&#xff0c;在Android5.0以后推荐使用Camera2和CameraX&#xff0c;Camera2推出是用来替换Camera的&#xff0c;它拥有丰富的API可以为复杂的用例提供…

ArcGIS批量计算shp面积并导出shp数据总面积(建模法)

在处理shp数据时&#xff0c; 又是我们需要知道许多个shp字段的批量计算&#xff0c;例如计算shp的总面积、面积平均值等&#xff0c;但是单个查看shp文件的属性进行汇总过于繁琐&#xff0c;因此可以借助建模批处理来计算。 首先准备数据&#xff1a;一个含有多个shp的文件夹。…

树莓派 ubuntu20.04下 python调讯飞的语音API,语音识别和语音合成

目录 1.环境搭建2.去讯飞官网申请密钥3.语音识别&#xff08;sst&#xff09;4.语音合成&#xff08;tts&#xff09;5.USB声卡可能报错 1.环境搭建 #环境说明&#xff1a;(尽量在ubuntu下使用, 本次代码均在该环境下实现) sudo apt-get install sox # 安装语音播放软件 pip …

【零基础入门VUE】VueJS - 模板

✍面向读者&#xff1a;所有人 ✍所属专栏&#xff1a;零基础入门VUE专栏https://blog.csdn.net/arthas777/category_12537076.html 我们在前面的章节中学习了如何在屏幕上以文本内容的形式输出。在本章中&#xff0c;我们将学习如何在屏幕上以 HTML 模板的形式获取输出。 为了…

使用element中el-cascader级联选择器动态懒加载以及回显 (单选)

<template><!-- 新增||修改弹框 --><el-dialog :close-on-click-modal"false" :close-on-press-escape"false" :title"title" :visible.sync"open"width"800px" append-to-body><el-form ref"for…

2023年高级软考系统架构师考题参考

对于一些有实践经验的同学来说&#xff0c;感觉不难&#xff0c;但是落笔到纸面上&#xff0c;就差强人意了&#xff0c;平时这方面要多练习&#xff0c;所想所思要落到纸面上&#xff0c;或者表达清晰让别人听懂&#xff0c;不仅是工作中的一个基本素质&#xff0c;也是个非常…

跟小德学C++之配置文件(形式)

嗨&#xff0c;大家好&#xff0c;我是出生在达纳苏斯的一名德鲁伊&#xff0c;我是要立志成为海贼王&#xff0c;啊不&#xff0c;是立志成为科学家的德鲁伊。最近&#xff0c;我发现我们所处的世界是一个虚拟的世界&#xff0c;并由此开始&#xff0c;我展开了对我们这个世界…

C/C++转WebAssembly及微信小程序调用

上一篇文章讲了C/C如何转WebAssembly&#xff0c;并测试了在Web端调用。本篇内容和上篇一样&#xff0c;介绍C/C包转的.wasm包如何在小程序中调用。 说明 本篇是在上一篇步骤1-4的基础上&#xff0c;再做修改&#xff0c;供微信小程序端调用的方法和步骤。 本篇操作手册可以…

再见2023,你好2024

再见2023&#xff0c;你好2024 生活1月 悲伤与治愈2~4月 运动与偏爱5月 体验与美食6月 婚礼与热爱7~8月 就医与别离9~11月 陪伴与暖房12月 体验&新生 运动追剧读书总结 生活 生活是一个修罗场&#xff0c;来世间一场&#xff0c;要经历丰腴有趣的人生。去体验各种滋味&…

线性代数——(期末突击)行列式(上)-行列式计算、行列式的性质

目录 行列式 行列式计算 逆序数 行列式的性质 转置 两行&#xff08;列&#xff09;互换 两行&#xff08;列&#xff09;对应相等 提公因子 两行&#xff08;列&#xff09;对应成比例 某行&#xff08;列&#xff09;为零 行列式分裂 行列式变换及三角行列式 行…

MySQL 数值函数,字符串函数与多表查询

MySQL像其他语言一样,也提供了很多库函数,分为单行函数和分组函数(聚合函数),我们这里先简易介绍一些函数,熟悉就行,知道怎么使用即可. 数值函数 三角函数 指数与对数函数 进制间的转换函数 字符串函数 注:LPAD函数是右对齐,RPAD函数是左对齐 多表查询 注:如果为表起了别名,就…

听GPT 讲Rust源代码--src/tools(34)

File: rust/src/tools/clippy/clippy_lints/src/collection_is_never_read.rs 文件"collection_is_never_read.rs"位于Rust源代码中的clippy_lints工具中&#xff0c;其作用是检查在集合类型&#xff08;如Vec、HashMap等&#xff09;的实例上执行的操作是否被忽略了…