自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 [LeetCode]100 链表-专题

本文介绍了合并K个升序链表的算法解决方案。该算法利用小顶堆数据结构,每次从K个链表的当前头节点中快速获取最小值节点。具体步骤包括:构建小顶堆存储各链表头节点,使用虚拟头节点简化操作,循环取出堆顶最小节点并拼接结果链表,同时将该节点的后继节点入堆。算法时间复杂度为O(NlogK),空间复杂度为O(K),其中N为总节点数,K为链表数量。代码实现使用优先级队列模拟小顶堆,通过自定义比较器确保堆顶始终为最小值节点,最终返回合并后的有序链表。

2026-04-01 01:33:55 191

原创 [C++]迭代器失效问题

摘要:本文分析了C++ vector容器中迭代器失效问题。通过insert()函数示例展示了当容器扩容时,原有迭代器因指向被释放的内存空间而失效,导致数据插入异常(出现随机值)。失效原因包括内存重分配和插入位置错误。解决方案是在扩容后,通过记录偏移量并重新计算迭代器位置来更新失效的迭代器。最终实现保证了数据正确插入,避免了未定义行为。该案例揭示了迭代器失效机制及解决方法。

2025-11-30 18:52:19 503 1

原创 [c++]string赋值运算符重载:从“砸碗“到优雅的“换碗仪式“

赋值运算符重载是解决对象深拷贝问题的关键。当类包含动态资源时,默认的浅拷贝会导致双重释放和内存泄漏。传统方法需手动分配新内存、复制数据并释放旧内存,但存在自赋值风险。现代"拷贝-交换"方法更优雅:通过拷贝构造创建临时对象,交换资源后让临时对象析构清理旧资源。这种写法简洁安全,自动处理自赋值情况,是推荐的实现方式。核心在于利用拷贝构造函数和swap操作,确保资源管理的正确性和异常安全性。

2025-11-30 18:51:53 824

原创 [C++]const成员

本文详细讲解了C++中const成员变量和const成员函数的使用规则。const成员变量必须在构造函数初始化列表中初始化,因其值不可改变;const成员函数保证不修改对象状态,可被const对象调用,但不能调用非const成员函数。文章通过代码示例展示了普通对象和const对象调用成员函数的不同情况,并分析了this指针的权限变化规则:权限平移和缩小允许,但权限放大禁止。最后总结了const成员必须通过初始化列表初始化的原因,以及const成员函数的调用权限规则。

2025-11-23 17:50:47 1434

原创 [C++]迭代器

摘要:本文介绍了C++迭代器的概念与应用。迭代器作为访问容器元素的通用接口,实现了算法与容器的解耦。通过std::reverse函数展示了迭代器与算法的配合使用,演示了字符串和vector的反转操作。详细阐述了四种迭代器类型:普通正向迭代器(iterator)、常量正向迭代器(const_iterator)、普通反向迭代器(reverse_iterator)和常量反向迭代器(const_reverse_iterator),通过代码示例说明了它们对普通对象和const对象的不同操作权限。迭代器机制体现了C++

2025-11-22 22:03:11 647

原创 [c++]string的三种遍历方式

本文介绍了三种C++字符串(string)的访问方式:1)下标+[]运算符重载,提供类似数组的访问接口;2)迭代器方式,通过begin()和end()实现容器元素的统一访问;3)范围for循环,基于迭代器自动完成遍历。每种方式都支持读写操作,其中范围for循环需要注意参数类型选择(auto、auto&或const auto&)以实现不同功能。示例代码展示了三种方式的遍历和修改字符串的具体实现,并分析了各自的特点和使用场景。

2025-11-22 22:00:26 509 1

原创 [C语言]const 修饰 指针(看一遍就能懂)

本文介绍了const修饰指针变量的三种情况:1) const位于左侧时,指针指向内容不可修改但指针本身可修改;2) const位于右侧时,指针本身不可修改但指向内容可修改;3) const位于*两侧时,指针本身和指向内容均不可修改。const修饰变量时赋予只读权限,修饰指针时根据位置不同分别限制指针指向内容或指针变量的修改权限,为编程中的常量定义提供了灵活的控制方式。这种语法特性在C/C++中常用于保护数据不被意外修改。

2025-11-19 13:31:38 402

原创 [c++]内存管理方式

摘要:本文对比分析了C++中new/delete与C语言malloc/free的内存管理差异。new/delete不仅能为内置类型分配内存,还能自动调用自定义类型的构造函数和析构函数。在底层实现上,new通过operatornew调用malloc,delete通过operatordelete调用free。相比malloc/free,new具有初始化功能、类型安全、自动异常处理等优势,特别适合面向对象编程。对于自定义类型,new会完成对象完整生命周期管理,这是C++内存管理的核心特性。

2025-11-19 13:31:29 874

原创 [c++]赋值运算符重载

本文介绍了C++中运算符重载的概念和应用。运算符重载允许自定义类型像内置类型一样使用运算符,通过在类中定义operator+、operator=等特殊函数实现。文章重点讲解了赋值运算符重载的实现要点,包括参数传递效率、返回引用支持连续赋值、避免自我赋值的判断等。同时对比了拷贝构造(创建新对象)和赋值运算符(已有对象间赋值)的区别。还指出赋值运算符必须作为类成员函数,不能重载为全局函数。通过日期类的代码示例,展示了==和=运算符重载的具体实现方法。

2025-11-15 18:04:10 1058

原创 [C++]拷贝构造函数使用规则以及注意事项

摘要:本文讲解了C++拷贝构造函数的使用规则和注意事项。拷贝构造函数是构造函数的重载形式,参数必须是类类型对象的const引用,避免无限递归。编译器会默认生成浅拷贝的拷贝构造函数,可能导致资源重复释放问题。对于涉及资源申请的类,需要自定义深拷贝的拷贝构造函数。文中通过栈类示例展示了如何实现深拷贝,并分析了浅拷贝引发的问题。最后总结了拷贝构造函数的调用场景和实现要点,包括参数类型、深浅拷贝处理等。

2025-11-15 18:00:53 877

原创 [c++]宏函数与内联函数

本文介绍了宏函数和内联函数的特性。宏函数是在预处理阶段展开的代码替换机制,具有无栈帧开销的优点,但容易出错且难以调试(如运算符优先级问题)。内联函数是C++为解决宏函数缺点提出的方案,在调用时展开,避免栈帧开销,但不适用于长函数或递归函数。宏函数和内联函数都适用于频繁调用的短小代码,但内联函数具有更好的可读性和安全性。文中通过错误代码示例展示了宏函数的常见问题,并给出了正确写法(如使用括号保证运算顺序),同时解释了内联函数在汇编层面的展开过程及其注意事项。

2025-11-12 19:14:17 395

原创 [C++]缺省参数-声明和定义歧义问题

函数缺省参数是C++中为形参指定默认值的特性,调用时可选择性传递实参。分为全缺省参数(所有参数都有默认值)和半缺省参数(部分参数有默认值)。使用时需注意:1)半缺省必须从右往左连续设置;2)声明和定义分离时,缺省参数只能在声明中指定,定义中重复指定会导致歧义错误(如默认值不一致)或编译错误。正确用法是在头文件声明中指定缺省值,定义时不重复指定。

2025-11-08 22:40:40 479

原创 双指针算法专题-283. 移动零-1089. 复写零

主要思想是找到最后一个复写的数,从后往前覆盖,该方法比较难想到,正常思路是从前往后覆盖,但是会覆盖关键元素,所以尝试从后往前覆盖,找到最后一个复写的数,然后从后往前覆盖。根据题目描述,可以归类该题为数组划分,通过双指针将数组划分为3个区间,分别为已处理区间(非零元素),零元素区间,待处理区间(非零元素)。当cur所指的元素是非零元素,dest++,如果cur所指的元素是零元素,则dest+=2,同时判断dest是否到结束位置,最后cur++;[dest+1,cur-1]表示为零元素区间。

2025-09-17 21:59:26 285

原创 【操作系统】进程终止中exit()和_exit()的区别

语句,该语句添加了'\n',程序会先把 you can see me语句显示到显示屏上,再sleep3秒,再退出程序。语句,该语句没有加'\n',程序会先sleep3秒,直接退出程序,不会把 you can see me语句显示到显示屏上。语句,该语句添加了'\n',程序会把you can see me 语句显示到显示屏上,再sleep3秒,再退出程序。语句,该语句没有加'\n',程序会先sleep3秒,再把you can see me 语句显示到显示屏上,再退出程序。

2024-03-21 10:53:28 840

原创 【操作系统】进程地址空间

地址空间本质上是OS为进程虚拟抽象出来的一种看待内存和外设的一种方案,让进程PCB指向自己的地址空间数据结构,结合页表来完成到物理内存的映射。虚拟地址是Linux配合硬件,软硬件结合的方案,创造出的地址空间的概念,以统一的视角来看到不同的设备,地址空间是进程地址空间,地址空间是一种内核数据结构struct mm_struct{},它里面有各个区域的划分,它来描述进程所看到的各个区域,进程里面会有结构体指针指向mm_struct{}//...//其它属性。

2024-03-21 10:53:08 1337

原创 【C++】多态

有继承关系,子类重新父类中的虚函数在虚函数的后面写上=0,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。四、多态的原理3.1、接口继承和实现继承1、普通函数的继承是一种实现继承,派生类继承了基类函数,可以使用函数,继承的是函数的实现。

2024-03-16 23:33:18 1238

原创 【牛客】HJ62 查找输入整数二进制中1的个数

是计算一个数二进制表示中1的个数,通过(n >> i) & 1可以获取第i位的二进制值,每次n右移一位,可 以获取一位的二进制值,右移32次,n变成0,循环终止。可以举一个八位的二进制例子来进行分析,对于二进制操作,我们直到,除以一个2,原来的数字会减少一个0.如果除的过程有余数,那么就表示当前位置有一个1.因此,可以考虑利用整形数据除法的特点,通过相除和判断余数的值来进行分析。利用val=val&(val-1)巧妙解法能最少次数统计1的个数。第二此除以2时,商为101 000 余数为1。

2024-03-13 21:52:41 540

原创 【C++】继承

继承机制是面向对象程序设计可以复用代码的重要手段,它允许程序在保持原有类特性的基础上进行扩展,增加功能,产生新的类,这个类为派生类。继承体现的是类定义层次的复用 继承的意义是复用1、公有继承:继承基类的public、protected、private在派生类中保持基类的原有访问权限2、保护继承:继承基类的public、protected成员,在派生类中全为protected3、私有继承:基类private成员在派生类中都是不可见的,即使是派生类的类内和类外。

2024-03-13 20:51:53 1096

原创 【牛客】HJ73 计算日期到天数转换

用一个数组存放每月的天数 输入的日期天数= 当月的天数 + 当月之前的累积天数 如果包含二月,再去判断是否为闰年,如果是闰年,再加1天。

2024-03-12 17:37:25 454

原创 【牛客】HJ74 参数解析

通过以空格和双引号为间隔,统计参数个数。对于双引号,通过添加flag,保证双引号中的空格被输出。

2024-03-12 17:36:30 477

原创 【牛客】HJ86 求最大连续bit数 CM24 最近公共祖先

上述树中子节点与父节点之间的关系为root = child / 2 所以如果a!= b,两个数进行比较,就让其中的较大数除以2, 如此循环直到a == b 即是原来两个数的最近公共祖先 比如: 2 和7的最近公共祖先:7/2 = 3 ---> 3/2 = 1, 2/2 = 1, 得到1为它们的公共祖先。根据位运算,获取每一位的二进制值。获取第i位的值: (n >> i) & 1。如果1连续,则计数累加,如果不连 续,则从0开始计数。用于统计当前最大连续1的个数。用于统计连续1的个数。

2024-03-10 15:54:15 408

原创 【牛客】CM26 二进制插入 HJ60 查找组成一个偶数最接近的两个素数

取出m的每一个二进制位 (m>>k)&1 假设k=0,即第一位二进制位(1101&0001)=0001。左移j+k位,取到逐个赋值到对应n的对应位数,或操作就是任意一个为1,则当前位为1。1、素数:判断素数,素数表示除过1和本身,不能被其它数整除。3、先从偶数的中间位置开始从两边查找素数对,m左移j位,然后进行与n或运算(|)即可。2、找到组成一个偶数的两个素数。8 12 8和12不是素数。7 13 7和13都是素数。9 11 9不是素数。

2024-03-10 15:53:26 576

原创 LCR 175. 计算二叉树的深度

4、最后返回左右子树较大的二叉树深度+1即为根节点二叉树深度。3、转换子问题:成求右子树为根节点的二叉树深度。2、转换子问题:求左子树为根节点的二叉树深度。1、要求根节点的二叉树深度。递归求左右子树的高度。

2024-03-08 21:19:48 436

原创 【牛客】HJ87 密码强度等级 CM62 井字棋

本题主要考察C语言中逻辑分支语句,基本语句以及对各种特殊字符 ,ASCII值以及条件表达中的逻辑运算符关系运算符各自功能的理解,以及基本使用,根据不同的条件,进入不同的分支,统计求和。1、先统计大小写字母,数字,以及特殊字符的个数。副斜board[row][col-1-i]正斜 board[row][row]2、再对题目给的限定条件累加求和。整个一行相加结果为列数 就获胜了。整个一列相加结果为行数 就获胜了。

2024-03-08 21:18:56 347

原创 【网络】HTTPS协议原理

数据摘要(数据指纹)基本原理是利用单向散列函数(Hash函数)进行信息运算,生成一串固定长度的数字摘要。数据摘要(数据指纹)并不是一种加密机制,可以判断数据是否被篡改。因为加密机制是可以对密文信息进行解密和加密,所以不是一种加密机制。HTTPS工作过程涉及到三组密钥第一组:CA机构的公钥和私钥保证客户端拿到服务器的公钥第二组:服务器持有的公钥和私钥用于协商对称密钥的私钥,客户端拿到服务端的合法公钥,就会随机生成对称密钥并且加密,发送给服务端,服务端通过私钥进行解密获取到对称密钥第三组:客户端生成的对称密钥。

2024-02-23 19:36:23 1799

原创 【C语言】程序编译链接详解

通过加选项-s来查看test.o,add.o形成的符号表。

2024-02-23 19:35:43 2972 2

原创 【高并发内存池】定长内存池实现

目前先介绍外碎片,所谓外碎片问题,是指一些空间的连续内存区域太小,这些内存空间不连续,以至于即使有足够的内存空间,也无法满足一些内存分配申请的需求(一段连续空间被切出去好多快,但是只有部分还回来了,但是它们不连续,导致要申请超过某个空间申请不出来,即使总空间大于要申请的空间,也申请不下来)。以服务器上的线程为例,它的主要思想是:启动诺干数量的线程,让他们处于睡眠状态,当接收到客户端的请求时,唤醒池中某个睡眠的线程,让它来处理客户端的请求,当处理完这个请求,线程又进入睡眠状态。2.3、内存池主要解决的问题。

2024-01-18 21:51:50 1330 1

原创 【数据结构】堆的实现和排序

前面两种思路当数据量特别大时求解不太容易现实,100亿个整数要占用40G的内存(1G=1024MB=1024*1024kb=1024*1024*1024byte 1G占10亿字节左右),明显不合适。思路2:将这N个元素建成大堆, Top和Pop K次 时间复杂度 O(O(n)+k*logN);在堆尾插入数据后,在插入的位置开始向上调整,依然保持堆结构。思路1:堆排序 时间复杂度O(N*logN)向上建堆的时间复杂度是O(n*logN)建堆有两种方式:向上建堆和向下建堆。向下建堆的时间复杂度是O(n)

2024-01-18 21:51:38 499

原创 【Linux】进程控制-进程终止

退出码是计算机为了方便返回结果设定的,我们并不清楚返回的1、2、3、4是什么意思,所以需要做一个将对应错误码或退出码转化为字符串描述的方案 .非0标识的是运行结果不正确,非0值有无数个,不同的非0值可以标识不同的错误原因,方便在进程运行结束后,结果不正确时,方便定位错误的原因。返回给上一级进程,父进程或者bash,用来评判该进程执行结果用的。0是退出码的一种,代表运行成功,代码对或不对用退出码判定。如果想在命令行中获取最近一次进程退出的退出码 通过。2、关闭所有打开的流,所有的缓存数据均被写入。

2023-12-03 19:46:11 867

原创 【Linux】进程控制-进程创建

fork()创建子进程,本质是系统里多了一个进程,该进程有对应的PCB,对应的地址空间,对应的页表,并将自己进程对应的代码和数据加载到内存,构建映射关系,将该进程PCB放入到运行队列里,等待OS或调度器调度,一旦CPU调度该进程,此时可以通过虚拟地址空间和页表找到该进程的相关代码,然后从上往下执行顺序语句,循环判断,函数跳转,进而在进程内部执行进程内的代码,完成某件事情。理论上,子进程也要有自己的代码和数据,可是一般而言,我们没有加载的过程,也就是说,子进程没有自己的代码和数据。

2023-12-03 19:46:01 522

原创 【Linux】环境变量

环境变量一般是指在操作系统中用来指定操作系统运行环境的一些参数问题引入:为什么系统命令可以直接运行,我自己写的程序必须带路径,如果不带路径,可以让自己写的程序程序和普通命令一样运行自己的程序吗?例如能够像指向系统命令pwd一样执行myproc程序因为OS运行一个命令要先找到它,不带路径就无法找到,OS的命令默认是可被找到的,这些命令在echo $PATH中(加$可以看到环境变量PATH里的内容),pwd命令在环境变量里的/usr/bin路径中,所以pwd可以被找到,而我们的程序并不在环境变量里的路径中。

2023-12-02 19:37:46 916

原创 【排序】直接插入排序和希尔排序

1>、元素集合越接近有序,直接插入排序的时间效率就越高,最坏情况是逆序<2>、时间复杂度:O(n^2)<3>、空间复杂度:O(1)<4>、稳定性:它是一种稳定的排序算法。

2023-12-02 19:37:26 243

原创 【C语言】整形在内存中的存储

大端存储模式,是指数据的高位保存在内存的低地址处,数据的低位保存在高地址处。小端存储模式,是指数据的低位保存在内存的低地址处,数据的高位保存在高地址处。

2023-11-23 16:20:27 233

原创 【C语言】结构体内存对齐

4、如果嵌套了结构体情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有的最大对齐数(包含嵌套结构体的对齐数)的整数倍。结构体的内存对齐是拿空间来换取时间的做法,如果在设计结构体的时候,既要满足对齐,又要节省空间,应该让占空间小的成员尽量集中在一起。3、结构体的总大小:最大对齐数(所有变量类型最大者和编译器默认对齐数取最小值)的整数倍。linux环境下没有默认对齐数(没有对齐数时,自身大小就是它的对齐数)2、其它成员变量要对其到某个数字(对齐数)的整数倍的地址处。

2023-11-09 20:24:13 324

原创 【Linux】Linux项目自动化构建工具Makefile

make是一个命令,makefile是一个文件,makefile文件里面包含依赖关系和依赖方法,一般必须有依赖关系和依赖方法,依赖关系可以不依赖任何文件,写makefile时要有目标,怎么生成项目,怎么清理项目,生成项目进行依赖关系和依赖方法的编写,清理项目使用.PHONY定义一个伪目标,使用伪目标来清理项目,伪目标总是被执行的,makefile辨别程序是否重新编译,取决于源文件和可执行程序时间的新旧,来决定程序是否重新编译。

2023-11-06 21:40:09 104

原创 【Linux】gcc/g++编译器原理

2、实际上系统把这些函数实现都放到名为libc.so.6的库文件中,在没有特别指定时,gcc会到系统默认的搜索路径“/usr/lib”下进行查找,也就是链接到libc.so.6库函数中去,这样就实现函数“printf”了,体现出了链接的作用。1、我们的C程序中,并没有定义“printf”的函数实现,而且再预编译中包含的“stdio.h”中只有该函数的声明,而没有定义函数的实现,那么“printf”是在哪里实现的?动态库一般后缀名为".so","libc.so.6"就是动态库,gcc在编译时默认使用动态库。

2023-10-31 19:53:56 270

原创 【Linux】进程状态

运行:task_struct结构体在运行队列中排队(等待某种资源),就叫做运行态。(进程还没有被CPU调度,正在等待调度器调度)阻塞:等待非CPU资源就绪,进程所处的状态为阻塞状态系统中一定存在各自资源的,除了CPU,还有网卡,磁盘,显卡等其他设备,系统中不只是存在一种队列,磁盘也可能由多个进程要访问,所以多个进程要访问同一个资源要排队等待。

2023-08-01 10:03:04 615

原创 【Linux】进程

所以想优先执行一个进程,在众多描述进程属性PCB中找到优先级高的,它的属性里面就是指向进程代码和数据的属性,就可以把它的代码和数据加载到CPU中,如果想删除一个已经是死亡状态的进程,就可以遍历所有的进程属性,找到死亡状态,把它曾经开辟的代码和数据free掉和和该进程的PCB结构体变量也删除,对应了遍历操作和链表的删除操作。因为父进程可以有一到多个子进程,而一个子进程只能有一个父进程,父进程和子进程的对应关系是1:n,fork之后,给父进程返回子进程的pid,父进程能通过pid区别子进程。

2023-07-30 21:26:53 145

原创 【LeetCode21】合并两个有序链表

定义head和tail的指针,并指向空,两个有序链表从头结点位置开始比较值大小,较小的值尾插到新链表上。按照思路编写,可能会遇到空指针问题。

2023-07-25 21:35:43 118

原创 【LeetCode 剑指offer 22】链表中倒数第k个结点

具体过程:开始快慢指针都指向头结点,先让快指针走k步,然后快慢指针同时走,当快指针走到空的时候,慢指针的位置即为链表倒数第k个结点的位置。快指针先走k步,快慢指针同时走。

2023-07-24 19:35:57 137

空空如也

空空如也

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

TA关注的人

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