自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 C++实现——红黑树

我们将红色与黑色设置成枚举类型,使代码看起来更加规范,我们定义节点采用类模板的方式,内部成员分别是左节点指针,右节点指针,父亲节点指针,pair结构体类型的变量,然后就是代表我们颜色的变量。我们再对它们进行初始化列表就可以了,我们的每个节点初始颜色都得设置成红色,不然就无法满足我们上面给的5条红黑树的性质。

2024-08-20 15:12:17 741 5

原创 C++实现AVL树(图解)

如上图所示,我们每一个节点的结构体就长这样,我们使用了类模板来构建一个K_V模型,类里面有三个结构体指针,分别代表左孩子,右孩子,还有父亲节点,多个父亲节点是为了后期我们进行旋转操作的时候能控制住节点间的关系。除了这三个指针外我们还有一个标准库里的pair结构体和一个平衡因子,这个平衡因子就是保证我们的二叉搜索树是平衡二叉搜索树的关键,接下来就是初始化列表来对这些成员变量进行初始化。

2024-08-15 16:34:21 653

原创 C++——多态

多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。举个栗子:比如买票这个行为,当普通人买票时,是全价买票;学生买票时,是半价买票;军人买票时是优先买票。再举个栗子: 最近为了争夺在线支付市场,支付宝年底经常会做诱人的扫红包-支付-给奖励金的活动。那么大家想想为什么有人扫的红包又大又新鲜8块、10块...,而有人扫的红包都是1毛,5 毛....。其实这背后也是一个多态行为。

2024-08-11 16:00:54 1180 4

原创 C++——继承(超详细)

看了上面的案例,我们大概知道了继承的概念,那么我们接下来就来看看继承的定义:下面我们看到Person是父类,也称作基类。Student是子类,也称作派生类。由上图,我们发现继承方式好像跟访问限定符一样也是三种,那是不是就有九种情况呢?那我们如何分辨呢?总结:1. 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。

2024-07-04 14:48:12 1586 2

原创 C++实现二叉搜索树(模型)

插入的逻辑其实非常简单,如果这棵树是一棵空树,那么我们直接创个根节点就可以了,不需要后续的操作,倘若不是空树,那我们就进行接下来的操作,我们先定义一个父亲节点parent和当前节点cur,然后按照我们的性质,key比cur中的大我们就往右,小的话我们就往左走,如果这个key在树中存在,我们就放回false,因为set是有去重功能的,就是说一棵树里不能存在两个一样的值。这里我们选择第二种。我们的二叉搜索树按照中序遍历是刚好是有序的,这个是我们二叉搜索树的意义之一,所以我们这里也是实现中序遍历。

2024-05-07 16:19:42 824 6

原创 实现优先队列——C++

然后我再说明一下,孩子节点和父亲节点是如何来确定的,我们知道顺序表的物理结构也是连续的,下标从0开始,我们的父亲节点只需要*2加1就能找到左孩子,再加一就能找到右孩子,而我们的不管是左孩子还是右孩子都只需要-1再除2就能找到父亲了,这其中的数学原理大家下去画画图,很快就能得出这个结论了。我们的优先队列的数据是连续的,从头部删除性能肯定不好,所以我们的思路是先把要删除的元素跟最后一个交换,然后删除最后一个元素就能达到我们的效果了,这个时候为了保证我们堆的性质要对首元素进行调整,调整到它该去的位置。

2024-05-03 11:43:03 754 7

原创 C++——map和set的基础应用

C++中的STL容器一般分为序列式容器和关联式容器,比如:vector、list、deque、 forward_list(C++11)等,这些容器统称为序列式容器,因为其底层为线性序列的数据结构,里面 存储的是元素本身。这四种容器的共同点是使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列。2. 在set中,元素的value也标识它(value就是key,类型为T),并且每个value必须是唯一的,set中的元素不能在容器中修改(元素总是const),但是可以从容器中插入或删除它们。

2024-04-29 21:52:49 860

原创 C++实现list容器

我们都知道C++中有一个list容器,有基础的人清楚它的底层是一个带头双向循环列表,但进一步的细节可能就不太了解,所以,本篇注重谈论list容器的底层细节。——(护盾)【由于本篇注重于细节,所以不再会去解释基础语法的作用,因此本篇针对非小白学习者查阅,即有不错的面向对象知识体系和带头双向循环列表理解的群体】

2024-04-10 10:00:44 570

原创 C++实现vector

自主实现C++中vector大部分的功能可以使我们更好的理解并使用vector。本篇我们只会实现最常用的,因为我们的目的不是要超越或则弄一个一模一样的,而是去理解。

2024-04-04 17:08:10 803 8

原创 Linux——进程程序替换

用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数 以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动 例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。如上图所示,我们使用exec系列函数后,会将物理内存的数据段和代码段进行替换,而我们的PCB(进程结构体)大致上是不会改变的。

2024-03-26 13:33:20 447 7

原创 Linux——程序地址空间

我们知道子进程是会继承(共享)父进程的数据的,我们的task_struct里存有g_val的虚拟地址,虚拟地址通过映射来找到对应的物理地址空间,如果我们不去修改数据,那么我们的子进程对应的数据也确实跟父进程一模一样,但是我们现在修改数据了,修改数据的时候,我们的物理空间会开辟出来一块存放你修改的值,这个值只影响你对应的这个子进程,不会影响你的父进程,所以页表上虽然虚拟地址是一样的,但是映射出来对应的物理空间却是不一样的,所以我们就看到了输出结果的情况。2.但地址值是一样的,说明,该地址绝对不是物理地址!

2024-03-20 13:18:17 620 12

原创 C++实现string类

一般我们的成员函数是设置成public属性,使其能在外部调用到,而内置成员变量我们一般是设置成私有,不允许外部随便就能修改到它。我们知道string是字符串类,所以要有char*类型的指针,还要有它的有效元素个数_size,还有计录它空间的_capacity,因此初步来看,string类基本上的一个框架就是这样,到后面我们会慢慢完善。

2024-03-16 09:44:41 1094 6

原创 Linux调试器——gdb的基础使用

众所周知,我们的程序发布有两种,分别是debug模式和release模式,在Linux中我们主要有两种编译器——gcc和g++,一个是编译C语言程序的,一个是编译C++程序的,当我们使用这些编译器进行汇编步骤的时候,会生成一个二进制文件,Linux系统中默认它是release模式的。由此我们就可以看到它的断点个数、序号,Disp我们先不管,Enb表达的是它的使能,就是说这个断点是开启的状态(y)还是关闭的状态(n),后面的信息就是它的地址,还有在哪个文件.(也可以简写成i b)

2024-02-23 14:32:51 874 10

原创 C++函数模板

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。我们知道匹配使用哪个函数是编译器自动帮我们搞定的,但是要写这么多函数也是挺累的,而且代码维护成本高,那我们有没有什么更好的办法呢?函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

2024-02-15 14:25:15 640 4

原创 C++中的new和delete

如上图所示,我们定义了一个Date类,接下来我们看看他们的区别结合上述的图片,我直接来说明结论:new/delete 和 malloc/free最大区别是 new/delete对于【自定义类型】除了开空间 还会调用构造函数和析构函数。

2024-02-14 15:47:12 277 5

原创 C++ 友元

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。友元分为:友元函数和友元类。

2024-02-07 18:58:26 611 6

原创 C++拷贝构造函数、赋值运算符重载

拷贝构造函数的写法如图所示调用方式如下接下来我来说说它的特征。

2024-02-04 16:43:04 548 10

原创 C++中 this指针、构造函数、析构函数

我们定义一个日期类来举例子对于上述类,有这样一个问题,Date类中有Init和Print这两个成员函数,函数体中没有关于不同对象的区分,那d1调用函数的时候,编译器是如和来确定d1而不是d2呢?C++通过引入this指针解决了这种问题。即C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量”的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

2024-01-30 15:03:31 1192 12

原创 C++中命名空间、缺省参数、函数重载

这是因为我们测试时是会包含a.h头文件的,编译器在预处理阶段会将头文件展开,相当于把头文件的内容复制到测试文件中,在编译阶段检测到是有这么个函数声明,所以不会报错。这是一种方法,但是这样写太麻烦了,所以在一般的联系中我们不会写到太多的代码,这个时候我们就可以将std库展开,展开就相当于是全局域,就在我们编译器的默认搜索范围之内了。2.接下来我们来了解命名空间域,它就相当于划分了一块地盘,里面住着各种成员,比如张三家有一只羊,李四家也有一只羊,拿谁家的羊有地址就行,张三家的羊跟李四家的也没有关系。

2024-01-22 15:29:47 1313 16

原创 归并排序(C语言)

所以,上面代码中的gap的作用就是控制对比元素的个数,一开始一个跟一个对比,每一趟新的循环gap阔两倍,然后治的过程,代码跟我们递归版的是相差无几的,但是这里的end1,begin2,end2要注意有可能会发生越界的情况,所以我们要对他们进行判断,当end1和begin2中的任意一个出现越界情况的话,我们就终止循环,因为光是左边的就已经到尾了,就没必要比右边了(右边压根没数据了);看上面的图,当我们将一个数组进行分离,一直分,知道左右两边进行对比的数只有一个,这种情况下肯定有序。

2024-01-18 15:05:50 497 9

原创 C语言实现快排核心思想(双指针法)

这就是每一趟快排的实现代码,由上面的动图,我们能知道前后指针法的核心是玩好cur和prev这两个指针,具体的逻辑是cur找比key小的值,找到就prev++,然后prev和cur的值就进行交换,但是总不能自己跟自己交换吧,这就是多此一举了,所以我们在代码中的if语句里多加一个判断,++prev不能等于cur;如果cur遇到比key大的值prev就不动,cur++。最后我们再把prev跟key的值进行交换,并更新一下key的值,这个key就是我们的下一趟的头和尾。

2024-01-14 11:30:24 573 3

原创 快速排序挖坑法

经过上面的图片分析,我们可以感受到挖坑法和hoare版本并没有太多本质上的区别(hoare版本的思路及代码在我的上一篇博客已经写过,这里我就不再赘述了),只不过挖坑法似乎更易理解,且我们在写代码的时候也会感觉到与hoare相比,它的坑会比较少,接下来我们来剖析代码加深理解。这两张图片中第一张是挖坑法的核心,我们重点来讲第一张的核心部分(第二张图片的内容我也在上一篇博客中展示过了)。不过在这里我们先穿插一个上次没有讲过的小模块,也算是一种小优化,就是GetMidi这个接口。

2024-01-07 11:15:04 461 5

原创 C语言实现Hoare版快速排序(递归版)

我们看下面的代码,我说过了,类似后序遍历的思想,所以我们就写出了先找左,再找右的递归代码,第一个QuickSort就是往左递归嘛,那么起始位置就是begin不变,右边的界限就是我们通过函数找出来的k(key交换后的下标),但是要减一,因为key的下标k已经是确定好的了嘛,就不需要访问它了;然后返回新的key下标。接下来说说第二趟也就是如何来递归,我们前面说过了,每一趟都会确认一个值的位置,那么,我们的步骤就是类比二叉树的后序遍历一样,以固定的值为最左值或最右值,依次固定住所有的该在的位置。

2023-12-17 11:32:18 696 11

原创 插入排序与希尔排序(C语言实现)

由上面的动图可以知道插入排序的逻辑就是从第一个元素开始往后遍历,如果找到比前一个元素小的(或者大的)就往前排,所以插入排序的每一次遍历都会保证前面的数据是有序的,接下类用代码进行讲解。我们这里传两个参数,一个是数组,一个是数组元素的个数。排序接口我们采用大事化小的想法来进行讲解, 我们先来思考单趟遍历要达成的目标。

2023-12-09 10:38:15 772 9

原创 Linux部分基础指令讲解

倘若我们有文件,我们就会清空文件的所有内容,再进行输出内容的操作(上面的图中我们也看到了第二次显示hellow的时候没有了第一次显示的内容),Linux中也是一样的,而且我们得知道在Linux中一切皆文件(也就是说Linux可以统一对文件/设备进行访问),也就是说我们的显示器是一个文件,我们的键盘也是一个文件。比如我们先ll,ll之后呢我们会看到这里有一个new.txt文件,我们会看到这个文件的内存很大,说明这是一个大文件,我们的more指令的作用主要也是用来输出大文件的,接下来我们来看看什么叫满屏。

2023-12-02 11:17:22 1316 7

原创 LeetCode OJ循环队列(C语言)

我们分析上述题目的时候会发现题目非常的长,不好整理思路,我这里可以大致的将本题的几个核心点说出来:1.队列的思路循环队列说来说去不还是队列嘛,那么队列的基本操作增删查改、以及队列的基本结构肯定都是不能变的,我们知道队列的逻辑结构就是先进先出,而在C语言中,我们要实现队列可以采用两种方法,一种是链表,一种是顺序表,本题我们采用顺序表。2.循环的实现。

2023-11-25 12:24:30 1349 11

原创 手撕单链表(C语言)

头插的操作跟尾插差不多,我们先断言指针是否为NULL,不是的话我们创建一个新的节点,这里我们注意一下顺序,我们要先把新节点的next指向原来的头节点,再把头节点指针指向新的节点,倘若我们先进行把头节点指针指向新的节点我们就会发现我们找不到原来的头节点了,这就是我们要注意的一个地方。这个就要节点的多,我们只需要断言一下pos和pos的下一个节点就行了,然后我们再创建一个del指针指向pos的下一个节点,然后把pos的next指向pos的下一个的下一个节点,我们再释放掉del。那么它的逻辑图长什么样呢?

2023-11-18 11:21:28 400 8

原创 板鸭带你手撕C语言双向链表

我们都知道双向链表有四种,分别是:双向带头循环链表,双向带头不循环链表,双向不带头循环链表,双向不带头不循环链表。这里我们就讲双向带头循环链表。为什么要讲这一种链表呢?因为双向带头循环链表在实际生活中的使用非常广泛,而且我们只需要了解这一种双向链表,其他三种双向链表我们也会很容易掌握。下图就是我们带头双向链表的逻辑结构。注意:这里的“带头”跟前面我们说的“头节点”是两个概念,实际前面的在单链表阶段称呼不严 谨,但是为了同学们更好的理解就直接称为单链表的头节点。

2023-11-11 12:18:27 102 9

原创 顺序表(C语言)

线性表是⼀种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...通俗一点,线性表在逻辑中是像线一样连续的,但它在物理结构上不一定连续,线性表在物理上存储时,通常以数组和链式结构的形式存储。这里要注意,我们传的是是顺序表的地址,因为我们是想改变顺序表,而如果我们不传地址的话,就无法改变顺序表本身,因为形参是实参的一份临时拷贝,,所以不会改变原来的顺序表。1.我们的库函数的头文件最好写在我们的头文件中,因为我们的两个.c源文件到时候是需要调用SqList.h这个头文件的。

2023-11-01 17:32:35 135 9

原创 算法的时间复杂度

我们会发现同样的目的,我们如果使用for循环的思想,可能两三次就想出来了,但我们用递归的思想。我们知道算法的效率是判断一个程序好坏的重要标准,在当今的社会,一个程序运行速度的快慢决定着人们对这个程序的好感已经认可度,那么我们都是如何来进行算法效率的表示的呢?这里,我们会发现,虽然结果是错误的但计算机很快就算出来了,结果错误是因为它的值超出了存储空间的大小, 那么在这里,代码的时间复杂度是多少呢?像这样的算法它的时间复杂度就是O(2^N)时间复杂度的计算我们采用的是估算的方法,使用的是大O的渐进表示法。

2023-10-28 16:56:27 86 7

原创 C语言中的#define

基本语法例子如下#define机制包括了一个规定,允许把参数替换到文本中,这种实现通常称为宏(macro)或定义宏(define macro)。下面是宏的声明方式其中的parament-list是一个由逗号隔开的符号表,它们可能出现在stuff中。注意:参数列表的左括号必须与name紧邻,如果两者之间有任何空白存在,参数列表就会被解释为stuff的一部分。

2023-10-09 16:02:56 145 17

原创 C语言预定义符号

C语言设置了一些预定义符号,可以直接使用,预定义符号也是在预处理期间处理的。由图可知VS2022中不遵循ANSI C。以上就是C语言的预定义符号。上述的预定义符号结果如下。

2023-10-05 17:25:43 104 2

原创 文件操作的相关内容

在磁盘上的文件就是文件,但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件,这是我们从功能角度来分类的。

2023-10-01 11:45:26 85 2

原创 C语言的编译和链接Add

1.程序必须载入内存中,在有操作系统的环境中:一般这个由操作系统完成。在独立的环境中,程序的载入必须由手工安排,也可能是通过可执行代码置入只读内存代码来完成;2.程序的执行便开始,接着便调用main函数;3.开始执行程序代码,这个时候程序将使用一个运行时堆栈,存储函数的局部变量和返回地址,程序同时也可以使用静态内存,存储于静态内存中的变量在程序的整个执行过程中一直保留他们的值。4.终止程序,正常终止main函数,也有可能是意外终止。

2023-09-29 09:42:13 130 2

原创 (干货)动态内存管理中的四大函数

realloc函数的出现让动态内存管理更加灵活。有的时候我们发现在过去我们申请的空间太小了,有的时候又感觉太大了,那为了合理的使用内存,我们一定会对内存的大小做灵活的调整,而realloc函数就可以做到这一点。ptr是要调整的内存地址;size调整之后新的大小;返回值为内存调整之后的内存起始位置;这个函数调整原内存空间大小的基础上,还会将原来内存中的数据移动到新的空间。realloc在调整内存空间的时候有两种情况:1.原有空间有足够大的空间会返回原空间的地址;

2023-09-23 17:23:50 89 5

原创 自定义类型:枚举

我们知道定义常量的时候可以用#define,那为什么还需要一个枚举类型呢,首先我们要知道存在即合理,接下来分析枚举类型的优点。枚举顾名思义就是一一列举,把可能的取值一一列举,比如周几到周几,性别,月份,三原色都可以采用枚举。这些可能取值都是有值的,默认从0开始,依次增一。比如第三个枚举类型红是0,绿是1,蓝是2.注意,在C语言中是可以的,但在C++中不行,因为C++的类型检查比较严格。5.枚举常量是遵循定义域规则的,枚举声明在函数内,只能在函数内使用。{}中的内容时枚举类型的可能取值 ,也叫枚举常量。

2023-09-23 10:31:53 74 1

原创 自定义类型:联合

像结构体一样,联合体也是由一个或者多个成员构成,这些成员可以不同的类型。联合体的特点是所有成员共用一块内存空间,所以联合体也叫共用体。我们知道联合体的成员是共用一块内存空间的,这样一个联合体变量的大小至少是最大成员的大小,我们来接到上一处代码。那么,我们怎么来理解一个成员的发生变化,另一个成员的值也发生变化呢?其次,如果最大成员的大小不是最大对齐数的大小的整数被时,就要对到最大对齐数的整数被。首先,我们已经知道联合体的大小至少是最大成员的大小;给联合体其中一个成员赋值,其它成员的值也跟着变化。

2023-09-22 23:33:13 73 1

原创 C语言结构体知识点

所以不能对位段的成员使用&操作符,这样就不能使用scanf直接给位段的成员输⼊值,只能是先输⼊放在⼀个变量中,然后赋值给位段的成员。下图是网络协议中,IP数据报的格式,我们可以看到其中很多的属性只需要几个bit位就能描述,这里使用位段,能够实现想要的效果,也节省了空间,这样网络传输的数据报大小也会较小⼀些,对网络的畅通是有帮助的。4.如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构。如果传递一个结构体对象的时候,结构体过大,参数压栈的开销比较大,会导致性能的下降。

2023-09-19 14:28:36 119 1

原创 整数和浮点数在内存中存储

但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE754规定,存入内存时E的真实值必须再加上⼀个中间数,对于8位的E,这个中间数是127;这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着⼀个字节,⼀个字节为8bit位,但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于⼀个字节,那么必然存在着⼀个如何将多个字节安排的问题。

2023-09-16 22:44:58 92 4

原创 字符函数和字符串函数

的,C语⾔程序启动的时候就会使⽤⼀个全⾯的变量errno来记录程序的当前错误码,只不过程序启动的时候errno是0,表⽰没有错误,当我们在使⽤标准库中的函数的时候发⽣了某种错误,就会讲对应的错误码,存放在errno中,⽽⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是有对应的错误信息的。4.strtok的第一个参数不为NULL,函数将找到str中的第一个标记,strtok将保存它在字符串中的位置。在一个字符串中找到另一个字符串的内容,返回找到的那个字符串中首字符的地址。

2023-09-11 21:42:10 66

空空如也

空空如也

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

TA关注的人

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