SB+AVL——二刷错误总结

码云

SBTree

insert中对头节点的处理

	void Insert(int val)
	{
		Node* node = new Node(val);
		// 找插入位置
		if (_root == nullptr)
		{
			_root = node;
			return;
		}
		else
		{
			Node* pre = _root, *head = _root;
			while (head)
			{
				pre = head;
				if (head->_val < val) head = head->_right;
				else if (head->_val > val) head = head->_left;
				else
				{
					assert(false);
				}
			}
			if (val < pre->_val) pre->_left = node;
			else pre->_right = node;
		}
	}

pop需要记住规律

  1. 右边为nullptr
  2. 左边为nullptr
  3. 两边都为nullptr
  4. 两边都不为nullptr
    情况3合并情况1,2一起分析
	void pop(int val)
	{
		// 需要在一开始找cur的时候就要找到pre节点
		// 因为需要改变pre后的节点
		// 找cur阶段不需要找pre节点,pre节点指的是左树最右边节点的父节点
		// 在左右有nullptr的时候是需要直接进行调整的——需要知道pre节点
		// 所以必须在找des的时候找到pre节点
		Node* des = _root, * pre = _root;
		while (des)
		{
			// 只有在向下变换的时候才会变
			// 如果在一开始就变,当他在找到des的时候,也会变换一次,这个时候就坏了
			//pre = des;
			if (des->_val < val) pre=des,des = des->_right;
			else if (des->_val > val) pre=des,des = des->_left;
			else
			{
				if (des->_left == nullptr)
				{
					if (pre == _root)
					{
						_root = pre->_right;
					}
					// 左为空
					else if (pre->_left == des)
					{
						pre->_left = des->_right;
					}
					else
					{
						pre->_right = des->_right;
					}
					delete des;
					des = nullptr;
					
				}
				else if (des->_right == nullptr)
				{
					if (pre == _root) _root = _root->_left;
					else if (pre->_left == des)
						pre->_left = des->_left;
					else pre->_right = des->_left;
					delete des;
					des = nullptr;
				}
				else
				{
					// 两边都不是空节点
					pre = des;// 必须要将pre节点进行转移
					Node* cur = des->_left;
					// 进行找节点的时候必须保证这个子树不是空树
					// 找左树的最右节点
					while (cur->_right)
					{
						pre = cur;
						cur = cur->_right;
					}
					swap(cur->_val, des->_val);
					pre->_right = cur->_left;
					delete cur;
					cur = nullptr;
				}
				break;
			}
		}
	}
  1. 必须在查找目标删除节点的时候就要提供pre节点的位置——在目标节点的左右有节点为空的时候需要立即知道pre节点并直接进行链接
  2. 删除的点是否为根节点
    <1> 目标节点的左右有空节点的情况
    需要考虑删除的点是根节点(需要特殊判断)
    <2> 在目标节点的左右不为空的情况
    不需要考虑这个点是否为根节点,他的变换规则是找到左边最大的或者右边最小的交换,所以不需要考虑是否为根节点
  3. 循环终止条件是找到了nullptr依旧没有找到目标节点
  4. insert中,pre需要一起更新;在pop中,在查找过程中更新,不能一起更新,如果des已经找到了目标节点,但是你在已进入循环就更新,那直接就将pre移动到了需要删除的点的位置,当左右节点有空的时候就找不到pre节点

AVL

概念

任意节点的左右高度 < 2 ,并且使用平衡因子——右树高度-左树高度

insert

pop不需要知道,如果想知道,可以去网上找找

		void insert(const T& val)
		{
			Node* node = new Node(val);
			if (_root == nullptr)
			{
				_root = node;
				return;
			}
			Node* des = _root, * pre = _root;
			while (des)
			{
				pre = des;
				if (des->_val < val) des = des->_right;
				else if (des->_val) des = des->_left;
				else assert(false);
			}
			if (pre->_val < val) pre->_right = node, pre->_bf++;
			else pre->_left = node, pre->_bf--;
			node->_parent = pre;
			// 进行调整
			Node* cur = pre;
			pre = cur->_parent;
			while (pre && cur->_bf)
			{
				if (pre->_left == cur) pre->_bf--;
				else pre->_bf++;
				if (pre->_bf == -2 && cur->_bf == -1)
				{
					rotateR(pre);
					break;
				}
				else if (pre->_bf == 2 && cur->_bf == 1)
				{
					rotateL(pre);
					break;
				}
				else if (pre->_bf == -2 && cur->_bf == 1)
				{
					rotateLR(pre);
					break;
				}
				else if (pre->_bf == 2 && cur->_bf == -1)
				{
					rotateRL(pre);
					break;
				}
				else
				{
					cur = pre;
					pre = cur->_parent;
				}
			}
		}
		void rotateL(Node* pre)
		{
			Node* subR = pre->_right, *subRL = subR->_left;
			Node* ppre = pre->_parent;
			subR->_parent = ppre;
			if (pre == _root)
			{
				_root = subR;
			}
			else
			{
				if (ppre->_right == pre) ppre->_right = subR;
				else ppre->_left = subR;
			}
			pre->_parent = subR;
			subR->_left = pre;
			pre->_right = subRL;
			if (subRL) subRL->_parent = pre;
			pre->_bf = subR->_bf = 0;
		}
		void rotateR(Node* pre)
		{
			Node* subL = pre->_left, *subLR = subL->_right;
			Node* ppre = pre->_parent;
			subL->_parent = ppre;
			if (pre == _root)
			{
				_root = subL;
			}
			else
			{
				if (ppre->_right == pre) ppre->_right = subL;
				else ppre->_left = subL;
			}
			pre->_parent = subL;
			subL->_right = pre;
			pre->_left = subLR;
			if (subLR) subLR->_parent = pre;
			pre->_bf = subL->_bf = 0;
		}
		void rotateRL(Node* pre)
		{
			Node* subR = pre->_right;
			int bf = subR->_left->_bf;
			rotateR(subR);
			rotateL(pre);
			if (bf == 1) pre->_bf = -1;
			else subR->_bf = 1;
		}
		void rotateLR(Node* pre)
		{
			Node* subL = pre->_left;
			int bf = subL->_right->_bf;
			rotateL(subL);
			rotateR(pre);
			if (bf == -1) pre->_bf == 1;
			else subL->_bf = -1;
		}
  1. 插入第一个节点对根节点进行特判
  2. 插入的时候需要知道pre节点,插入的同时要调整平衡因子
  3. 注意循环更新条件while (pre && cur->_bf) ,我们要更新的是pre节点,所以pre必须要有;cur->bf 如果为0的话,证明子树已经平衡,不会影响上面;如果bf是1,可能还有向上影响的可能需要继续向上
  4. 在代码复用上,一定要小心,需要在复用的时候,将需要变化的位置进行改变才行
  5. 单旋的时候需要注意pre节点是根节点以及subLR节点是空节点的情况
  6. 双旋平衡因子更新是不同的,需要特别分析

左右双旋
在这里插入图片描述

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

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

相关文章

P1259 黑白棋子的移动题解

题目 有2n个棋子排成一行&#xff0c;开始为位置白子全部在左边&#xff0c;黑子全部在右边&#xff0c;如下图为n5的情况&#xff1a; 移动棋子的规则是&#xff1a;每次必须同时移动相邻的两个棋子&#xff0c;颜色不限&#xff0c;可以左移也可以右移到空位上去&#xff0c…

【C++】内存管理方式--new/delete

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

Repo命令使用实例(三十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

(01)Hive的相关概念——架构、数据存储、读写文件机制

目录 一、架构及组件介绍 1.1 Hive整体架构 1.2 Hive组件 1.3 Hive数据模型&#xff08;Data Model&#xff09; 1.3.1 Databases 1.3.2 Tables 1.3.3 Partitions 1.3.4 Buckets 二、Hive读写文件机制 2.1 SerDe 作用 2.2 Hive读写文件流程 2.2.1 读取文件的过程 …

BUGKU-WEB 你必须让他停下

题目描述 题目截图如下&#xff1a; 进入场景看看&#xff1a; 解题思路 图片会消失,那应该是使用了js来控制根据提示,那就是要停止js才会看到flag (也就是要抓包,不要陷入停止js的思维) 相关工具 F12大法Burp Suit抓包工具 解题步骤 出现图片的时候,源码中确实出现…

ICLR 2023#Learning to Compose Soft Prompts for Compositional Zero-Shot Learning

组合零样本学习&#xff08;CZSL&#xff09;中Soft Prompt相关工作汇总&#xff08;一&#xff09; 文章目录 组合零样本学习&#xff08;CZSL&#xff09;中Soft Prompt相关工作汇总&#xff08;一&#xff09;ICLR 2023#Learning to Compose Soft Prompts for Compositional…

Android之Android.bp文件格式语法(一百八十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

力扣hot3--并查集+哈希

第一想法是排个序然后遍历一遍&#xff0c;but时间复杂度就超啦 并查集居然与哈希结合了&#xff08;&#xff09; 已经好久没用过并查集了&#xff0c;&#xff0c;&#xff0c;我们用哈希表f_node中来记录原结点的父节点&#xff0c;其中key是原结点&#xff0c;value是父节点…

Github项目推荐-Tiny-Rdm

项目地址 GitHub - tiny-craft/tiny-rdm: A Modern Redis GUI Client 项目简述 一个开源的Redis管理工具&#xff0c;有漂亮的界面和丰富的功能。使用的编程语言如下 项目截图

【Qt】环境安装与初识

目录 一、Qt背景介绍 二、搭建Qt开发环境 三、新建工程 四、Qt中的命名规范 五、Qt Creator中的快捷键 六、QWidget基础项目文件详解 6.1 .pro文件解析 6.2 widget.h文件解析 6.3 widget.cpp文件解析 6.4 widget.ui文件解析 6.5 main.cpp文件解析 七、对象树 八、…

对什么都不感兴趣,怎么办?

这大概是现代社会&#xff0c;最为常见的都市病。 很多人大抵都明白&#xff1a;好的生活是什么样的呢&#xff1f;要有一个大目标&#xff0c;再分拆成一个个小目标&#xff0c;每天朝着目标前进&#xff0c;看着自己的进步和成长&#xff0c;转化为成就感和动力 —— 对不对&…

揭秘Angular世界的奥秘:全面提升你的前端开发技能!

介绍&#xff1a;Angular是一个由Google维护的开源JavaScript框架&#xff0c;专为构建Web应用程序而设计&#xff0c;特别适合开发大型单页应用&#xff08;SPA&#xff09;。以下是对Angular的详细介绍&#xff1a; 技术栈&#xff1a;Angular使用HTML作为模板语言&#xff0…

C++集群聊天服务器 nginx+redis安装 笔记 (中)

一、nginx安装 nginx: download 下载nginx安装包 hehedalinux:~/package$ tar -zvxf nginx-1.24.0.tar.gz nginx-1.24.0/ nginx-1.24.0/auto/ nginx-1.24.0/conf/ nginx-1.24.0/contrib/ nginx-1.24.0/src/ nginx-1.24.0/configure nginx-1.24.0/LICENSE nginx-1.24.0/README…

言语残疾和言语残疾分级

言语残疾和言语残疾分级 言语残疾&#xff0c;指各种原因导致的不同程度的言语障碍&#xff0c;经治疗一年以上不愈或病程超过两年&#xff0c;而不能或难以进行正常的言语交流活动&#xff0c;以致影响其日常生活和社会参与。包括&#xff1a;失语、运动性构音障碍、器质性构音…

黑马程序员——移动Web——day02

目录 空间转换 空间转换简介平移视距旋转左手法则rotate3d-了解立体呈现案例-3d导航缩放动画 动画实现步骤animation复合属性animation拆分写法案例-走马灯精灵动画多组动画综合案例-全名出游 背景云彩位置和动画文字动画 1.空间转换 空间转换简介 空间&#xff1a;是从坐标…

ITK 图像分割(一):阈值ThresholdImageFilter

效果&#xff1a; Video: 区域增加分割 1、itkThresholdImageFilter 该类的主要功能是通过设置低阈值、高阈值或介于高低阈值之间&#xff0c;则将图像值输出为用户指定的值。 如果图像值低于、高于或介于设置的阈值之间&#xff0c;该类就将图像值设置为用户指定的“外部”值…

山西电力市场日前价格预测【2024-02-10】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2024-02-10&#xff09;山西电力市场全天平均日前电价为126.73元/MWh。其中&#xff0c;最高日前电价为302.95元/MWh&#xff0c;预计出现在08:15。最低日前电价为0.00元/MWh&#xff0c;预计出…

Stable Diffusion之最全详解图解

Stable Diffusion之最全详解图解 1. Stable Diffusion介绍1.1 研究背景1.2 学术名词 2.Stable Diffusion原理解析2.1 技术架构2.2 原理介绍扩散过程 3.1 Diffusion前向过程3.2 Diffusion逆向&#xff08;推断&#xff09;过程 1. Stable Diffusion介绍 Stable Diffusion是2022…

分布式文件系统 SpringBoot+FastDFS+Vue.js【一】

分布式文件系统 SpringBootFastDFSVue.js【一】 一、分布式文件系统1.1.文件系统1.2.什么是分布式文件系统1.3.分布式文件系统的出现1.3.主流的分布式文件系统1.4.分布式文件服务提供商1.4.1.阿里OSS1.4.2.七牛云存储1.4.3.百度云存储 二、fastDFS2.1.fastDSF介绍2.2.为什么要使…

跟着pink老师前端入门教程-day26

一、计算机编程基础 &#xff08;一&#xff09;编程语言 1、编程 编程&#xff1a;就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码&#xff0c;并最终得到结果的过程。 计算机程序&#xff1a;就是计算机所执行的一系列的指令集合&#xff0c;而程序全部…