012 C++ AVL_tree

news2024/11/15 4:32:17

前言

本文将会向你介绍AVL平衡二叉搜索树的实现

引入AVL树

二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序普通的二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年发明了一种解决上述问题的方法(AVL树是以这两位的名字命名的):当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1,超过了1需要对树中的结点进行调整(旋转),即可降低树的高度,从而减少平均搜索长度。

平衡因子

AVL树的平衡因子是指一个节点的左子树的高度减去右子树的高度的值。在AVL树中,每个节点的平衡因子必须为-1、0或1,如果不满足这个条件,就需要通过旋转操作来重新平衡树。AVL树的平衡因子可以帮助我们判断树的平衡状态,并且在插入进行相应的调整,以保持树的平衡性。

节点的创建

除了需要增加一个_bf平衡因子,这里还多加了一个pParent的结构体指针便于我们向上遍历对平衡因子进行调整

struct AVLTreeNode
{
	AVLTreeNode(const T& data = T())
		: _pLeft(nullptr)
		, _pRight(nullptr)
		, _pParent(nullptr)
		, _data(data)
		, _bf(0)
	{}

	AVLTreeNode<T>* _pLeft;
	AVLTreeNode<T>* _pRight;
	AVLTreeNode<T>* _pParent;
	T _data;
	int _bf;   // 节点的平衡因子
};

插入节点

先按照二叉搜索树的规则将节点插入到AVL树中
新节点插入后,AVL树的平衡性可能会遭到破坏,此时就需要更新平衡因子,并检测是否破坏了AVL树的平衡性
cur插入后,pParent的平衡因子一定需要调整,在插入之前,pParent的平衡因子分为三种情况:-1,0, 1, 分以下两种情况:

如果cur插入到pParent的左侧,只需给pParent的平衡因子-1即可
如果cur插入到pParent的右侧,只需给pParent的平衡因子+1即可

此时:pParent的平衡因子可能有三种情况:0,正负1, 正负2

1. 如果pParent的平衡因子为0,说明插入之前pParent的平衡因子为正负1,插入后被调整成0,此时满足AVL树的性质,插入成功
2. 如果pParent的平衡因子为正负1,说明插入前pParent的平衡因子一定为0,插入后被更新成正负1,此时以pParent为根的树的高度增加,需要继续向上更新
3. 如果pParent的平衡因子为正负2,则pParent的平衡因子违反平衡树的性质,需要对其进行旋转处理

	// 在AVL树中插入值为data的节点
	bool Insert(const T& data)
	{
		Node* cur = _pRoot;
		Node* parent = nullptr;
		if (_pRoot == nullptr)
		{
			//直接插入
			_pRoot = new Node(data);
			//插入成功
			return true;
		}
		//寻找插入位置
		else
		{
			Node* parent = cur;
			while (cur)
			{
				parent = cur;
				if (cur->_data > data)
				{
					cur = cur->_pLeft;
				}
				else if (cur->_data < data)
				{
					cur = cur->_pRight;
				}
				//已有
				else return false;
			}
			cur = new Node(data);
			//插入+链接
			if (parent->_data > data)
			{
				parent->_pLeft = cur;
			}
			else
			{
				parent->_pRight = cur;
			}
			//链接
			cur->_pParent = parent;
		}
		//更新平衡因子
		while (parent)
		{
			if (cur == parent->_pRight)
			{
				parent->_bf++;
			}
			else if (cur == parent->_pLeft)
			{
				parent->_bf--;
			}

			if (parent->_bf == 0)
			{
				//插入后子树稳定,不用向上更新平衡因子
				return true;
			}
			else if (parent->_bf == 1 || parent->_bf == -1)
			{
				return true;
			}
			else if (parent->_bf == 2 || parent->_bf == -2)
			{
				if (parent->_bf == 2 && cur->_bf == 1)
				{
					//左旋 (右高左低,往左边压)
					RotateL(parent);
				}
				else if (parent->_bf == -2 && cur->_bf == -1)
				{
					//右旋(左高右低,往右边压)
					RotateR(parent);
				}
				else if (parent->_bf == 2 && cur->_bf == -1)
				{
					//右左双旋(不是单独的左右有一方低,有一方高)
					RotateL(parent);
				}
				else if (parent->_bf == -2 && cur->_bf == 1)
				{
					//左右双旋(不是单独的左右有一方低,有一方高)
					RotateR(parent);
				}
				parent = parent->_pParent;
				cur = cur->_pParent; 
			}
			else
			{
				return false;
			}
			return true;
		}
	}


右单旋

左高右低,往右边旋(根据平衡因子判断(右子树的高度减去左子树的高度))
细节分析+代码
在这里插入图片描述

整体思路
在这里插入图片描述
在这里插入图片描述

	void RotateR(Node* pParent)
	{
		Node* pPnode = pParent->_pParent;
		Node* subL = pParent->_pLeft;
		Node* subLR = subL->_pRight;
		if (subLR)
		{
			pParent->_pLeft = subL->_pRight;
			subL->pParent = pParent;
		}
		subL->_pRight = pParent;
		pParent->_pParent = subL;
		//旋转部分子树
		if (pPnode)
		{
			//是左子树
			if (pPnode->_pLeft == pParent)
			{
				pPnode->_pLeft = subL;
				subL->pParent = pPnode;
			}
			//是右子树
			else
			{
				pPnode->_pLeft = subL;
				subL->pParent = pPnode;
			}
		}
		//旋转整棵子树
		else
		{
			_pRoot = subL;
			subL->pParent = nullptr;
		}
		//调节平衡因子
		pParent->_bf = subL->_bf = 0;
	}

左单旋

这里作统一说明:h表示子树的高度,绿色标记的数字为节点的平衡因子,长方形表示的是一棵抽象的子树
右高左低,往左边旋(根据平衡因子判断(右子树的高度减去左子树的高度))
左单旋和右单旋的思路很像,这里就不再进行细节分析。

整体思路
在这里插入图片描述
在这里插入图片描述

void RotateL(Node* pParent)
	{
		Node* pPnode = pParent->_pParent;
		Node* subR = pParent->_pRight;
		Node* subRL = subR->_pLeft;//可能为空
		if (subRL)
		{
			pParent->_pRight = subRL;
			subRL->_pParent = pParent;
		}
		subR->_pLeft = pParent;
		pParent->_pParent = subR;

		//链接:旋转整棵树
		if (pPnode == nullptr)
		{
			_pRoot = subR;
			subR->_pParent = nullptr;
		}
		//链接:旋转子树
		else
		{
			if (pPnode->_pLeft == pParent)
			{
				pPnode->_pLeft = subR;
				subR->_pParent = pPnode;
			}
			else if (pPnode->_pRight == pParent)
			{
				pPnode->_pRight = subR;
				subR->_pParent = pPnode;
			}
		}
		//更新平衡因子
		pParent->_bf = subR->_bf = 0;
	}

左右双旋

右左双旋(不是单独的左右有一方低,有一方高)

(1)第一种情况,也是最特殊的情况,即parent的右子树只有两个节点

在这里插入图片描述

(2)第二种情况,parent的左右子树是高度为h的抽象子树,新增节点插入到b子树上

在这里插入图片描述

(2)第三种情况,parent的左右子树是高度为h的抽象子树,新增节点插入到c子树上 实际上第二三种情况的分析是一致的

在这里插入图片描述

void RotateLR(Node* pParent)
	{
		Node* subL = pParent->_pLeft;
		Node* subLR = subL->_pRight;
		int bf = subLR->_bf;
		//复用
		RotateL(subL);
		RotateR(pParent);
		//更新平衡因子
		//插入右边
		if (bf == 1)
		{
			subLR->_bf = 0;
			subL->_bf = -1;
			pParent->_bf = 0;
		}
		//插入左边
		else if (bf == -1)
		{
			subLR->_bf = 0;
			subL->_bf = 0;
			pParent->_bf = 1;
		}
		else if (bf == 0)
		{
			subLR->_bf = 0, subL->_bf = 0, pParent->_bf = 0;
		}
		else
		{
			assert(false);
		}
	}

右左双旋

左右双旋(不是单独的左右有一方低,有一方高)

(1)第一种情况,也是最特殊的情况,即parent的左子树只有两个节点

在这里插入图片描述

(2)第二种情况,parent的左右子树是高度为h的抽象子树,新增节点插入到c子树上

在这里插入图片描述

(3
)第三种情况,parent的左右子树是高度为h的抽象子树,新增节点插入到b子树上 实际上第二三种情况的分析是一致的

在这里插入图片描述

void RotateRL(Node* pParent)
	{
		Node* subR = pParent->_pRight;
		Node* subRL = subR->_pLeft;
		int bf = subRL->_bf;
		RotateR(subR);
		RotateL(pParent);
		//更新平衡因子
		//插入在右边
		if (bf == 1)
		{
			subRL->_bf = 0;
			subR->_bf = 0;
			pParent->_bf = -1;
		}
		//插入在左边
		else if (bf == -1)
		{
			subRL = 0;
			pParent->_bf = 0;
			subR->_bf = 1;
		}
		else if (bf == 0)
		{
			subRL =pParent->_bf = subR->_bf = 0;
		}
		else
		{
			assert(false);
		}
	}

测试

	size_t _Height(Node* pRoot)
	{
		if (pRoot == nullptr)
		{
			return 0;
		}
		int leftHeight = _Height(pRoot->_pLeft);
		int rightHeight = _Height(pRoot->_pRight);
		return (leftHeight > rightHeight) ? leftHeight + 1 : rightHeight + 1;
	}
	bool _IsBalance(Node* pRoot)
	{
		if (pRoot == nullptr)
		{
			return true;
		}
		int leftHeight = _Height(pRoot->_pLeft);
		int rightHeight = _Height(pRoot->_pRight);
		//平衡因子异常的情况
		if (rightHeight - leftHeight != pRoot->_bf)
		{
			cout << pRoot->_data << "平衡因子异常" << endl;
			return false;
		}
		//检查是否平衡
		return abs(rightHeight - leftHeight) < 2
			//检查、遍历左右子树
			&& _IsBalance(pRoot->_pLeft)
			&& _IsBalance(pRoot->_pRight);
	}
	bool IsBalance()
	{
		return _IsBalance(_pRoot);
	}
	int main()
{
	const int N = 30000;
	vector<int> v;
	v.reserve(N);
	srand(time(0));

	for (size_t i = 0; i < N; i++)
	{
		v.push_back(rand());
		cout << v.back() << endl;
	}
	AVLTree<int> t;
	for (auto e : v)
	{
		if (e == 41)
		{
			t.Insert(e);
		}
		cout << "Insert:" << e << "->" << t.IsBalance() << endl;
	}

	cout << t.IsBalance() << endl;

	return 0;
}

全部代码

template<class T>
struct AVLTreeNode
{
	AVLTreeNode(const T& data = T())
		: _pLeft(nullptr)
		, _pRight(nullptr)
		, _pParent(nullptr)
		, _data(data)
		, _bf(0)
	{}

	AVLTreeNode<T>* _pLeft;
	AVLTreeNode<T>* _pRight;
	AVLTreeNode<T>* _pParent;
	T _data;
	int _bf;   // 节点的平衡因子
};


// AVL: 二叉搜索树 + 平衡因子的限制
template<class T>
class AVLTree
{
	typedef AVLTreeNode<T> Node;
public:
	AVLTree()
		: _pRoot(nullptr)
	{}

	// 在AVL树中插入值为data的节点
	bool Insert(const T& data)
	{
		Node* cur = _pRoot;
		Node* parent = nullptr;
		//判断是否为空树
		if (_pRoot == nullptr)
		{
			//直接插入
			_pRoot = new Node(data);
			//插入成功
			return true;
		}

		//寻找插入位置
		else
		{
			Node* parent = cur;
			while (cur)
			{
				//记录父节点的位置,便于后续的链接操作
				parent = cur;
				//向左遍历
				if (cur->_data > data)
				{
					cur = cur->_pLeft;
				}
				//向右遍历
				else if (cur->_data < data)
				{
					cur = cur->_pRight;
				}
				//已有
				else return false;
			}
			cur = new Node(data);
			//插入+链接
			if (parent->_data > data)
			{
				parent->_pLeft = cur;
			}
			else
			{
				parent->_pRight = cur;
			}
			//链接
			cur->_pParent = parent;
		}
		//更新平衡因子
		while (parent)
		{
			if (cur == parent->_pRight)
			{
				parent->_bf++;
			}
			else if (cur == parent->_pLeft)
			{
				parent->_bf--;
			}

			if (parent->_bf == 0)
			{
				//插入后子树稳定,不用向上更新平衡因子
				return true;
			}
			else if (parent->_bf == 1 || parent->_bf == -1)
			{
				return true;
			}
			else if (parent->_bf == 2 || parent->_bf == -2)
			{
				if (parent->_bf == 2 && cur->_bf == 1)
				{
					//左旋 (右高左低,往左边压)
					RotateL(parent);
				}
				else if (parent->_bf == -2 && cur->_bf == -1)
				{
					//右旋(左高右低,往右边压)
					RotateR(parent);
				}
				else if (parent->_bf == 2 && cur->_bf == -1)
				{
					//右左双旋(不是单独的左右有一方低,有一方高)
					RotateL(parent);
				}
				else if (parent->_bf == -2 && cur->_bf == 1)
				{
					//左右双旋(不是单独的左右有一方低,有一方高)
					RotateR(parent);
				}
				parent = parent->_pParent;
				cur = cur->_pParent; 
				return true;
			}
			else
			{
				return false;
			}	
		}
		return true;
	}

	
	// AVL树的验证
	bool IsAVLTree()
	{
		return _IsAVLTree(_pRoot);
	}
	void _InOrder(Node* root)
	{
		if (root == nullptr)
		{
			return;
		}
		_InOrder(root->_pLeft);
		cout << root->_data << " ";
		_InOrder(root->_pRight);
	}
	void InOrder()
	{
		_InOrder(_pRoot);
		cout << endl;
	}
	// 根据AVL树的概念验证pRoot是否为有效的AVL树
	size_t _Height(Node* pRoot)
	{
		if (pRoot == nullptr)
		{
			return 0;
		}
		int leftHeight = _Height(pRoot->_pLeft);
		int rightHeight = _Height(pRoot->_pRight);
		return (leftHeight > rightHeight) ? leftHeight + 1 : rightHeight + 1;
	}
	bool _IsBalance(Node* pRoot)
	{
		if (pRoot == nullptr)
		{
			return true;
		}
		int leftHeight = _Height(pRoot->_pLeft);
		int rightHeight = _Height(pRoot->_pRight);
		//平衡因子异常的情况
		if (rightHeight - leftHeight != pRoot->_bf)
		{
			cout << pRoot->_data << "平衡因子异常" << endl;
			return false;
		}
		//检查是否平衡
		return abs(rightHeight - leftHeight) < 2
			//检查、遍历左右子树
			&& _IsBalance(pRoot->_pLeft)
			&& _IsBalance(pRoot->_pRight);
	}
	bool IsBalance()
	{
		return _IsBalance(_pRoot);
	}
	// 右单旋
	void RotateR(Node* pParent)
	{
		Node* pPnode = pParent->_pParent;
		Node* subL = pParent->_pLeft;
		Node* subLR = subL->_pRight;
		if (subLR)
		{
			pParent->_pLeft = subL->_pRight;
			subL->_pParent = pParent;
		}
		subL->_pRight = pParent;
		pParent->_pParent = subL;
		//旋转部分子树
		if (pPnode)
		{
			if (pPnode->_pLeft == pParent)
			{
				pPnode->_pLeft = subL;
				subL->_pParent = pPnode;
			}
			else
			{
				pPnode->_pLeft = subL;
				subL->_pParent = pPnode;
			}
		}
		//旋转整棵子树
		else
		{
			_pRoot = subL;
			subL->_pParent = nullptr;
		}
		//调节平衡因子
		pParent->_bf = subL->_bf = 0;
	}
	// 左单旋
	void RotateL(Node* pParent)
	{
		Node* pPnode = pParent->_pParent;
		Node* subR = pParent->_pRight;
		Node* subRL = subR->_pLeft;
		if (subRL)
		{
			pParent->_pRight = subRL;
			subRL->_pParent = pParent;
		}
		subR->_pLeft = pParent;
		pParent->_pParent = subR;

		//链接:旋转整棵树
		if (pPnode == nullptr)
		{
			_pRoot = subR;
			subR->_pParent = nullptr;
		}
		//链接:旋转子树
		else
		{
			if (pPnode->_pLeft == pParent)
			{
				pPnode->_pLeft = subR;
				subR->_pParent = pPnode;
			}
			else if (pPnode->_pRight == pParent)
			{
				pPnode->_pRight = subR;
				subR->_pParent = pPnode;
			}
		}
		//更新平衡因子
		pParent->_bf = subR->_bf = 0;
	}
	// 右左双旋
	void RotateRL(Node* pParent)
	{
		Node* subR = pParent->_pRight;
		Node* subRL = subR->_pLeft;
		int bf = subRL->_bf;
		RotateR(subR);
		RotateL(pParent);
		//更新平衡因子
		//插入在右边
		if (bf == 1)
		{
			subRL->_bf = 0;
			subR->_bf = 0;
			pParent->_bf = -1;
		}
		//插入在左边
		else if (bf == -1)
		{
			subRL = 0;
			pParent->_bf = 0;
			subR->_bf = 1;
		}
		else if (bf == 0)
		{
			subRL =pParent->_bf = subR->_bf = 0;
		}
		else
		{
			assert(false);
		}
	}
	// 左右双旋
	void RotateLR(Node* pParent)
	{
		Node* subL = pParent->_pLeft;
		Node* subLR = subL->_pRight;
		int bf = subLR->_bf;
		RotateL(subL);
		RotateR(pParent);
		//更新平衡因子
		//插入右边
		if (bf == 1)
		{
			subLR->_bf = 0;
			subL->_bf = -1;
			pParent->_bf = 0;
		}
		//插入左边
		else if (bf == -1)
		{
			subLR->_bf = 0;
			subL->_bf = 0;
			pParent->_bf = 1;
		}
		else if (bf == 0)
		{
			subLR->_bf = 0, subL->_bf = 0, pParent->_bf = 0;
		}
		else
		{
			assert(false);
		}
	}
private:
	Node* _pRoot;
};

//int main()
//{
//	//int a[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15};
//	int a[] = { 4,2,6,13,5,15,7,16,14 };
//	AVLTree<int> t;
//	for (auto e : a)
//	{
//		t.Insert(e);
//	}
//	t.InOrder();
//	return 0;
//}
int main()
{
	const int N = 30000;
	vector<int> v;
	v.reserve(N);
	srand(time(0));

	for (size_t i = 0; i < N; i++)
	{
		v.push_back(rand());
		cout << v.back() << endl;
	}
	AVLTree<int> t;
	for (auto e : v)
	{
		if (e == 41)
		{
			t.Insert(e);
		}
		cout << "Insert:" << e << "->" << t.IsBalance() << endl;
	}

	cout << t.IsBalance() << endl;

	return 0;
}

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

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

相关文章

直流电机干扰的产生-EMC和EMI

直流电机干扰的产生-EMC和EMI 干扰的产生电路滤波处理EMC处理措施 干扰的产生 带电刷的电动机&#xff0c;由于在电刷切换时&#xff0c;电动机线圈中的电流不能突变&#xff0c;当一路线圈通电断开时&#xff0c;会在该线圈的两端产生较高的反电动势&#xff0c;这个电动势会…

2023.11.17使用flask将多个图片文件上传至服务器

2023.11.17使用flask将多个图片文件上传至服务器 实现功能&#xff1a; 1、同时上传多个图片文件 2、验证文件扩展名 3、显示上传文件的文件名 4、显示文件上传结果 程序结构 main.py from flask import Flask, request, jsonify, render_template import osapp Flask(__n…

vscode快捷键使用总结

&#xff09; 1、格式化选中的代码 1、格式化选中的代码 vscode中选中所要格式化的代码&#xff1a; ctrl k,ctrlf 其实可以查到该命令 ctrlshiftp打开命令窗口输入format

单片机实验(二)

前言 实验一&#xff1a;用AT89C51单片机控制LCD 1602&#xff0c;使其显示两行文字&#xff0c;分别显示自己的学号和姓名拼音。 实验二&#xff1a;设计一个中断嵌套程序。要求K1和K2都未按下时&#xff0c;单片机控制8只数码管&#xff0c;滚动输出完整的学号。当按一下K1…

中间件安全:Apache 目录穿透.(CVE-2021-41773)

中间件安全&#xff1a;Apache 目录穿透.&#xff08;CVE-2021-41773&#xff09; Apache 的 2.4.49、2.4.50 版本 对路径规范化所做的更改中存在一个路径穿越漏洞&#xff0c;攻击者可利用该漏洞读取到Web目录外的其他文件&#xff0c;如系统配置文件、网站源码等&#xff0c…

微服务调用链路追踪

概述 本文介绍微服务调用链路追踪&#xff0c;涉及技术有&#xff1a;sleuth和zipkin。sleuth负责追踪调用链路数据&#xff0c;zipkin负责调用链路数据可视化展现。 本文的操作是在 服务网关实践 的基础上进行。 环境说明 jdk1.8 maven3.6.3 mysql8 spring cloud2021.0.8 …

【开源】基于Vue.js的独居老人物资配送系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 查询社区4.2 新增物资4.3 查询物资4.4 查询物资配送4.5 新增物资配送 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的独居老人物资配送系统&#xff0c;包含了社区档案、…

Node.js之TCP(net)

Hi I’m Shendi Node.js之TCP&#xff08;net&#xff09; 最近使用Nodejs编写程序&#xff0c;需要用到自己编写的分布式工具&#xff0c;于是需要将Java版的用NodeJs重新写一遍&#xff0c;需要使用到TCP通信&#xff0c;于是在这里记录下Node.js TCP 的使用方法 依赖 需要使…

LRU最近最少使用算法

LRU(LeastRecentlyUsed)“最近最少使用”算法&#xff1a; 1.当缓存空间已满耗用时&#xff0c;淘汰最近最少使用数据的缓存对象以释放更多的缓存空间(用于历史缓存对象的维护)。 2. 哈希表:快速查找缓存对象&#xff1b;双向链表:维护 历史数据所在的节点顺序。 步骤&#xff…

T10 数据增强

文章目录 一、准备环境和数据1.环境2. 数据 二、数据增强&#xff08;增加数据集中样本的多样性&#xff09;三、将增强后的数据添加到模型中四、开始训练五、自定义增强函数六、一些增强函数 &#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f…

CSS的选择器(一篇文章齐全)

目录 Day26&#xff1a;CSS的选择器 1、CSS的引入方式 2、CSS的选择器 2.1 基本选择器​编辑 2.2 组合选择器 2.3 属性选择器 2.4 伪类选择器 2.5 样式继承 2.6 选择器优先级 3、CSS的属性操作 3.1 文本属性 3.2 背景属性 3.3 边框属性 3.4 列表属性 3.5 dispal…

Vue3+Vite实现工程化,事件绑定以及修饰符

我们可以使用v-on来监听DOM事件&#xff0c;并在事件触发时执行对应的Vue的Javascript代码。 用法&#xff1a;v-on:click "handler" 或简写为 click "handler"vue中的事件名原生事件名去掉 on 前缀 如:onClick --> clickhandler的值可以是方法事件…

Rust开发——切片(slice)类型

1、什么是切片 在 Rust 中&#xff0c;切片&#xff08;slice&#xff09;是一种基本类型和序列类型。在 Rust 官方文档中&#xff0c;切片被定义为“对连续序列的动态大小视图”。 但在rust的Github 源码中切片被定义如下&#xff1a; 切片是对一块内存的视图&#xff0c;表…

系列十一、你平时工作用过的JVM常用基本配置参数有哪些?

一、常用参数 1.1、-Xms 功能&#xff1a;初始内存大小&#xff0c;默认为物理内存的1/64&#xff0c;等价于 -XX:InitialHeapSize 1.2、-Xmx 功能&#xff1a;最大分配内存&#xff0c;默认为物理内存的1/4&#xff0c;等价于 -XX:MaxHeapSize 1.3、-Xss 功能&#xff1a;设置…

树,二叉树,二叉树遍历,哈夫曼树(详解+刷题)

&#x1f442; 后街男孩经典之精选 - 歌单 - 网易云音乐 &#x1f442; 年轮&#xff08;电视剧《花千骨》男声版插曲&#xff09; - 汪苏泷 - 单曲 - 网易云音乐 目录 &#x1f33c;5.1 -- 树 &#x1f33c;5.2 -- 二叉树 1&#xff0c;性质 2&#xff0c;存储 3&#x…

RTMP协议和源码解析

一、背景 实时消息传输协议&#xff08;Real-Time Messaging Protocol&#xff09;是目前直播的主要协议&#xff0c;是Adobe公司为Flash播放器和服务器之间提供音视频数据传输服务而设计的应用层私有协议。RTMP协议是目前各大云厂商直线直播业务所公用的基本直播推拉流协议&a…

02 elementplus前端增删改查【小白入门SpringBoot+Vue3】

视频教程来源于 B站青戈 https://www.bilibili.com/video/BV1H14y1S7YV 只用elementplus&#xff0c;学点增删改查&#xff0c;还没有于后端连接起来&#xff0c;具体在下一篇 搭建一个小页面&#xff0c;显示数据 补充&#xff1a;webstorm格式化代码&#xff0c;修改了快捷…

二叉树oj题集(LeetCode)

100. 相同的树 关于树的递归问题&#xff0c;永远考虑两方面&#xff1a;返回条件和子问题 先考虑返回条件&#xff0c;如果当前的根节点不相同&#xff0c;那就返回false&#xff08;注意&#xff0c;不要判断相等时返回什么&#xff0c;因为当前相等并不能说明后面节点相等…

记录:RK3568显示异常。

最近调一个RK3568的新板子&#xff0c;板子其它接口功能都调试ok。可唯独在适配显示时发现&#xff0c;HDMI和MIPI显示均出现异常。当系统启动要进入桌面时候内核就开始报错。 因为这套源码之前在其它的板子上适配过&#xff0c;所以第一反应就是硬件问题或者是那个电压没配置…

5 redis的GEO操作

一、GEO Redis 3.2版本提供了GEO(地理信息定位)功能&#xff0c;支持存储地理位置信息用来实现诸如附近位置、摇一摇这类依赖于地理位置信息的功能。 有效纬度从-85.05112878度到85.05112878度 注意&#xff1a;当坐标位置超出上述指定范围时&#xff0c;将会返回一个错误。 …