自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(417)
  • 收藏
  • 关注

原创 PlayerFeedback 插件开发日志

**PlayerFeedback 是一款基于 Spigot/Paper 1.21+ 的 Kotlin 插件,旨在为 Minecraft 服务器提供完善的玩家反馈系统。核心功能包括多样化的反馈提交(Bug报告、建议、举报等)、多轮对话互动、智能评价系统(支持8种评价类型)和可视化GUI界面。系统采用SQLite存储数据,支持管理员通过命令和界面管理反馈,包含状态流转、实时通知和统计报告功能。特色设计包括动态筛选排序、反馈评价互动和模板化回复机制,为服务器管理提供高效工具。

2025-11-03 10:41:57 793

原创 如果你要去实现share_ptr,它的引用计数你准备用什么去存储?正常类型还是静态类型?

如果你要去实现share_ptr,它的引用计数你准备用什么去存储?正常类型还是静态类型?

2025-10-22 09:55:31 294

原创 自己实现share_ptr怎么实现?

如何实现shared_ptr?shared_ptr的核心是引用计数机制,允许多个指针共享同一对象。实现要点:1)包含对象指针和引用计数指针;2)构造时初始化引用计数为1;3)拷贝构造/赋值时递增引用计数;4)析构时递减引用计数,当计数归零时释放对象;5)需重载解引用和箭头操作符。关键操作包括:构造函数、拷贝控制、引用计数管理(增/减/归零释放)以及指针操作支持。注意处理空指针情况,确保线程安全(实际实现需加锁)。

2025-10-22 09:50:23 134

原创 冒泡排序的时间复杂度多少?

摘要:冒泡排序的时间复杂度在最坏和平均情况下为O(n²),最好情况下为O(n)。最坏情况出现在完全逆序数组,需要进行n(n-1)/2次比较和交换;最好情况是已排序数组,仅需n-1次比较。空间复杂度为O(1),属于原地排序。冒泡排序是稳定的,可通过标志位优化提前终止。虽然简单但效率不高,适合小规模数据或教学使用。实际应用中通常会选择更高效的排序算法。

2025-10-22 09:36:51 326

原创 怎么实现堆?

本文介绍了最大堆的实现原理和方法。最大堆是一种完全二叉树,其中父节点值总大于子节点值,通常用数组存储。文章详细说明了最大堆的核心操作:插入元素时先放到数组末尾,然后通过heapifyUp向上调整;删除最大值时将末尾元素移至根部,再通过heapifyDown向下调整。文中提供了完整的C++实现代码,包括获取父/子节点索引、堆调整等核心函数。最后指出堆操作的时间复杂度(插入删除为O(logn),查看最大值为O(1))及其应用场景(优先队列、堆排序、Dijkstra算法等),并说明最小堆只需反向比较即可实现。

2025-10-21 09:44:26 221

原创 有一个服务器,用于提供HTTP服务,但是需要限制每个用户在任意的100秒内只能请求60次,怎么实现这个功能

摘要:本文讨论了如何实现HTTP服务的限流功能,要求在任意100秒内每个用户最多请求60次。提出了两种解决方案:1)使用时间戳队列记录请求时间,精确但内存消耗大;2)滑动窗口计数器方案,内存效率高但精度稍低。文中还建议考虑线程安全、内存清理和分布式环境等扩展问题。作者倾向于第二种方案,认为其内存效率高且精度足够满足多数场景需求。

2025-10-21 09:37:43 366

原创 LeetCode - 50. Pow(x, n)

本文介绍了快速计算x的n次幂的优化算法。传统循环方法时间复杂度为O(n),而快速幂算法通过分治思想将时间复杂度降至O(logn)。算法核心是将问题分解:当n为偶数时,x^n=x^(n/2)*x^(n/2);当n为奇数时,x^n=x^(n/2)*x^(n/2)*x。同时处理了n为负数及边界情况,如n取最小值时的溢出问题。通过递归实现,每次将问题规模减半,显著提高了计算效率。示例代码展示了该算法的实现方式。

2025-10-16 10:07:21 358

原创 互斥锁的优缺点

互斥锁是一种常用的线程同步机制,具有实现简单、数据安全性高、标准化程度高等优点,能有效避免竞态条件。但其也存在性能开销大、可能引发死锁、优先级反转等问题。合理使用互斥锁需要权衡锁粒度,过粗影响并发性能,过细则增加复杂度。在实际开发中,应根据具体场景选择合适的同步方案,对于高性能场景可考虑无锁编程等替代方案。

2025-10-16 09:57:01 678

原创 堆如何保证这样一个父节点比子节点大的性质呢?

本文介绍了维护堆性质的两种核心操作:上浮和下沉。插入新元素时采用上浮操作,将新元素置于堆尾后与父节点比较并交换,直至找到合适位置;删除根节点时则采用下沉操作,将末尾元素移至根节点后与子节点比较交换。两种操作的时间复杂度均为O(logn),通过这种"自我修复"机制能有效维护堆的结构特性。文章通过具体实例演示了操作过程,展示了堆的动态调整原理。

2025-10-15 09:57:48 236

原创 介绍一下堆是什么?和完全二叉树区别是什么?

堆是一种满足两个条件的数据结构:1.结构上是完全二叉树;2.满足堆序性质(父节点值≥或≤子节点)。完全二叉树仅要求结构上每层从左到右填充,而堆在此基础上还需满足数值关系。例如大顶堆中每个父节点值必须≥子节点值。堆一定是完全二叉树,但完全二叉树不一定是堆。堆常用于优先队列和堆排序,因其能快速获取最大/最小值。两者的核心区别在于堆额外要求数值关系,而完全二叉树只关注结构形态。

2025-10-15 09:41:51 188

原创 能解释一下时间复杂度的含义吗?O(1)复杂度是什么意思?

时间复杂度是衡量算法执行效率的指标,表示数据量增大时算法所需时间的变化。O(1)复杂度是最理想的情况,表示无论数据量多大,执行时间都是固定的。例如直接查找数组元素或哈希表查询都是O(1)操作,就像直接查看自己的身份证号一样,不受数据规模影响。

2025-10-15 09:11:18 188

原创 LeetCode - 1171.

摘要:题目要求删除链表中所有和为0的连续节点序列。采用前缀和方法,通过两次遍历实现:第一次遍历记录每个前缀和最后出现的节点位置,第二次遍历直接跳过中间和为0的子序列。时间复杂度O(n),空间复杂度O(n)。关键点在于利用前缀和相同则中间段和为0的特性,并使用哈希表存储最远出现位置来一次性处理重叠子序列。

2025-10-14 09:33:04 721

原创 C和C++管理动态内存的方式

C/C++动态内存管理对比:C语言使用malloc/calloc/realloc/free进行底层内存操作,不调用构造/析构函数;C++则提供new/delete运算符(自动调用构造/析构)和智能指针(unique_ptr/shared_ptr/weak_ptr)实现更安全的对象生命周期管理。主要区别在于C++支持自动构造/析构和RAII机制,能有效避免内存泄漏,而C语言仅进行原始内存分配。现代C++推荐使用智能指针替代手动内存管理。

2025-10-14 09:30:51 140

原创 tcp和udp中,如果要求传输效率比较高用哪种协议

摘要:选择TCP还是UDP取决于对"传输效率"的定义。UDP适合要求高速传输和实时性的场景(如视频直播、在线游戏),因其无连接开销、头部简单、无需确认重传和拥塞控制。TCP则能保证数据完整性,适合对可靠性要求高的场景。选择依据是业务对丢包的容忍度:重速度选UDP,重可靠选TCP。

2025-10-14 09:15:24 220

原创 http的get,pust,put几种请求方式有什么区别

HTTP请求方法的主要区别在于用途和特性: GET:用于获取数据,参数显示在URL中,安全性较低但有缓存功能,适用于查询操作(如搜索、列表展示)。典型特征为幂等性(多次请求结果相同)和长度限制(约2KB)。 POST:用于创建资源或提交数据,参数在请求体中,适合敏感信息和大量数据(如注册、文件上传)。不具备幂等性,多次请求可能产生多个资源。 PUT:用于完整更新资源,需传递完整对象数据,具有幂等性(多次更新结果一致)。与POST的核心区别在于幂等性和操作对象(PUT更新已知ID资源,POST创建新资源)。

2025-10-13 09:35:26 409

原创 线程不加锁如何实现同步?

本文介绍了无锁同步的两种主要方法:原子操作和CAS。原子操作通过CPU指令保证操作的不可中断性,适用于计数器等简单场景。CAS采用乐观策略,通过比较并交换实现同步,更适合竞争不激烈的场景。文章还分析了CAS的ABA问题及解决方案,并建议根据实际复杂度选择合适方法。

2025-10-11 09:32:04 292

原创 线程同步是什么?为什么要同步,有哪些同步的方法

线程同步是协调多线程访问共享资源的技术,防止数据竞争和不一致。当多个线程同时修改共享数据时(如count++),可能引发错误结果。常见同步方法包括:互斥锁(std::mutex)、读写锁(std::shared_mutex)、条件变量、信号量、原子操作(std::atomic)、自旋锁和屏障。实际开发中优先考虑原子操作提升性能,复杂场景使用互斥锁+条件变量组合,并通过RAII机制(如std::lock_guard)自动管理锁以避免死锁。这些方法能有效解决线程安全问题,确保程序正确性。

2025-10-11 09:20:01 419

原创 静态多态有哪些实现方法,重载原理,在编译的哪个阶段?

C++静态多态的实现方法包括函数重载、运算符重载和模板。重载原理基于名字修饰,编译器通过参数类型、个数和顺序为每个重载函数生成唯一内部名称。静态多态解析发生在编译期的语义分析阶段(函数重载)和模板实例化阶段,具有零运行时开销的优势,与动态多态形成对比。返回值类型不参与重载决议。

2025-10-11 09:09:12 325

原创 如何理解C++的面向对象编程,不要背八股文,给出自己的理解?关键点是:抽象

面向对象编程的核心是抽象思维,通过将现实概念映射为代码中的类和对象。以图形系统为例,抽象出Shape基类定义通用行为(绘制、计算面积),具体图形继承实现。这种抽象带来三大优势:1)隔离变化,遵循开闭原则;2)降低复杂度,避免条件判断;3)提升扩展性,新增类型无需修改已有代码。作者通过数据源处理项目实践,验证了抽象接口使业务逻辑与具体实现解耦的优越性。本质是将系统分层,绑定数据与行为,使代码更符合人类思维且易于维护。但需注意避免过度设计,根据实际需求权衡抽象程度。

2025-10-10 10:02:23 392

原创 vector是如何扩容的

vector扩容机制基于动态数组实现,当元素数量(size)达到容量(capacity)时触发。扩容过程包括:按1.5倍或2倍因子分配新内存、拷贝/移动数据、释放旧内存并更新指针。不同编译器采用不同增长因子(GCC用2倍,MSVC用1.5倍)。频繁扩容影响性能,建议用reserve预分配空间。注意扩容会导致迭代器失效,继续使用可能引发未定义行为。

2025-10-10 09:43:42 380

原创 push_back和emplace_back区别

摘要:push_back和emplace_back都用于向容器末尾添加元素,但构造方式不同。push_back会先创建临时对象再拷贝/移动到容器,而emplace_back直接在容器内存中原地构造对象,避免了临时对象的创建。对于复杂对象,emplace_back效率更高,而简单类型差异不大。虽然移动语义减少了push_back的性能损失,但emplace_back在避免额外构造方面仍更优。

2025-10-10 09:36:50 167

原创 二叉树和红黑树的区别

摘要:红黑树是一种自平衡二叉搜索树,相比普通二叉搜索树,它通过节点颜色和平衡规则(如根节点为黑色、无连续红节点等)确保树的高度平衡。这使得红黑树在最坏情况下仍能保持O(logn)的操作效率,而普通二叉搜索树可能退化为O(n)。虽然实现较复杂,但红黑树广泛应用于Linux进程调度、C++ STL等需要稳定性能的场景。

2025-10-09 09:12:23 304

原创 管道和消息队列的区别

管道和消息队列是两种进程间通信方式,主要区别在于:管道基于字节流,无明确消息边界,适合简单的进程间通信;消息队列基于消息块,有明确边界,支持多对多通信。管道生命周期与进程绑定,容量较小;消息队列由内核维护,独立于进程,容量更大。管道适合父子进程通信,消息队列更适用于复杂分布式系统的异步处理场景。

2025-10-09 09:01:52 257

原创 一个全局int变量,两个线程A,B,分别对这个全局变量进行++操作,每个线程一万次,问这个全局变量最后是多少?

在多线程环境下,两个线程同时对全局int变量执行1万次++操作,最终结果通常小于预期的2万。这是因为++操作(读取-修改-写入)不是原子性的,线程间可能发生竞态条件,导致部分增量丢失。实际结果可能在1万到2万之间波动。解决方案包括使用互斥锁(mutex)或原子类型(std::atomic)来确保操作的原子性。这是多线程编程中典型的数据竞争问题,正确地处理共享资源访问至关重要。

2025-09-30 09:52:17 243

原创 #define和const的区别

#define和const的主要区别在于:#define是预处理阶段的文本替换,无类型检查,作用域全局;const是编译阶段处理的类型安全常量,遵循变量作用域。const支持指针操作、调试查看,可用于类成员;而#define不占内存但不能用于类。现代C++推荐优先使用const而非#define,以提升类型安全性和可维护性。

2025-09-30 09:38:19 175

原创 Linux下的内存管理

Linux内存管理采用分页机制实现进程隔离与共享,使用多级页表优化地址转换。物理内存通过伙伴系统分配,SLAB/SLUB管理小对象。页面回收机制(kswapd、LRU链表)和交换空间处理内存压力,支持参数调优(swappiness等)。提供free、vmstat等工具监控内存状态,cgroups限制进程组资源使用。

2025-09-28 10:02:22 427

原创 菱形继承,虚继承?A为虚基类,B、C虚继承A,D普通继承于B,C,有几份虚表,如何调用

摘要:C++虚继承通过virtual关键字解决菱形继承问题,确保虚基类A在D中只有一份实例。示例中,A为虚基类,B、C虚继承A,D继承B、C,共产生5个虚表:D的主虚表、B/C的子对象虚表及各自虚表。虚函数调用通过虚基类表指针间接寻址完成。虚继承特点包括:唯一实例保证、派生类负责构造、访问需额外开销。典型应用如iostream避免ios基类重复继承。但虚继承复杂且影响性能,建议优先使用组合替代多重继承。(150字)

2025-09-28 09:56:18 715

原创 在数据库事务中的一致性是什么意思

摘要:数据库事务中的一致性(Consistency)是ACID特性之一,指事务执行前后数据库必须保持有效状态,满足预定义规则。例如转账事务需保持金额总数不变。一致性通过完整性约束(主键、外键等)、业务逻辑、原子性/隔离性机制及触发器/存储过程来保证,与其他ACID特性协同确保数据可靠性。

2025-09-26 09:49:35 229

原创 间隙锁以及其作用

间隙锁是MySQL InnoDB在可重复读隔离级别下的特殊锁机制,锁定记录间的间隙而非记录本身。其核心作用是防止幻读,通过Next-Key Lock(记录锁+间隙锁)确保事务一致性,但会降低并发性能。在不需要严格防幻读的场景,可考虑使用读已提交隔离级别来避免间隙锁的开销。(99字)

2025-09-26 09:39:44 158

原创 说明一下各种生命周期的类型

C++中变量的生命周期类型包括:自动存储期(局部变量)、静态存储期(全局/静态变量)、动态存储期(new/delete管理)和线程存储期(thread_local)。不同类型决定变量的创建和销毁时机:自动变量随作用域结束销毁,静态变量持续整个程序运行,动态变量需手动管理,线程变量随线程生命周期变化。合理选择变量存储类型对编写高效、无内存泄漏的代码至关重要。

2025-09-26 09:31:48 249

原创 【无标题】

C++内存管理主要涉及栈/堆内存分配和智能指针。栈内存由编译器自动管理,堆内存需手动使用new/delete操作符分配释放。C++11引入unique_ptr、shared_ptr等智能指针实现自动内存管理,遵循RAII原则。最佳实践建议优先使用智能指针和容器类,避免裸指针操作,同时注意防止内存泄漏等常见问题。性能关键场景可考虑内存池优化。

2025-09-26 09:26:39 227

原创 c++和java的区别是什么

C++和Java的主要区别包括:内存管理(C++手动/Java自动)、平台依赖性(C++依赖特定平台/Java跨平台)、语言特性(C++更底层/Java更安全)。C++适合高性能场景如系统编程和游戏开发,Java则更适合企业应用和移动开发。

2025-09-26 09:22:21 190

原创 复合索引在使用上有什么注意事项

复合索引使用需注意:遵循最左匹配原则,查询条件必须包含首列;查询条件顺序不影响优化器识别;范围查询会中断后续索引匹配;避免过度索引导致存储和写入负担;优先将高区分度列前置;利用覆盖索引减少回表操作提升性能。合理设计复合索引可显著优化查询效率。

2025-09-26 09:14:03 151

原创 数据库索引,什么是复合索引

复合索引是将多个字段组合创建的数据库索引,遵循"最左匹配原则",即查询必须包含最左列才能生效。比如索引(name,age,city)支持name或name+age的查询,但不支持单独age查询。复合索引比单列索引更高效,能减少索引数量、节省空间,并可能实现覆盖索引避免回表操作。设计时应将高选择性、常用查询列放在前面,同时注意索引会增加写操作开销。

2025-09-26 09:11:31 261

原创 最左匹配底层的原理,是什么原因导致会出现这个原则

最左匹配原则源于B+树索引的工作机制。MySQL查询时从左至右依次比较索引列,直到条件不满足或比较完所有列。该原则存在是因为复合索引按列从左到右物理排序存储。例如索引(a,b,c)先按a排序,a相同按b排,再按c排。若查询不含最左列a,索引失效,必须全表扫描。这类似于查字典需要首个字母才能快速定位。最左匹配原则本质是由B+树的数据结构特性决定的,缺少最左列就失去了排序依据。

2025-09-26 09:04:29 403

原创 服务器上有两张网卡,如何选择哪个网卡发送消息

服务器多网卡选择发送消息的方法主要由系统路由表决定。Linux通过策略路由机制,根据目标IP匹配度、路由优先级和度量值(metric)选择最优网卡。管理员可通过iproute命令、设置网卡权重、基于源地址路由或应用层绑定等方式控制选择。实际应用中可按业务需求配置路由策略,如内外网分流、负载均衡等,也可通过网卡绑定实现高可用和带宽提升。

2025-09-25 09:50:45 341

原创 当你登上服务器的时候发现特别卡,怎么排查

服务器卡顿排查方法: 使用top/htop检查CPU、内存和负载情况 通过psaux分析高CPU进程 用free-m查看内存使用,关注swap情况 使用iostat/iotop检查磁盘IO 用netstat/iftop监控网络连接和流量 检查应用日志和数据库慢查询 查看定时任务(crontab)是否影响性能 从CPU、内存、磁盘、网络四个维度系统排查

2025-09-25 09:49:15 255

原创 野指针的成因,如何预防

野指针是指向无效内存的指针,常见成因包括未初始化、释放后继续使用和超出作用域。预防方法:初始化置空、释放后立即置空、使用智能指针、避免返回局部变量地址、采用RAII模式。实际开发中建议多用智能指针和容器,减少原始指针操作,以降低风险。(98字)

2025-09-25 09:14:20 137

原创 C++中类和结构体的区别

C++中类和结构体的核心区别在于默认访问权限与继承方式:类成员默认私有,结构体默认公有;类继承默认私有,结构体继承默认公有。结构体适合简单数据集合,类更适合需要封装的复杂场景。尽管功能几乎相同,这种设计差异反映了不同的编程意图。

2025-09-25 09:08:09 129

原创 LRU怎么实现,说一下具体思路

摘要:LRU缓存通过哈希表和双向链表结合实现,哈希表提供O(1)查询,双向链表维护访问顺序。get操作时若存在则移动节点至头部;put操作时更新或新增节点至头部,若缓存满则删除尾部节点。这种设计确保所有操作在O(1)时间内完成。

2025-09-23 09:46:00 177

耗时一个月,15万字+的Linux思维导图!!!

耗时一个月,15万字+的Linux思维导图!!!

2025-05-31

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除