- 博客(62)
- 收藏
- 关注
原创 C++:哈希表
unordered_set参考文档unordered_set 是无序的,而set中序遍历是有序的这里 Hash 和 Pred 是两个仿函数结构:差异:哈希(hash)⼜称散列,是⼀种组织数据的⽅式。从译名来看,有散乱排列的意思。本质就是通过哈希函数把关键字Key跟存储位置建⽴⼀个映射关系,查找时通过这个哈希函数计算出Key存储的位置,进⾏快速查找。当关键字的范围⽐较集中时,直接定址法就是⾮常简单⾼效的⽅法,⽐如⼀组关键字都在[0,99]之间,那么我们开⼀个100个数的数组,每个关键字的值直接就是存储位
2025-11-14 16:08:31
671
原创 VS Code搭建C/C++开发环境
下载地址:https://code.visualstudio.com/进入界面后直接点击下载下载好后在下载文件夹中就有如下可执行程序:下载下来的安装包直接双击:点击下一步:设置好安装路径后点击下一步:安装好后进来后是如下界面:安装好后会提示重启一下:下载地址:https://github.com/niXman/mingw-builds-binaries/releases进入下载界面开始按如下图片一步一步进行:点击后进入界面就会开始自动下载了现在好后是一个压缩后的文件:
2025-04-25 14:03:55
2817
原创 Linux:库的制作与原理
在计算机中库是由高级程序员写好的现有的,成熟的,可以复⽤的代码,现实中每个程序都要依赖很多基础的底层库,不可能每个⼈的代码都从零开始,因此库的存在意义⾮同寻常。在生活中也充满了库,比如说想要个手机,直接买就行,不需要自己制作,已经有手机生成商把手机所需要的显示屏内存等等零件组装好后,可直接使用的手机。
2025-04-24 14:58:17
1028
原创 Linux:Ext系列文件系统
⼀个”块”的⼤⼩是由格式化的时候确定的,并且不可以更改,最常⻅的是4KB,即连续⼋个扇区组成⼀个 ”块”。其实硬盘是典型的“块”设备,操作系统读取硬盘数据的时候,其实是不会⼀个个扇区地读取,这样效率太低,⽽是⼀次性连续读取多个扇区,即⼀次性读取⼀个”块”(block)。所有,寻址⼀个扇区:先找到哪⼀个柱⾯(Cylinder),在确定柱⾯内哪⼀个磁道(其实就是磁头位置,Head),在确定扇区(Sector),所以就有了CHS。• 磁头(head)数:每个盘⽚⼀般有上下两⾯,分别对应1个磁头,共2个磁头。
2025-04-15 20:05:15
1244
原创 Linux:基础IO
缓冲区是内存空间的⼀部分。也就是说,在内存空间中预留了⼀定的存储空间,这些存储空间⽤来缓冲输⼊或输出的数据,这部分预留的空间就叫做缓冲区。缓冲区根据其对应的是输⼊设备还是输出设备,分为输⼊缓冲区和输出缓冲区。
2025-02-25 20:55:43
1345
原创 C++:红黑树
假设我们把新增结点标识为c(cur),c的⽗亲标识为p(parent),p的⽗亲标识为g(grandfather),p的兄弟标识为u(uncle)。
2025-02-13 16:55:41
472
原创 Linux:进程控制
• 另外,进程⼀旦变成僵⼫状态,那就⼑枪不⼊,“杀⼈不眨眼”的kill -9 也⽆能为⼒,因为谁也没有办法杀死⼀个已经死去的进程。通常,⽗⼦代码共享,⽗⼦再不写⼊时,数据也是共享的,当任意⼀⽅试图写⼊,便以写时拷⻉的⽅式各⾃⼀份副本。新进程为⼦进程,⽽原进程为⽗进程。• ⼦进程退出,⽗进程如果不管不顾,就可能造成‘僵⼫进程’的问题,进⽽造成内存泄漏。通过父进程的变量,传地址让waitpid()把子进程结束时的返回值写入父进程的变量。• ⽗进程通过进程等待的⽅式,回收⼦进程资源,获取⼦进程退出信息。
2025-01-21 09:57:59
1167
原创 C++:异常
有时catch到⼀个异常对象后,需要对错误进⾏分类,其中的某种异常错误需要进⾏特殊的处理,其他错误则重新抛出异常给外层调⽤链处理。捕获异常后需要重新抛出,直接 throw;就可以把捕获的对象直接抛出。当异常抛出类型未捕获时,不想程序终止,用catch(…
2024-12-25 22:41:44
488
原创 C++:AVL树
key,vaule的二叉搜索树,需要用三叉链,多定义的父亲指针用来更新平衡因子。旋转总共分为四种,左单旋/右单旋/左右双旋/右左双旋。2、让旋转的树从不满⾜变平衡,其次降低旋转树的⾼度。左边的高度大于右边时右旋转。
2024-12-21 22:44:57
801
原创 Linux:进程的概念
输入/输出设备称为外设,Input/Output->IO,站在内存的角度理解IO。对应的每个数字目录都是一个进程,数字对应的是进程的pid。在父进程里的代码中fork()返回值是子进程的pid。• 内核(进程管理,内存管理,⽂件管理,驱动管理)课本概念:程序的一个执行实例,正在执行的程序等。Linux系统所以的进程都是被它的父进程创建的。本来是一个执行流的遇到fork会变成两个执行流。在子进程里的代码中fork()返回值是等于0的。一个父进程可以有多个子进程,进程也是进程树。:键盘,鼠标,话筒,摄像头……
2024-11-25 16:47:48
1669
原创 C++STL--------map和set
set的相关文档默认仿函数是小于,中序遍历为升序传greater仿函数,中序遍历为降序map是一个key/value的结构,相比set而言多了一个绑定的valuemap底层的红黑数节点中的数据,使用pair<Key,T>存储键值和数据。T1 first;T2 second;{}{}{}make_pair是一个函数模版,自己推导变量类型。
2024-11-19 13:28:29
910
原创 Linux:调试器-gdb/cgdb
断点编号 ------ 断点类型---------------------------是否使能----断点地址--------------------------------打的什么断点。如果监视的表达式在程序运⾏期间的值发⽣变化,GDB会暂停程序的执⾏,并通知使⽤者。cgdb跟gdb的使用方法一样,但cgdb更好观察代码,会分屏显示代码。-g选项,让最后形成的可执行程序,添加调试信息—debug模式!-g后生成的.o 文件被链接后的可执行程序占用的空间会变大。指定 行号从指定行号开始显示。
2024-11-19 12:19:29
1448
原创 C++:搜索二叉树
找到N左子树的最大结点R(最右结点)或者N右子树的值最小结点R(最左结点)代替N,因为这两个结点任意一个放到N的位置,都满足二叉搜索树的规则。替代N的意思就是N和R这两个结点的值交换,转而变成删除R结点,R结点符合情况2或情况3,可以直接删除。3、如果⽀持插⼊相等的值,插⼊值跟当前结点相等的值可以往右⾛,也可以往左⾛,找到空位置,插⼊新结点。1、把N结点的父亲对应孩子指针指向空,直接删除N结点(情况1可以当成情况2或者3处理,效果是一样的)3、把N结点的父亲对应孩子指针指向N的左孩子,直接删除N结点。
2024-11-12 13:18:06
908
原创 Linux环境基础和基础开发工具使用
先ctrl + v,用h、j、k、l 键选择要注释的行,选择之后然后输入shift +i,//在ESC一下自动完成注释。程序在打印到显示器上是,内容存在缓冲区中,缓冲区的刷新策略是行刷新。静态链接:把我们要的库方法实现,直接拷贝到我们的可执行程序中。查看包服务器中软件包,只找了软件名包含ls 的软件包名字。使用动态链接必须在系统里面存在动态库,动态库也称为共享库。软件源分为稳定软件源和扩展软件源,甚至有更多分类。$<:把依赖文件一批文件一个一个交给对应的命令。修改当前家目录下的.vimrc的配置文件。
2024-11-08 23:00:34
1665
1
原创 深入了解排序
introsort是introspectivesort采⽤了缩写,他的名字其实表达了他的实现思路,他的思路就是进⾏⾃我侦测和反省,快排递归深度太深(sgistl中使⽤的是深度为2倍排序元素数量的对数值)那就说明在这种数据序列下,选key出现了问题,性能在快速退化,那么就不要再进⾏快排分割递归了,改换为堆排序进⾏排序。三路代表的是:一路全部小于,一路全部是相等值,一路全部大于。专治这种有大量重复的。
2024-11-08 17:40:29
375
原创 C++继承
继承(inheritance)机制是⾯向对象程序设计使代码可以复⽤的最重要的⼿段,它允许我们在保持原有类特性的基础上进⾏扩展,增加⽅法(成员函数)和属性(成员变量),这样产⽣新的类,称派⽣类。继承呈现了⾯向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的函数层次的复⽤,继承是类设计层次的复⽤。
2024-11-04 19:33:42
1503
原创 Linux权限
shell就是一个外壳程序,我们输入的命令交给shell,它去和操作系统交流,实现对应的操作。表明以超级用户的身份去执行,但不是谁都能执行sudo,必须是被信任的用户。所以又想共享目录,但又不想让其他人删除目录里的文件,就需要天剑粘滞位。对于一个文件,如果没有r权限,用任何工具都不行。Linux中一切皆文件,所以权限都是文件对角色的限制。修改权限掩码,到达修改Linux文件缺省 权限的问题。+t :t 代表other 的意思,权限位x变成了t。1、Linux在多用户下,对文件的访问,是隔离的。
2024-10-29 12:10:36
829
原创 Linux基础指令
当我们Ctrl+a选择删除文件时,默认隐藏文件时不会被选中的,可以避免我们对重要数据误操作。以-开头的称为普通文件:文本文件,二进制可执行,动静态库,视频,音频,图片……不光能显示当前路径下的文件也可以显示指定路径的文件,路径称为绝对路径。以自己的当前路径为参照点,查找定位目标文件的路径:相对路径。家目录是保护用户私有信息的目录,默认登录的地方就在家目录。Linux中,以.开头的文件或者目录是隐藏文件。ls:白色文字的是普通文件,蓝色的是目录。Modify: 最后一次修改文件的时间。
2024-10-28 11:33:02
524
原创 C++模版
来解决存储数据类型的问题,但如果存储了一个类型的数据,就不用用栈存储另一个类型的数据,栈不能进行同时存在多个类型数据进行存储。也可以由程序员控制让模版生成什么类型的函数来调用,称为显示实例化。在针对不同类型时也可以使用强转让编译器知道要实例化什么类型的函数。所以还是用模版生成栈可以同时存在用来存储不同类型的数据。对于需要不同类型模版也可以实现,需要定义多个参数类型。在调用时根据不同类型编译器生成一个匹配该类型的函数。前面编译器自动推导后生成的函数是隐式实例化。模版生成的函数就是逻辑一样,就是类型不一样。
2024-10-28 11:32:44
1194
原创 C++STL--------stack栈和queue队列
实现的初心是为了替代vector和list,但效率上都不上,list把插入删除的效率做到极致,vector把访问效率做到极致,deque克服了vector和list的缺点但访问比不上vector,中间位置插入删除又比不上list。stack就是适配器,把设计好的数据结构让stack来进行复用,通过传模版参数,形参不同的栈数据存储形式,链式栈或者是数组栈等等,就是负责完成后进先出的效果。队列也一样,只要实现效果是先进先出就可以,不用管底层是如何实现的,底层也是复用已经实现好的数据结构来完成的。
2024-10-27 11:46:01
501
原创 C++STL--------list
是一个支持O(1)时间复杂度插入和删除的链表结构,迭代器是双向的,底层是一个带头双向循环链表。跟push_back有差异,push_back要插入的类型被固定,可以支持隐式类型转换。list 自己实现的sort是支持双向迭代器的,算法库里的sort是传随机迭代器。emplace_back不支持隐式类型转换,但可以直接传要初始的值进行构造。比算法库里的swap更高效,底层是交换指向头结点。可以调整链表里面的顺序,把自己的结点转移给自己。位置用迭代器表示,也可以删除一个迭代器区间。插入1到9,打印9到1。
2024-10-22 18:24:09
1503
原创 C++STL--------string
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
2024-10-07 18:45:48
1378
原创 类的初始化列表
C++支持内置类型和类类型的相互转换class Apublic:A(int n):_a1(n),_a2(_a1)private:int main()A aa1 = 1;return 0;用整形 1 创建了一个临时的A构造函数,拷贝构造给了aa1但因为构造加拷贝构造太浪费了,就直接优化为直接构造看上图,编译器只执行了一次构造函数。如果不想让隐式类型发生转换可以在前面加explicit:_a1(n),_a2(_a1)当有多个参数转换时,用大括号括起来class A。
2024-09-16 22:56:00
1784
原创 C++运算符重载
如果不写赋值运算符重载函数,系统会自动生成,但是浅拷贝,一个字节一个字节的拷贝,对于占用资源的还是要自己写才好。对于类类型的使用运算符编译器是不知道要干嘛的就需要自己写函数,自己实现功能。要跟拷贝构造区分,拷贝构造是一个已经存在,给另一个初始化时进行的拷贝操作。日期 - 日期,日期 + 天数,日期 - 天数,这些都是有意义的。总结如果显示写了析构,就要显示写赋值运算符重载。对两个已经存在的类的对象进行赋值拷贝操作。运算符的作用,用于定义类的成员函数指针。就比如日期类的大小比较。
2024-09-09 21:20:50
3595
原创 《C语言实现各种排序算法》
希尔排序法的基本思想是:先选定⼀个整数(通常是gap = n/3+1),把待排序⽂件所有记录分成各组,所有的距离相等的记录分在同⼀组内,并对每⼀组内的记录进⾏排序,然后gap=gap/3+1得到下⼀个整数,再将数组分成各组,进⾏插⼊排序,当gap=1时,就相当于直接插⼊排序。直接插⼊排序是⼀种简单的插⼊排序法,其基本思想是:把待排序的记录按其关键码值的⼤⼩逐个插⼊到⼀个已经排好序的有序序列中,直到所有的记录插⼊完为⽌,得到⼀个新的有序序列。快排的时间复杂度:O(n。快排的空间复杂度:O(
2024-08-20 23:11:06
966
1
原创 C++构造和析构
构造函数的名字跟它所在的类的名字一样,构造函数没有返回值(viod 也不用写),构造函数支持重载,就是根据传参来区分调用哪一个构造函数。内置类型是int/char/double/指针等类型,自定义类型是class/struct关键字创建的类型。构造函数是一个类的成员函数,在类创建好后(就是开劈好空间)自动调用构造函数对类的成员变量进行初始化。编译器自动生成的构造函数对内置类型有可能不做处理,对自定义类型会调用对应的构造函数。总结就是不传实参就调用的构造叫默认构造。在不传参时调用构造函数不用加括号。
2024-08-12 16:24:50
1081
原创 C++类和对象
calss是定义类的关键词,用法更C语言中的结构体struct关键词用法一样,区别是类可以在里面创建函数,当然在C++中也是兼容结构体的,同样也对结构体进行升级也可以包含函数了。在类里面的函数默认是被内联函数inline修饰的。C++中的类和结构体的用法相同,区别在于默认的限制访问。类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的⽅法或者成员函数。
2024-08-06 22:58:50
1352
原创 C++入门基础
定义命名空间,需要使⽤到namespace关键字,后⾯跟命名空间的名字,然后接⼀对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。namespace本质是定义出⼀个域,这个域跟全局域各⾃独⽴,不同的域可以定义同名变量,所以下⾯的rand不在冲突了。C++中域有函数局部域,全局域,命名空间域,类域;域影响的是编译时语法查找⼀个变量/函数/类型出处(声明或定义)的逻辑,所有有了域隔离,名字冲突就解决了。
2024-08-03 16:49:45
1334
原创 《数据结构:链表递归实现二叉树》
⽤链表来表⽰⼀棵⼆叉树,即⽤链来指⽰元素的逻辑关系。根结点的左⼦树和右⼦树分别⼜是由⼦树结点、⼦树结点的左⼦树、⼦树结点的右⼦树组成的,因此⼆叉树定义是递归式的,后序链式⼆叉树的操作中基本都是按照该概念实现的。⼆叉树分为空树和⾮空⼆叉树,⾮空⼆叉树由根结点、根结点的左⼦树、根结点的右⼦树组成的。:先打印根节点,然后打印左子树,最后打印右子树。:先打印左子树,再打印根结点,最后打印右子树。:先打印左子树,再打印右子树,最后打印根结点。
2024-07-27 17:08:40
408
1
原创 《数据结构:顺序实现二叉树》
对于深度为 K 的,有 n 个结点的⼆叉树,当且仅当其每⼀个结点都与深度为K的满⼆叉树中编号从 1 ⾄ n 的结点⼀⼀对应时称之为完全⼆叉树。要注意的是满⼆叉树是⼀种特殊的完全⼆叉树。现实中我们通常把堆(⼀种⼆叉树)使⽤顺序结构的数组来存储,需要注意的是这⾥的堆和操作系统虚拟进程地址空间中的堆是两回事,⼀个是数据结构,⼀个是操作系统中管理内存的⼀块区域分段。树形结构中,我们最常⽤的就是⼆叉树,⼀棵⼆叉树是结点的⼀个有限集合,该集合由⼀个根结点加上两棵别称为左⼦树和右⼦树的⼆叉树组成或者为空。
2024-07-22 15:40:33
914
原创 《数据结构:栈和队列》
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行插入和删除操作的一端称为栈顶,另一端称为栈底。概念:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)队列也可以由数组和链表的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据,效率会比较低。栈的实现一般可以使用数组或者链表实现,相对而言数组的结构实现更优一些。:栈的插入操作叫做进栈/压栈/入栈/,入数据在栈顶。
2024-07-19 21:34:02
800
1
原创 《数据结构:C语言实现双链表》
带头链表中的头结点,实际为“哨兵位”,哨兵位结点补存储任何有效元素,只是站在这里“放哨的”虽然有这么多的链表的结构,但我们实际中最常用的还是两种结构:单链表和双向带头循环链表.
2024-07-19 16:10:30
549
原创 《数据结构:C语言实现单链表》
当我们想要保存⼀个整型数据时,实际是向操作系统申请了⼀块内存,这个内存不仅要保存整型数据,也需要保存下⼀个结点的地址(当下⼀个结点为空时保存的地址为空)。在有数据的情况下,要找到最后一个结点,最后一个结点存放的指针指向的地址为NULL,把这个节点的指针指向为新结点。在数据为5的结点前面插入新结点,要传三个值,第一个是首结点,第二个要在哪个结点之前插入结点,第三个插入的数据值。思路在开辟新结点,需要用首结点找到插入结点之前的结点,让之前结点指向新结点,新结点指向被插入的结点。
2024-07-13 14:37:39
1130
1
原创 《数据结构:C语言实现顺序表》
创建完成就一步步实现1、在squence_list.h的文件,首先要创建顺序表所要用到的结构体自定义类型//sequence_list.h文件中//顺序表存放数据的类型//顺序表的类型创建//存放指定类型数据的指针//存放数据的有效个数int count;//属性表空间大小int size;}SL;//重命名一个简单的名字。
2024-07-11 19:33:46
903
原创 算法的复杂度
实际中我们计算时间复杂度时,计算的也不是程序的精确的执⾏次数,精确执⾏次数计算起来还是很⿇烦的(不同的⼀句程序代码,编译出的指令条数都是不⼀样的),计算出精确的执⾏次数意义也不⼤,因为我么计算时间复杂度只是想⽐较算法程序的增⻓量级,也就是当N不断变⼤时T(N)的差别,上⾯我们已经看到了当N不断变⼤时常数和低阶项对结果的影响很⼩,所以我们只需要计算程序能代表增⻓量级的⼤概执⾏次数,复杂度的表⽰通常使⽤⼤O的渐进表⽰法。空间复杂度也是⼀个数学表达式,是对⼀个算法在运⾏过程中因为算法的需要额外临时开辟的空间。
2024-07-10 20:08:26
1499
原创 《C语言》预处理
C语言设置了一些预定义符号,可以直接使用,在预处理期间进行处理的。__FILE__//进行编译的源文件__LINE__//文件当前的行号__DATE__//文件被编译的日期__TIME__//文件被编译的时间__STDC__//如果编译器遵循ANSI C,其值为1,否则未定义100逻辑规则是帮后面代码中出现MAX直接替换成100,这个操作步骤是在预处理阶段完成的,一般在用#define定义常量时的名称用大写书写。
2024-07-07 13:44:02
964
原创 《C语言》编译和链接
程序同时也可以使用静态(static)内存,存储于静态内存中的变量在程序的整个执行过程一直保留它们的值。链接会生成一个表记录函数名有没有被声明,变量名赋值等等,一个文件定义了一个函数,另一个文件中没有声明这个函数也可以使用的原因就是因为链接产生的效果。将源代码程序输入扫描器,扫描器的任务就是简单的进行词法分析,把代码中的字符分割成一系列的记号(关键字、标记符、字面量、特殊字符等)。在使用编译器编写代码时,编写的代码是高级语言,机器无法直接识别和运行,在编译器内部会翻译成机器可执行的机器语言。
2024-06-25 17:29:45
1040
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅