当前位置: 首页 > 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;的软件设计技术。每个模块都封装了特定的功能…...

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

基于ASP.NET+ SQL Server实现(Web)医院信息管理系统

医院信息管理系统 1. 课程设计内容 在 visual studio 2017 平台上&#xff0c;开发一个“医院信息管理系统”Web 程序。 2. 课程设计目的 综合运用 c#.net 知识&#xff0c;在 vs 2017 平台上&#xff0c;进行 ASP.NET 应用程序和简易网站的开发&#xff1b;初步熟悉开发一…...

C# 类和继承(抽象类)

抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...

select、poll、epoll 与 Reactor 模式

在高并发网络编程领域&#xff0c;高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表&#xff0c;以及基于它们实现的 Reactor 模式&#xff0c;为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。​ 一、I…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...