C++语言相关的常见面试题目(三)

1. List底层实现原理

省流: list底层实现了一个双向循环链表。

每个元素(或节点)包含三个部分:数据域(_M_Storage)、前驱指针(_M_prev)、后继指针(_M_next)。

数据域:存储实际数据。

前驱指针:指向链表中当前节点之前的一个节点。

后继指针:指向链表中当前节点之后的一个节点

此外,存在一个特殊节点,通常称为哨兵节点(sentinel node)或者空节点。这个节点不存储用户定义的数据,其主要作用是简化边界条件处理。在双向循环链表的实现中,这个空节点同时作为头节点和尾节点的前驱和后继,使得链表形成一个闭环。

# 构造与析构
list<T>():默认构造函数,创建一个空的list。
list<T>(size_type n, const T& value):构造一个包含n个重复值value的list。
list<T>(const list<T>&):拷贝构造函数。
~list():析构函数,释放list占用的所有资源。
# 赋值操作
list<T>& operator=(const list<T>&):赋值运算符,复制另一个list的内容给当前list。
assign(iterator first, iterator last):将[first, last)区间内的元素赋值给list。
# 大小操作
size_type size() const:返回list中元素的数量。
bool empty() const:如果list为空则返回true,否则返回false。
void resize(size_type sz, T c = T()):调整list的大小到sz,若增加则用c填充新位置。
# 元素访问
reference front():返回第一个元素的引用。
const_reference front() const:返回第一个元素的常量引用。
reference back():返回最后一个元素的引用。
const_reference back() const:返回最后一个元素的常量引用。
# 插入与删除
iterator insert(iterator position, const T& val):在position指定的位置插入val。
void push_back(const T& val):在list末尾添加一个元素。
void push_front(const T& val):在list开头添加一个元素。
iterator erase(iterator position):删除position指定的元素并返回下一个元素的迭代器。
iterator erase(iterator first, iterator last):删除[first, last)区间内的所有元素。
void pop_back():删除最后一个元素。
void pop_front():删除第一个元素。
# 迭代器操作
iterator begin():返回指向list第一个元素的迭代器。
const_iterator begin() const:返回指向list第一个元素的常量迭代器。
iterator end():返回指向list末尾的下一个位置的迭代器。
const_iterator end() const:返回指向list末尾的下一个位置的常量迭代器。
# 其他操作
void swap(list<T>& x):交换两个list的内容。
void remove(const T& val):删除所有值为val的元素。
template <class Predicate> void remove_if(Predicate pred):根据谓词pred删除元素。
void reverse():反转list中的元素顺序。
void sort():按升序排序list中的元素(注意:list的sort函数是特化的,不能直接使用std::sort)。
void merge(list<T>& x):合并x到当前list中,要求list已排序。

2. deque的底层实现原理

deque底层基于分段数组实现,结合了动态数组和双向链表的特点。

deque继承自_Deque base。整体结构可以分为两部分:指针数组和迭代器。

指针数组:首位元素的地址空间、指针数组容量大小

迭代器:当前正在遍历的元素、当前连续空间的首尾地址,还有指向当前空间的指针(存储在指针数组中)

基础API:

# 构造与析构
deque<T>():默认构造函数,创建一个空的deque。
deque<T>(size_type n, const T& value):构造一个包含n个重复值value的deque。
deque<T>(const deque<T>&):拷贝构造函数。
deque<T>(initializer_list<T>):使用初始化列表构造deque。
~deque():析构函数,释放deque占用的所有资源。
# 赋值操作
deque<T>& operator=(const deque<T>&):赋值运算符,复制另一个deque的内容给当前deque。
assign(iterator first, iterator last):将[first, last)区间内的元素赋值给deque。
assign(size_type n, const T& value):将deque的元素替换为n个value。
# 大小操作
size_type size() const:返回deque中元素的数量。
bool empty() const:如果deque为空则返回true,否则返回false。
void resize(size_type sz, T c = T()):调整deque的大小到sz,若增加则用c填充新位置。
# 元素访问
reference front():返回第一个元素的引用。
const_reference front() const:返回第一个元素的常量引用。
reference back():返回最后一个元素的引用。
const_reference back() const:返回最后一个元素的常量引用。
# 注意:deque不直接支持下标运算符[]进行随机访问,但迭代器可用于遍历。
# 插入与删除
iterator insert(iterator position, const T& val):在position指定的位置插入val。
void push_back(const T& val):在deque末尾添加一个元素。
void push_front(const T& val):在deque开头添加一个元素。
iterator erase(iterator position):删除position指定的元素并返回下一个元素的迭代器。
iterator erase(iterator first, iterator last):删除[first, last)区间内的所有元素。
void pop_back():删除最后一个元素。
void pop_front():删除第一个元素。
# 迭代器操作
iterator begin():返回指向deque第一个元素的迭代器。
const_iterator begin() const:返回指向deque第一个元素的常量迭代器。
iterator end():返回指向deque末尾的下一个位置的迭代器。
const_iterator end() const:返回指向deque末尾的下一个位置的常量迭代器。
# 其他操作
void swap(deque<T>& x):交换两个deque的内容。
void clear():清空deque中的所有元素。

3.  multiset的实现原理 

概括:基于红黑树实现,允许键值重复的有序集合

简单介绍一下红黑树。红黑树是一种自平衡的二叉搜索树,它具有以下特性:

  1. 每个节点都带有颜色属性,可以是红色或黑色。
  2. 根节点和叶子节点(NIL 节点)都被认为是黑色的。
  3. 如果一个节点是红色的,则它的子节点必须是黑色的(也就是说,不能有两个相邻的红色节点)。
  4. 从任一节点到其每个叶子(NIL 节点)所经过的黑色结点数目相同。

STL multiset底层函数成员:

_Rb_tree:这是一个模板类,表示红黑树。红黑树是一种自平衡二叉搜索树,广泛用于实现关联容器(如 set 和 map)。key_type:这是红黑树中键的类型。它通常是用户定义的类型,用于标识红黑树中的元素。value_type:这是红黑树中值的类型。对于 set,key_type 和 value_type 是相同的;对于 map,value_type 是 std::pair<const key_type, mapped_type>。_Identity<value_type>:这是一个函数对象,用于返回值本身。在红黑树中,它用于从节点中提取键值对。key_compare:这是一个比较函数对象,用于比较键的大小。它决定了红黑树的排序规则。Key_alloc_type:这是一个分配器类型,用于管理红黑树中节点的内存分配。_Rep_type:这是一个类型别名,表示一个 _Rb_tree 类型的对象。通过 typedef,我们可以使用 _Rep_type 来引用 _Rb_tree<key_type, value_type, _Identity<value_type>, key_compare, Key_alloc_type> 类型。

主要API使用说明:

# 构造、复制、销毁
multiset();
explicit multiset(const Compare& comp); // Compare 是比较元素的函数对象类型。
template <class InputIterator> multiset(InputIterator first, InputIterator last, const Compare& comp = Compare()); // InputIterator 是输入迭代器类型,能够从first到last
# 遍历元素。
multiset(const multiset& ms);
~multiset();
# 元素访问(尽管直接访问接口较少,但迭代器可用于间接访问)
# 通过迭代器遍历,如上面提到的iterator, const_iterator, reverse_iterator, const_reverse_iterator。
# 迭代器
iterator begin(); // 返回multiset类型迭代器,指向第一个元素。
const_iterator begin() const;
iterator end(); // 返回multiset类型迭代器,指向最后一个元素之后的位置。
const_iterator end() const;
reverse_iterator rbegin(); // 反向迭代器,指向最后一个元素。
const_reverse_iterator rbegin() const;
reverse_iterator rend(); // 反向迭代器,指向第一个元素之前的位置。
const_reverse_iterator rend() const;
# 容量
bool empty() const;
size_type size() const; // size_type 是无符号整数类型,足够大以存储容器中可能的最大元素数量。
size_type max_size() const; // 返回理论上容器能容纳的最大元素数量。
# 修改
pair<iterator,bool> insert(const value_type& x); // value_type 是容器中存储的元素类型,iterator指向新插入元素或已存在的相等元素的位置,bool指示是否插入了新元素。
iterator insert(iterator position, const value_type& x); // 在迭代器position指示的位置附近插入元素,返回指向插入元素的迭代器。
template <class InputIterator> void insert(InputIterator first, InputIterator last); // 插入区间内的元素。
void erase(iterator position); // 删除迭代器position所指的元素。
size_type erase(const key_type& x); // 删除所有键值等于x的元素,返回删除的数量。
void swap(multiset& x); // 交换两个multiset的内容。
# 查找
iterator find(const key_type& x); // 返回指向键值等于x的第一个元素的迭代器,如果不存在则返回end()。
const_iterator find(const key_type& x) const;
size_type count(const key_type& x) const; // 返回键值等于x的元素数量。
iterator lower_bound(const key_type& x); // 返回第一个键值不低于x的元素的迭代器。
const_iterator lower_bound(const key_type& x) const;
iterator upper_bound(const key_type& x); // 返回第一个键值大于x的元素的迭代器。
const_iterator upper_bound(const key_type& x) const;
pair<iterator,iterator> equal_range(const key_type& x); // 返回一个迭代器对,分别指向键值等于x的元素范围的首尾。
pair<const_iterator,const_iterator> equal_range(const key_type& x) const;
# 比较
bool operator==(const multiset& x) const;
bool operator!=(const multiset& x) const;
bool operator<(const multiset& x) const;
bool operator>(const multiset& x) const;
bool operator<=(const multiset& x) const;
bool operator>=(const multiset& x) const;

4. 优先级队列的实现原理

 STL内部使用最大最小堆实现优先级队列,STL中的priority_queue默认使用的底层数据结构是vector。这个容器适配器底层实现了一个最大堆,利用vector来存储元素,因为vector提供了快速的随机访问能力。

常用API:

构造函数:priority_queue<T>:默认构造函数,创建一个空的优先队列,默认使用 std::less<T> 作为比较函数。
explicit priority_queue(const Compare& comp):使用指定的比较函数 comp 创建一个空的优先队列。
成员函数:size_t size() const:返回优先队列中元素的数量。
bool empty() const:判断优先队列是否为空,若为空则返回 true,否则返回 false。
const T& top() const:获取优先级最高(即顶部)元素的引用,并不删除该元素。
void push(const T& value):将元素插入到优先队列中,并保持堆结构。
template <class... Args> void emplace(Args&&... args):通过传递参数直接构造新元素并插入到优先队列中,并保持堆结构。
void pop():删除顶部(即最高优先级)元素。

5. 迭代器的底层实现原理?有哪几种迭代器?

迭代器的定义:实现了一种访问容器内元素但是不会暴露容器内部实现的方式。

迭代器底层原理核心包括:

(1) 模拟指针操作:通过类对象模拟指针行为,重载解引用和递增/递减操作符,实现对容器元素的访问与遍历。

(2)标准化接口:提供一套统一的接口规范,确保不同容器迭代器的兼容性和互换性。

(3)与容器互动:依赖容器实现间接访问元素,不直接管理内存,需考虑容器变化导致的迭代器失效问题。

(4)类型系统与泛型编程:利用类型推导和模板技术,自动匹配容器类型,实现泛型迭代。

(5)抽象与解耦:隐藏容器内部结构,使算法独立于数据结构,提高代码复用性和灵活性。

这是一条吃饭博客,由挨踢零声赞助。学C/C++就找挨踢零声,加入挨踢零声,面试不挨踢!

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

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

相关文章

Mysql 数据库主从复制-CSDN

查询两台虚拟机的IP 主虚拟机IP 从虚拟机IP服务 修改对应的配置文件 查询对应配置文件的命令 find / -name my.cnf编辑对应的配置文件 主 my.cnf &#xff08;部分配置&#xff09; [mysqld] ########basic settings######## server_id 1 log_bin /var/log/mysql/mysql-…

gnome 建议安装的扩展

安装 扩展管理器&#xff1a; sudo apt install gnome-shell-extension-manager在 扩展管理器 里搜索并添加 扩展 推荐 Applications Menu&#xff1a;自带。左上角显示 应用程序 按钮&#xff0c;以下拉菜单分类显示应用RunCat&#xff1a;状态栏里显示一只猫和 cpu 利用率…

[激光原理与应用-98]:南京科耐激光-激光焊接-焊中检测-智能制程监测系统IPM介绍 - 2 - 什么是激光器焊接? 常见的激光焊接技术详解

目录 一、什么是激光焊接 1.1 概述 1.2 激光焊接的优点 二、激光焊接的应用 2.1 哪些场合必须使用激光焊接 1. 汽车制造业 2. 航空航天领域 3. 电子行业&#xff1a;消费类电子3C 4. 医疗器械制造 5. 新能源锂电池行业 6. 其他领域 三、激光焊接的分类 3.1 按焊接…

【ONLYOFFICE8.1】ONLYOFFICE8.1版本桌面编辑器测评

有宝子说office太贵&#xff0c;不适合个人和学生&#xff0c;而WPS不仅贵广告还多&#xff0c;那么有没有一款软件可以替代office和WPS呢&#xff1f;...当然有喽。当当当当&#xff01;它就是众望所归、备受好评的ONLYOFFICE。下面就和小编一起来探索和测评一下ONLYOFFICE8.1…

深入解析怀庄之醉酱酒的独特魅力

在众多美酒中&#xff0c;酱酒以其独有的风格和丰富的文化内涵&#xff0c;赢得了无数鉴赏家的青睐。本文旨在从专业角度深入探讨酱酒的空杯留香现象、典型色泽特性及品鉴技巧&#xff0c;揭示其背后的科学原理与艺术魅力&#xff0c;助您更全面地理解与欣赏这一中华传统佳酿。…

C++报错无法访问Private

严重性 代码 说明 项目 文件 行 禁止显示状态 错误 C2248 “main::Person::~Person”: 无法访问 private 成员(在“main::Person”类中声明) #include<iostream> #include<ctime> int main() {using namespace std;class Person{//Per…

响应式设计的双璧:WebKit 支持 CSS Flexbox 和 Grid 布局深度解析

响应式设计的双璧&#xff1a;WebKit 支持 CSS Flexbox 和 Grid 布局深度解析 在现代网页设计中&#xff0c;响应式布局是实现跨设备兼容性的关键。CSS Flexbox 和 Grid 作为 CSS 布局的两大支柱&#xff0c;提供了强大的工具来构建灵活和复杂的用户界面。WebKit&#xff0c;作…

JS的块级作用域是什么

在JavaScript中&#xff0c;块级作用域&#xff08;Block Scope&#xff09;是指变量或函数在代码块&#xff08;如{}内的代码区域&#xff09;中声明后&#xff0c;其作用域被限制在这个块级结构内部。这意味着&#xff0c;块外部的代码无法访问块内部声明的变量或函数&#x…

Linux之三剑客(grep、sed、awk)

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

LeetCode热题100刷题8:54. 螺旋矩阵、73. 矩阵置零、48. 旋转图像

54. 螺旋矩阵 class Solution { public:vector<int> spiralOrder(vector<vector<int>>& matrix) {vector<int> vec;if(matrix.empty())return vec;int left0;int right matrix[0].size()-1;int up0;int down matrix.size()-1;while(true) {for(i…

探索 WebKit 的网络脉络:深入网络栈的设计艺术

探索 WebKit 的网络脉络&#xff1a;深入网络栈的设计艺术 在当今这个以网页为中心的时代&#xff0c;WebKit 作为众多流行浏览器的心脏&#xff0c;其网络栈的设计对于网页内容的加载、处理和渲染起着至关重要的作用。本文将深入探讨 WebKit 网络栈的架构和设计&#xff0c;揭…

Nuxt:父子组件传值

在Nuxt中&#xff0c;父子组件间的数据传递数据有两种方法&#xff0c;如下 1、 props 父组件通过props将数据传递给子组件&#xff0c;子组件通过props接收数据。代码如下&#xff1a; <template><div><ChildLeft :msg"msg"></ChildLeft>…

代码随想录-DAY④-相交链表经典三解——leetcode 160

解法一&#xff1a;哈希集合 思路 将链表 A 中的每个节点都存入哈希集合&#xff0c; 遍历链表 B 并判断每一个节点&#xff0c; 如果发现已存在在哈希集合中的&#xff0c;说明相交&#xff0c; 如果遍历结束&#xff0c;说明不相交。 时间复杂度&#xff1a;O(mn) 空间…

CentOS 6.5 配置国内在线yum源和制作openssh 9.8p1 rpm包 —— 筑梦之路

CentOS 6.5比较古老的版本了&#xff0c;而还是有一些古老的项目仍然在使用。 环境说明 1. 更换国内在线yum源 CentOS 6 在线可用yum源配置——筑梦之路_centos6可用yum源-CSDN博客 cat > CentOS-163.repo << EOF [base] nameCentOS-$releasever - Base - 163.com …

C组暑假第一次训练题解

A.寄包柜 题意 两种操作 1.在第i个柜子第j个格子输入 2.输出第i个柜子第j个格子的数字 分析 因为i和j最大为1e5&#xff0c;使用二维数组会爆空间&#xff0c;使用map即可解决 代码 #include<iostream> #include<algorithm> #include<cstring> #incl…

Java中线程的常用方法(并发编程基础)

Java中线程的常用方法 sleep 调用sleep会让当前线程从Running进入TIMED WAITING状态其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时sleep方法会抛出InterruptedException睡眠结束后的线程未必会立刻得到执行建议用TimeUnit的sleep代替Thread的sleep来获得更好的可读…

均匀采样信号的鲁棒Savistky-Golay滤波(MATLAB)

S-G滤波器又称S-G卷积平滑器&#xff0c;它是一种特殊的低通滤波器&#xff0c;用来平滑噪声数据。该滤波器被广泛地运用于信号去噪&#xff0c;采用在时域内基于多项式最小二乘法及窗口移动实现最佳拟合的方法。与通常的滤波器要经过时域&#xff0d;频域&#xff0d;时域变换…

掌握 IPython:灵活运用系统环境变量

掌握 IPython&#xff1a;灵活运用系统环境变量 在数据科学和编程的广阔天地中&#xff0c;IPython 以其强大的交互式功能成为了探索和实验的利器。但你知道吗&#xff1f;IPython 同样能够与系统环境变量进行交互&#xff0c;这使得我们能够更灵活地控制我们的代码和环境。本…

ubuntu22 使用ufw防火墙

专栏总目录 一、安装 sudo apt update sudo apt install ufw 二、启动防火墙 &#xff08;一&#xff09;启动命令 sudo ufw enable &#xff08;二&#xff09;重启命令 sudo ufw reload 三、配置规则 #允许SSH连接 sudo ufw allow ssh #如果sshd服务端口指定到了8888&a…

Oracle PL / SQL 插入insert

INSERT是SQL的数据操作语言的一部分的SQL关键字之一。 DML可以操作关系数据库中的数据。 让我们从INSERT语句的第一种形式开始&#xff0c;INSERT ... VALUES。 INSERT ... VALUES 以下代码显示如何使用DML的INSERT VALUES子语句。 INSERT INTO authors ( id, name, birth_d…