腾讯云智面经

STL容器,vector实现,map实现,迭代器失效

1.序列式容器

vector:
优势 随机访问,下标访问
.size() 返回向量的长度

vector<string> path = {
	"path1",
	"path2",
	"path3"
};

pair
pair常和vector配合,用来存储map:

#include <utility>  //pair的头文件
using std::pair;

vector<pair<string,int>> vec;

deque 双端队列
优势 头尾增删:在容器首尾插入和删除元素。如:对服务窗口先来先服务的情况

list list 双向链表
优势 中间增删:在容器中间插入和删除元素

2.关联式容器
set和map只允许唯一key值 (即有去重功能),且按升序排序。
multiset和multimap可以存多个相同的key值。

set
分类
①集合 set:字符串升序排序、自动去重
插入:insert() 删除:erase()
②多重集合 multiset:字符串排序、不去重

set
①自动去重
②升序排序
③要键值对:字典
map插入:insert map遍历:迭代器iterator
注意,map的key必须是唯一的。不同key可以拥有相同的value

vector与list的区别?

vector是顺序存储的动态数组,list是链式存储的双向链表。
顺序存储查找效率高,链式存储增删效率高。

C++中vector<pair*>和直接使用map有什么区别?

答:①效率:map可以根据key在O(logN)时间内搜索到value。而vector< pair>查找的复杂度是O(N)。
②方便程度:map更方便,比如可以用key直接索引到value,自动初始化key项,所以针对这种特殊的需求,直接用map更好。

C++迭代器失效

这里有几个常见的情况会导致迭代器失效:

  1. 容器重新分配内存:当向一个动态大小的容器(如std::vector)中添加元素,而容器需要扩大其内部存储空间时,所有指向该容器的迭代器都会失效。这是因为容器会创建一个新的、更大的内存块来存放数据,并将旧数据复制到新位置,然后释放旧的内存。因此,任何指向原内存地址的迭代器都会失效。

  2. 删除元素:从容器中删除元素可能会导致迭代器失效。例如,在std::liststd::vector中删除一个元素后,指向该元素的迭代器将不再有效。对于std::mapstd::set等关联容器,删除元素同样会使指向该元素的迭代器失效。

  3. 插入元素:虽然在许多容器中插入元素不会使现有迭代器失效(例如std::list),但在一些情况下,如上述的std::vector需要重新分配内存时,插入操作仍可能导致迭代器失效。

为了避免迭代器失效带来的问题,可以采取以下几种策略:

  • 使用范围循环:对于支持范围循环的语言(如C++11及更高版本),使用范围循环可以避免直接处理迭代器,从而减少迭代器失效的风险。
  • 检查并更新迭代器:在执行可能使迭代器失效的操作之后,检查迭代器的有效性,并在必要时重新获取迭代器。
  • 使用索引而不是迭代器:对于支持随机访问的容器(如std::vector),使用索引访问元素比使用迭代器更安全,因为即使容器重新分配了内存,索引值仍然有效。
  • 选择合适的容器:根据具体需求选择最合适的容器类型。例如,如果频繁插入和删除元素,可能应该选择链表(std::list)而非向量(std::vector),因为前者在这些操作下迭代器失效的风险较低。

java里面map是否线程安全,如何实现一个线程安全的map

java里面map接口类里包含
HashMap 线程不安全
TreeMap 线程不安全
LinkedHashMap 线程不安全
Hashtable 线程安全

Innodb

事务安全:支持ACID(原子性、一致性、隔离性、持久性)事务,适用于需要高度一致性和可靠性的工作负载。
行级锁定:提供行级锁定(包括Next-Key Locks),在高并发环境下可以减少锁定资源的竞争,提高并发性能。
聚簇索引:数据按照主键顺序存储在聚簇索引中,对主键查询非常高效,且支持覆盖索引。
外键支持:支持外键约束,确保数据引用完整性。
崩溃恢复:具有自动崩溃恢复能力,通过重做日志(Redo Log)和回滚日志(Undo Log)确保数据的一致性和完整性。
其他特性:包括插入缓冲(Insert Buffer)、自适应哈希索引(Adaptive Hash Index)、多版本并发控制(MVCC)等。

描述InnoDB存储引擎的ACID特性是如何实现的?

ACID 是数据库管理系统中事务处理的四个关键属性:原子性(Atomicity) 、一致性(Consistency) 、隔离性(Isolation) 、和持久性(Durability) 。

原子性 :InnoDB通过事务日志(undo log)来保证操作的原子性。每个事务开始时,InnoDB会记录一个日志点(LSN),如果事务失败或回滚,InnoDB将使用undo log来恢复之前的状态。
一致性 :一致性是通过原子性、隔离性和持久性的结合来实现的。InnoDB确保数据库从一个一致的状态转换到另一个一致的状态,同时遵循预定义的规则,如外键约束。
隔离性 :InnoDB通过多版本并发控制(MVCC)实现事务的隔离性。它允许多个事务看到自己版本的数据库快照,通过这种方式减少了锁的需要,提高了并发性能。
持久性 :InnoDB使用重做日志(redo log)来确保事务的持久性。在事务提交时,相关的修改会先被写入到redo log中,并在之后某个时间点,通过后台线程异步地刷新到磁盘上。即使发生系统崩溃,已提交的事务也能通过重做日志恢复。

InnoDB的索引结构是如何设计的,它与MyISAM的区别在哪里?

InnoDB采用B+树索引模型,它支持主键索引和二级索引(也称为辅助索引)。

主键索引 :在InnoDB中,表是根据主键顺序组织存储的,这种方式称为聚集索引。每个表只能有一个聚集索引,如果没有显式定义主键,InnoDB会自动选择一个唯一非空索引代替。
二级索引 :辅助索引包含索引列和指向聚集索引记录的指针。因此,二级索引的查找可能涉及两次索引查找:先在二级索引中找到对应的主键,然后再在主键索引中找到实际的行。
与MyISAM相比,InnoDB的最大区别在于它支持事务和行级锁定。MyISAM只支持表级锁定,并且不支持ACID事务。此外,MyISAM的索引是保存在单独的文件中,而InnoDB的数据和索引是存储在同一个文件中。

解释InnoDB的锁机制及其种类

InnoDB提供了多种锁机制,包括行级锁、表级锁和意向锁,以支持不同级别的数据访问控制。

行级锁 :InnoDB支持两种类型的行级锁:共享锁(S锁)和排他锁(X锁)。共享锁允许事务读取一行数据,排他锁允许事务更新或删除一行数据。
表级锁 :虽然InnoDB主要使用行级锁,但在某些情况下,如对整个表进行扫描时,它也会使用表级锁。
意向锁 :意向锁是表级锁,表明事务打算在表中的行上加上行级锁。存在两种类型的意向锁:意向共享锁(IS锁)和意向排他锁(IX锁)。
InnoDB的锁机制支持高并发的数据访问,同时减少了死锁的可能性。

如何理解InnoDB的多版本并发控制(MVCC)?

MVCC 是一种用于实现数据库事务隔离的技术,它允许事务读取数据的早期版本,从而在不锁定资源的情况下增加并发性。InnoDB实现MVCC主要依赖于undo log,每当数据被修改时,InnoDB都会将原始数据保存在undo log中。

在InnoDB中,每条记录实际上都有额外的系统字段,包括DB_TRX_ID(最后修改记录的事务ID)、DB_ROLL_PTR(指向undo log的指针)和DB_ROW_ID(自动生成的行ID,作为隐藏的聚集索引)。

MVCC在InnoDB中支持两种隔离级别的实现:可重复读(REPEATABLE READ)和读已提交(READ COMMITTED)。

在可重复读 隔离级别下,事务在第一次读取数据时创建一个快照,之后的查询操作都会访问这个快照,从而确保数据的一致性。
在读已提交 隔离级别下,每个SELECT语句都会创建自己的快照。

InnoDB日志系统如何工作,包括undo log和redo log?

InnoDB的日志系统包括两部分:undo log 和redo log ,它们共同支持事务的ACID特性。

undo log 用于在事务失败或执行ROLLBACK时回滚更改。它保存了事务开始前数据的旧版本,使数据库能够恢复到之前的状态。
redo log 用于恢复提交的事务修改,以保证持久性。即使数据库发生崩溃,系统也可以通过redo log重放操作来恢复数据。
redo log是循环使用的,由一系列固定大小的文件组成,形成redo log buffer。当事务提交时,更改首先记录到redo log buffer中,然后异步刷新到磁盘上的redo log文件中。这种设计减少了磁盘I/O操作,从而提高了性能。

InnoDB中的事务隔离级别及其如何实现?

InnoDB支持四种标准的SQL事务隔离级别:读未提交(READ UNCOMMITTED)、读已提交(READ COMMITTED)、可重复读(REPEATABLE READ)和串行化(SERIALIZABLE)。

读未提交 :事务可以读取其他事务未提交的修改,这可能导致脏读。
读已提交 :事务只能读取到其他事务已提交的修改。
可重复读 :是InnoDB的默认隔离级别,保证在事务内读取的数据前后一致,即使其他事务提交了新的修改。
串行化 :通过强制事务顺序执行,以及对所有读取的数据加锁,来避免并发问题。
InnoDB主要通过undo log实现不同的隔离级别,结合锁机制(如行锁和间隙锁)来控制事务之间的并发访问,确保数据的一致性和隔离性。

解释InnoDB的页面结构和记录格式

InnoDB的数据文件是由页面(Page)组成的,每个页面默认大小为16KB。页面是InnoDB磁盘管理的基本单位,它们可以包含不同类型的信息,如B+树节点、系统事务信息等。

InnoDB支持多种记录格式,主要包括COMPACT 和REDUNDANT 格式。从MySQL 5.0.3开始,默认的记录格式是COMPACT,它相对于REDUNDANT格式来说,存储效率更高,因为它使用了更少的空间来存储null值和变长字段的长度。

如何优化InnoDB的性能?

优化InnoDB性能涉及多个方面,包括但不限于:

配置InnoDB缓冲池大小 :InnoDB缓冲池是存储数据页和索引页的内存区域。适当增加其大小可以显著提高数据库操作的速度。
调整redo log的大小和数量 :适当增加redo log文件的大小和数量可以减少磁盘I/O,提高事务的处理速度。
使用合理的索引策略 :确保查询经常使用的列被索引,避免不必要的全表扫描。
分析和优化查询 :使用EXPLAIN命令分析查询的执行计划,优化慢查询。
并发插入操作 :InnoDB支持并发插入,当表的末尾没有竞争时,可以提高插入操作的性能。
避免锁竞争 :合理设计事务逻辑和数据访问模式,减少锁竞争,提高并发性能。

如何监控和优化InnoDB的性能?

监控和优化InnoDB的性能是确保数据库高效运行的关键。可以通过以下方式来监控和优化InnoDB:

使用性能监控工具 :如MySQL的性能模式(Performance Schema)和信息模式(INFORMATION_SCHEMA)提供了丰富的监控数据,可以帮助识别潜在的性能瓶颈。
优化查询 :通过分析慢查询日志来识别和优化慢查询,使用索引来加快查询速度。
配置InnoDB参数 :合理配置InnoDB的缓冲池大小(innodb_buffer_pool_size)、日志文件大小(innodb_log_file_size)等参数,可以显著提高性能。
分析表结构和索引设计 :确保数据模型和索引设计适合应用程序的访问模式。

InnoDB的表空间管理如何工作?

InnoDB存储引擎使用表空间(tablespace)来组织数据。默认情况下,所有的表和索引都存储在一个共享的表空间文件(ibdata1)中,但也可以配置为每个表使用独立的表空间文件。

使用独立表空间文件可以提高数据管理的灵活性,比如可以更容易地将表迁移到不同的磁盘上。此外,它还可以在某些情况下提高性能,因为并发操作不同表时磁盘I/O操作更分散。

InnoDB的备份和恢复策略有哪些?

InnoDB支持物理备份和逻辑备份两种方式:

物理备份 :直接复制数据文件、日志文件和配置文件。这种方法备份速度快,恢复也简单,但缺点是备份集较大。工具如Percona XtraBackup可以进行热备份,即在数据库运行时进行备份而不影响数据库操作。
逻辑备份 :通过导出SQL语句来备份数据库,如使用mysqldump工具。逻辑备份允许更灵活的恢复选项,比如仅恢复选定的表或数据库,但备份和恢复速度通常比物理备份慢。

InnoDB与其他存储引擎的比较?

与其他MySQL存储引擎相比,InnoDB提供了一些独特的特性和优势:

支持事务 :InnoDB提供完全的ACID事务支持,而如MyISAM之类的存储引擎则不支持。
行级锁定和MVCC :InnoDB通过行级锁定和MVCC提供高并发性,而MyISAM只支持表级锁。
崩溃恢复 :InnoDB通过redo log支持崩溃后的自动恢复,提高了数据的可靠性。
外键约束 :InnoDB支持外键约束,有助于维护数据的完整性。
这些特性使InnoDB成为了许多高负载、需要事务支持的应用的首选存储引擎。

分布式一致性算法——Paxos 和 Raft 算法

添加链接描述

排序算法

1. 冒泡排序 (Bubble Sort)

  • 原理:通过重复遍历列表,比较相邻元素并根据需要交换它们的位置,直到没有任何一对元素需要交换为止。
  • 时间复杂度:平均和最坏情况均为 O(n^2),最好情况为 O(n)。
  • 稳定性:稳定。

2. 插入排序 (Insertion Sort)

  • 原理:将数组分成已排序和未排序两部分,每次从未排序部分取出第一个元素,插入到已排序部分的合适位置。
  • 时间复杂度:平均和最坏情况均为 O(n^2),最好情况为 O(n)。
  • 稳定性:稳定。

3. 选择排序 (Selection Sort)

  • 原理:每次从未排序部分选出最小(或最大)的元素,将其放到已排序部分的末尾。
  • 时间复杂度:O(n^2)。
  • 稳定性:不稳定。

4. 快速排序 (Quick Sort)

  • 原理:通过一个分区操作,将数组分成左右两部分,左边的元素都不大于右边的元素,然后递归地对这两部分进行快速排序。
  • 时间复杂度:平均情况为 O(n log n),最坏情况为 O(n^2)。
  • 稳定性:不稳定。

5. 归并排序 (Merge Sort)

  • 原理:采用分治策略,将数组分成两半,分别对这两半进行排序,然后合并两个有序数组。
  • 时间复杂度:O(n log n)。
  • 稳定性:稳定。

6. 堆排序 (Heap Sort)

  • 原理:利用堆的数据结构进行排序。首先构建一个最大堆(或最小堆),然后将堆顶元素与最后一个元素交换,再重新调整堆,重复此过程。
  • 时间复杂度:O(n log n)。
  • 稳定性:不稳定。

7. 计数排序 (Counting Sort)

  • 原理:适用于一定范围内的整数排序。通过计算每个不同关键字的数量,确定每个关键字应该放置的位置。
  • 时间复杂度:O(n + k),其中 k 是数据范围。
  • 稳定性:稳定。

8. 桶排序 (Bucket Sort)

  • 原理:将数组分到有限数量的桶里,每个桶再分别排序(可能使用其它排序算法或者递归使用桶排序)。
  • 时间复杂度:平均情况为 O(n),最坏情况为 O(n^2)。
  • 稳定性:稳定。

9. 基数排序 (Radix Sort)

  • 原理:基于键值的每一位进行排序,通常从最低有效位开始排序,逐步到最高有效位。
  • 时间复杂度:O(nk),其中 k 是数字的位数。
  • 稳定性:稳定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值