当前位置: 首页 > news >正文

利用红黑树封装map和set

前言:

我们已经学过了如何去实现一棵完整的红黑树,而我们所知道的map和set容器的底层都是由红黑树实现的,因此我们今天来学习如何用红黑树来实现封装map和set。

本来我们需要两个红黑树去分别封装map和set,但是代码会有重复、冗余,因此我们采用泛型编程的思想,同一颗红黑树通过传不同的模板参数来分别实现map和set。就是为了复用同一个类模板的红黑树,让代码变的简洁,体现了泛型编程的思想。

比如这里的模板参数T,如果传的是K类型的,代表使用的是set,如果参数传的是pair类型的就代表是map。

问题:为什么要用两个模板参数,前面的K有什么用,我们不是只需要后面的T就可以区分这两个容器了吗?

当我们使用find这个函数的时候,传的参数必须是K类型的,因为如果我们只传后面的T模板参数,那么使用map查找值的时候,find函数的查找值的类型不可能是pair类型的,因此这里我们需要多添加一个模板参数,让find()的时候,保持一致。

这里又有一个问题,我们如何比较T类型的值?

在insert函数里面,我们需要通过比较T类型的值大小,但是如果是pair类型的值,如何比较呢?

下面是系统默认的pair的比较方式

,这与我们的比较理念有偏差,我们只希望比较first内容的值,不让second内容的值参与进来,那我们该如何解决呢?

利用仿函数解决。

我们之前只知道仿函数可以用来比较大小,但其实仿函数可以做很多事情。

比如这里,我们定义了一个仿函数之后呢,你给仿函数一个值,仿函数就会返回一个其他的值

KeyOfT仿函数 取出T对象中的key

但是在红黑树中,不清楚T类型到底是K还是key-value,但是map和set知道,因此我们可以将这个仿函数定义在我们的map和set里面,进行一个传参。

下面是map的仿函数

template<class K, class V>class map{struct MapKeyOfT{const K& operator()(const pair<K, V>& kv){return kv.first;}};public:typedef typename RBTree<K, pair<const K, V>, MapKeyOfT>::iterator iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}bool insert(const pair<K, V>& kv){return _t.Insert(kv);}private:RBTree<K, pair<const K, V>, MapKeyOfT> _t;};

set的仿函数

	template<class K>class set{struct SetKeyOfT{const K& operator()(const K& key){return key;}};public:typedef typename RBTree<K, const K, SetKeyOfT>::iterator iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}bool insert(const K& key){return _t.Insert(key);}private:RBTree<K, const K, SetKeyOfT> _t;};

上面便是仿函数的新玩法

红黑树迭代器的实现:

++it如何实现,总体思路还是左子树、根节点、右子树的中序遍历

  1. it指向结点,右不为空,下一个就是右子树的最左结点
  2. it指向结点,右为空,意味这个结点的子树中序访问完了,下一个结点找祖先里面孩子 == 父亲左的那个祖先

原码:

template<class T>
struct RBTreeIterator
{typedef RBTreeNode<T> Node;typedef RBTreeIterator<T> Self;Node* _node;RBTreeIterator(Node* node):_node(node){}T& operator*(){return _node->_data;}T* operator->(){return &_node->_data;}Self& operator++(){if (_node->_right){// 右子树的中序第一个(最左节点)Node* subLeft = _node->_right;while (subLeft->_left){subLeft = subLeft->_left;}_node = subLeft;}else{// 祖先里面孩子是父亲左的那个Node* cur = _node;Node* parent = cur->_parent;while (parent && cur == parent->_right){cur = parent;parent = cur->_parent;}_node = parent;}return *this;}Self& operator--(){// return *this;}bool operator!=(const Self& s){return _node != s._node;}bool operato==(const Self& s){return _node == s._node;}
};

而我们的map和set只需要调用相应的接口即可。

typename的妙用

如何复用红黑树?

--it?

相关文章:

利用红黑树封装map和set

前言&#xff1a; 我们已经学过了如何去实现一棵完整的红黑树&#xff0c;而我们所知道的map和set容器的底层都是由红黑树实现的&#xff0c;因此我们今天来学习如何用红黑树来实现封装map和set。 本来我们需要两个红黑树去分别封装map和set&#xff0c;但是代码会有重复、冗…...

python pyqt5暂停和恢复功能

在PyQt5中&#xff0c;你可以通过结合按钮和事件处理来实现暂停和恢复功能。以下是一个简单的示例代码&#xff0c;演示了如何在PyQt5应用程序中实现暂停和恢复功能。 import sys from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButton, QVBoxLayout, QWidget,…...

CAN总线详解-理论知识部分

目录 CAN总线简介 CAN总线硬件电路 CAN电平标准 CAN收发器 ​编辑 CAN物理层特性 CAN总线帧格式 数据帧 数据帧格式 数据帧发展历史 遥控帧 错误帧 过载帧 帧间隔 位填充 波形实例 CAN总线接收方数据采样 接收方数据采样遇到的问题 位时序 硬同步 再同步 波…...

【Java数据结构】---List(LinkedList)

乐观学习&#xff0c;乐观生活&#xff0c;才能不断前进啊&#xff01;&#xff01;&#xff01; 我的主页&#xff1a;optimistic_chen 我的专栏&#xff1a;c语言 &#xff0c;Java 欢迎大家访问~ 创作不易&#xff0c;大佬们点赞鼓励下吧~ 文章目录 前言链表&#xff08;MyS…...

开发军用LabVIEW程序注意事项

在开发军用LabVIEW程序时&#xff0c;开发者需要从多个角度仔细考虑&#xff0c;以满足军方对安全性、可靠性、法规遵从性等方面的严格要求。由于军事系统通常涉及高度敏感的信息和严苛的环境条件&#xff0c;程序的设计必须保证数据的保密性、系统的稳定性以及与各种军事标准的…...

A3VLM: Actionable Articulation-Aware Vision Language Model

发表时间&#xff1a;13 Jun 2024 作者单位&#xff1a;SJTU Motivation&#xff1a;以往的机器人VLM如RT-1[4]、RT-2[3]和ManipLLM[21]都专注于直接学习以机器人为中心的动作。这种方法需要收集大量的机器人交互数据&#xff0c;这在现实世界中非常昂贵。 解决方法&#xf…...

企业高性能web服务器

web服务器介绍 Apache HTTP Server&#xff1a;也称为Apache&#xff0c;是一个开源的HTTP服务器&#xff0c;目前是全球使用最广泛的Web服务器 Nginx&#xff1a;Nginx是一个高性能的HTTP和反向代理服务器&#xff0c;也是一个IMAP/POP3/SMTP服务器 Microsoft Internet Inform…...

数据库:深入解析SQL分组与聚合——提升数据查询效率的关键技巧

数据库&#xff1a;深入解析SQL分组与聚合——提升数据查询效率的关键技巧 在数据分析和数据库管理中&#xff0c;SQL 的分组与排序操作是不可或缺的工具。本篇博客将深入探讨 GROUP BY 和 ORDER BY 的使用方法&#xff0c;并通过实际案例说明如何通过分组实现数据聚合以及如何…...

【CSS】数字英文css没有转换成...换行点、没有换行、拆分的问题(非常常见的需求)

默认情况下&#xff0c;连续的英文或数字文本不会在空格处换行&#xff0c;这可能导致布局问题。 解决方案 要解决这个问题&#xff0c;可以使用以下几种CSS属性&#xff1a; word-break: 控制单词如何换行。设置为break-all可以让任何字符都能成为换行点。word-wrap: 控制是…...

C++ string模拟实现

一 如何区分自定义类与标准库中的同名类 // string.h #define _CRT_SECURE_NO_WARNINGS 1 #pragma once #include<iostream> using namespace std;namespace bit {class string{} }// Test.cpp include "string.h"int main() {return 0; } 既然要模拟实现str…...

Lora 全文翻译

作者&#xff1a; 地点&#xff1a;hby 来源&#xff1a;https://arxiv.org/pdf/2106.09685 工具&#xff1a;文心 LORA: LOW-RANK ADAPTATION OF LARGE LANGUAGE MODELS 摘要 自然语言处理的一个重要范式包括在通用领域数据上进行大规模预训练&#xff0c;并适应特定任务或…...

结题阶段(2024年8月)

海门区教育科学 “十四五”规划2022年度立项课题 结题鉴定材料 课 题 名 称 高中信息技术项目化教学的研究与应用 课题负责人  郭书艳 所 在 单 位 江苏省包场高级中学 报 送 日 期   2024 年 6 月 20 日…...

贪吃蛇(C语言详解)

贪吃蛇游戏运行画面-CSDN直播 目录 贪吃蛇游戏运行画面-CSDN直播 1. 实验目标 2. Win32 API介绍 2.1 Win32 API 2.2 控制台程序&#xff08;Console&#xff09; 2.3 控制台屏幕上的坐标COORD 2.4 GetStdHandle 2.5 GetConsoleCursorlnfo 2.5.1 CONSOLE_CURSOR_INFO …...

国际以太网专线(IEPL)与国际专线(IPLC)服务

中国联通国际公司产品: 国际以太网专线 (IEPL)/国际专线&#xff08;IPLC&#xff09; 在全球化的今天&#xff0c;企业越来越依赖于高速、稳定且安全的国际网络连接来支持其跨国业务活动。中国联通国际公司作为中国领先的电信运营商之一&#xff0c;在这一领域提供了多种优质…...

vue 子父组件互相改值

在Vue.js中&#xff0c;子组件想要修改父组件的状态&#xff08;如数据属性的值&#xff09;时&#xff0c;通常遵循以下步骤&#xff1a; 父组件向子组件传递数据&#xff1a;通过props&#xff08;属性&#xff09;将需要被子组件操作的值传入子组件。例如&#xff0c;在父组…...

java之拼图小游戏(开源)

public class LoginJFrame extends JFrame {//表示登录界面&#xff0c;以后所有跟登录相关的都写在这里public LoginJFrame() {//设置界面的长和宽this.setSize(603,680);//设置界面的标题this.setTitle("拼图登陆界面");//设置界面置顶this.setAlwaysOnTop(true);/…...

Linux Shell批量测试IP连通性

Linux 通过Shell脚本来实现读取txt文件中的IP地址&#xff0c;并使用telnet对其后的所有端口进行测试&#xff0c;判断是否可以连接。每个IP地址的端口测试时间限制为5秒。 IP文件 : ips.txt 192.168.1.1 22,80,443 192.168.1.2 21,25,110 192.168.1.3 8080每一行包含一个IP地…...

已解决:anaocnda如何备份环境与安装环境

1.使用pip进行备份 激活对应的虚拟环境&#xff0c;切换到桌面或者想备份的位置。 备份即可&#xff1a; pip freeze > requirements.txt如何安装备份&#xff1f; pip install -r requirements.txt2.使用conda进行备份 激活对应的虚拟环境&#xff0c;切换到桌面或者想…...

自动化与高效设计:推理技术在FPGA中的应用

想象一下&#xff0c;你正在设计一个复杂的电路系统&#xff0c;就像在搭建一座精巧的积木城堡。你手头有各种形状和功能的积木块&#xff0c;这些积木块可以组合成任何你需要的结构。在这个过程中&#xff0c;你有两种主要的方法&#xff1a;一种是手动挑选和搭建每一块积木&a…...

对react模块和模块化理解

在React开发中&#xff0c;模块化和React模块是两个紧密相关但又有区别的概念。理解它们对于构建高效、可维护的React应用至关重要。 模块化 模块化是一种将大型代码库拆分成更小、更易于管理的部分&#xff08;即模块&#xff09;的软件设计技术。每个模块都封装了特定的功能…...

CAN总线-----帧格式

目录 前言 一、CAN总线帧格式分类 1.数据帧&#xff08;重点&#xff09; 2.遥控帧 3.错误帧 4.过载帧 5.间隔帧 二、位填充 三、波形实例 前言 本期我们就开始学习CAN总线的帧格式&#xff0c;对应帧格式的话&#xff0c;在前面我们学习I2C协议和SPI协议等协议的时候…...

UE网络同步(一) —— 一个项目入门UE网络同步之概念解释

最近在学习UE网络同步&#xff0c;发现了一个非常好的教程&#xff0c;并且附带了项目文件&#xff0c;这里从这个小项目入手&#xff0c;理解UE的网络同步 教程链接&#xff1a;https://www.youtube.com/watch?vJOJP0CvpB8w 项目链接&#xff1a;https://github.com/awforsyt…...

MATLAB中rsf2csf函数用法

目录 语法 说明 示例 将实数 Schur 形式变换为复数 Schur 形式 rsf2csf函数的功能是将实数 Schur 形式转换为复数 Schur 形式。 语法 [Unew,Tnew] rsf2csf(U,T) 说明 ​[Unew,Tnew] rsf2csf(U,T) 将实矩阵 X 的 [U,T] schur(X) 的输出从实数 Schur 形式变换为复数 Sc…...

Java基础 文字小游戏

souf System.out.printf("你好啊%s","张三") 输出你好啊张三 System.out.printn()放在中间可以换行 System.out.printf("%s你好啊%s","张三","李四") 输出 张三你好啊李四 只有输出没有换行效果。 制作一个文字小游戏…...

「数组」归并排序 / if语句优化|小区间插入优化(C++)

概述 在上一篇文章中&#xff0c;我们介绍了快速排序以及随机快速排序&#xff1a; 「数组」快速排序 / 随机值优化|小区间插入优化&#xff08;C&#xff09; 今天&#xff0c;我们来介绍归并排序。 相比于快速排序是冒泡排序融合了分治思想后形成的究极promax进化版&…...

颠覆传统 北大新型MoM架构挑战Transformer模型,显著提升计算效率

挑战传统的Transformer模型设计 在深度学习和自然语言处理领域&#xff0c;Transformer模型已经成为一种标准的架构&#xff0c;广泛应用于各种任务中。传统的Transformer模型依赖于一个固定的、按深度排序的层次结构&#xff0c;每一层的输出都作为下一层的输入。这种设计虽然…...

接口优化笔记

索引 添加索引 where条件的关键自动或者order by后面的排序字段可以添加索引加速查询 索引只能通过删除新增进行修改&#xff0c;无法直接修改。 # 查看表的索引 show index from table_name; show create table table_name; # 添加索引 alter table table_name add index …...

pandas 科学计数法显示

我注意到pandas中有一个问题&#xff0c; 默认情况下&#xff0c;就是其中的数据的小数位不能超过6位&#xff0c;比如0.0000007就会被显示为0&#xff0c;这个结果如下 全部以科学技术显示 import pandas as pd import numpy as np# 设置显示格式为科学计数法 pd.options.d…...

PHP正则替换字符串中的图片地址

在PHP中&#xff0c;可以使用preg_replace()函数来实现正则表达式的替换功能。以下是一个简单的例子&#xff0c;演示如何替换字符串中的图片地址。 double $str 图片地址1&#xff1a;<img src"http://example.com/image1.jpg"> 图片地址2&#xff1a;<i…...

基于多商户AI智能名片商城小程序的粉丝忠诚度提升策略:深度融合足额法则与多维度激励体系

摘要&#xff1a;在数字化浪潮的推动下&#xff0c;多商户AI智能名片商城小程序以其独特的商业模式和技术优势&#xff0c;正逐步成为连接商家与消费者&#xff0c;特别是粉丝群体的重要平台。本文深入探讨了如何通过深度融合足额法则与多维度激励体系&#xff0c;有效提升多商…...