自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 【C++】unordered_map和unordered_set的模拟实现

首先对关键码集合用散列函数计算散列地址,具有相同地址的关键码归于同一子集合,每一个子集合称为一个桶,各个桶中的元素通过一个单链表链接起来,各链表的头结点存储在哈希表中。哈希(散列)是一种通过函数直接映射元素存储位置的存储方法,核心是用“哈希函数”把元素的关键码转成存储位置,从而跳过比较、提升效率。如果不扩容,不断插入,某些桶越来越长,效率得不到保障,让负载因子适当放大一些,一般负载因子控制在1,平均下来每个桶存一个数据。注意:哈希函数设计的越精妙,产生哈希冲突的可能性就越低,但是无法避免哈希冲突。

2025-11-25 06:00:00 695

原创 【C++】位图和布隆过滤器

因为无符号整数的最大值为2^32 - 1,所以我们可以用2^32个比特位来标记对应值在不在(直接定址法),又因1byte = 8bit,所以仅需2^29个byte,即0.5G左右,这对于计算机来说是非常容易的。一个文件所有值映射到一个位图,另一个文件判断在不在,标记时就对两个位图去重,因为文件中可能有重复的元素。数据是否在给定的整形数据中,结果是在或不在两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果二进制比特位为1代表在,为0代表不在。它是用多个哈希函数,将一个数据映射到位图结构中。

2025-11-22 13:59:37 988

原创 【C++】红黑树

倍,相对而言,降低了插入和旋转的次数,所以在经常进行增删的结构中性能比AVL。,红黑树不追求绝对平衡,其只需保证最长路径不超过最短路径的2。树更优,而且红黑树实现比较简单,所以实际运用中红黑树更多。树都是高效的平衡二叉树,增删改查的时间复杂度都是。针对每种情况进行相应的处理即可。检测其是否满足红黑树的性质。检测其是否满足二叉搜索树。中序遍历是否为有序序列。

2025-11-20 07:00:00 672

原创 【C++】AVL树

树做一些结构修改的操作,性能非常低下,比如:插入时要维护其绝对平衡,旋转的次数比较多,更差的是在删除时,有可能一直要让旋转持续到根的位置。因此:如果需要一种查询高效且有序的数据结构,而且数据的个数为静态的(树是一棵绝对平衡的二叉搜索树,其要求每个节点的左右子树高度差的绝对值都不超过。树也是二叉搜索树,可按照二叉搜索树的方式将节点删除,然后再更新平衡因子。树中插入一个新节点,可能造成不平衡,此时必须调整树的结构,树是在二叉搜索树的基础上加入了平衡性的限制,因此要验证。树也可以看成是二叉搜索树。

2025-11-16 08:56:24 800

原创 【C++】map和set

关联式容器是用来存储数据的,与序列式容器(vector,list,deque等)不同的是,其里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高。键值对是用来表示具有一一对应关系的一种结构,该结构中一般只包含两个成员变量key和value,key代表键值,value表示与key对应的信息。是按照特定顺序存储元素的容器,其中元素是可以重复的。中的元素如果用迭代器去遍历,可以得到一个有序的序列。作为其底层结果,容器中的元素是一个有序的序列。中的元素进行遍历,可以得到有序的序列。

2025-11-09 16:52:23 951

原创 【C++】二叉搜索树

在二叉搜索树中检索该单词是否存在,存在则拼写正确,不存在则拼写错误。、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。若它的左子树不为空,则左子树上所有节点的值都小于根节点的值;若它的右子树不为空,则右子树上所有节点的值都大于根节点的值;、最多查找高度次,走到到空,还没找到,这个值不存在。树不空,按二叉搜索树性质查找插入位置,插入新节点。,统计成功后,给定单词就可快速找到其出现的次数,,通过英文可以快速找到与其对应的中文,英。树为空,则直接新增节点,赋值给。,构建一棵二叉搜索树,

2025-10-31 22:53:36 573

原创 C++-类和对象(下)

内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,编译器一定会先使用初始化列表初始化。,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。非静态的成员函数调用需要this指针,静态的成员函数没有this指针。,不属于任何类,但需要在类的内部声明,声明时需要加。

2025-08-28 23:23:22 635

原创 C++-类和对象(中)

注意:为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用尽量使用引用。注意:内置类型成员变量是直接赋值的,而自定义类型成员变量需要调用对应类的赋值运算符 重载完成赋值。我们不写,编译器默认生成构造函数,内置类型不做处理,自定义类型会去调用它的默认构造。如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如。一般情况下,有内置类型成员,就需要自己写构造函数,不能用编译器自己生成的。有些编译器也会处理内置类型,但是那是个性化行为,不是所有编译器都会处理。

2025-08-25 11:09:35 562

原创 C++-类和对象(上)

计出需要什么东西,但是并没有实体的建筑存在,同样类也只是一个设计,实例化出的对象。如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整。补充(内联函数):适用于短小的频繁调用的函数,不适用于比较长的函数和递归函数。其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。一样的东西,限定了类有哪些成员,定义出一个类。类实例化出的对象才有具体的年龄。修饰的成员在类外不能直接被访问。,类的所有成员都在类的作用域中。

2025-08-22 20:43:33 843

原创 C++入门

概念:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数或类型或类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。//预处理:头文件展开,宏替换,条件编译,去掉注释等。比如:李逵,在家称为“铁牛”,江湖上人称“黑旋风”。//汇编:汇编代码转换成二进制机器码。//编译:检查语法,生成汇编代码。2.我们互相之间冲突。

2025-08-17 19:32:57 159

原创 C语言-二叉树的相关算法

堆本质上是一棵完全二叉树,堆中某个结点的值总是不大于或不小于其父结点的值。排升序---建大堆 排降序---建小堆。层序遍历:一层一层的,需借助队列的先进先出。非完全二叉树按层序走,空节点后还有非空结点。完全二叉树按层序走,非空节点一定是连续的。向下调整的条件:左右子树都是大堆/小堆。前序遍历:根 左子树 右子树。中序遍历:左子树 根 右子树。后序遍历:左子树 右子树 根。物理结构:在内存中是如何存储的。时间复杂度:N*logN。逻辑结构:是想象出来的。

2025-08-17 16:12:32 223

原创 C语言-常见排序算法

稳定性判断:如果在原数组中两个相同数据的位置是固定的,那么在排序后两者的前后位置关系不能发生改变,即之前位于前面,排序后依然在另一个数之前,称该排序是稳定的,反之则不稳定。每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到待排序的数据元素全部排完。把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为。的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题。将值较大的数据向序列的尾部移动,值较小的数据向序列的前部移动。

2025-08-15 22:15:24 686

原创 C语言-树及二叉树的相关概念

对任意一棵二叉树,如果度为0其叶结点个数为n0,度为2的分支结点个数为n2,则有n0 = n2 + 1。高度为h的完全二叉树,结点数量的范围为[2^(h - 1), 2^h - 1]:若一个节点含有子节点,则这个节点称为其子节点的父节点;:一个节点含有的子树的根节点称为该节点的子节点;:以某节点为根的子树中任一节点都称为该节点的子孙。:一个节点含有的子树的个数称为该节点的度;:具有相同父节点的节点互称为兄弟节点;:一棵树中,最大的节点的度称为树的度;:从根到该节点所经分支上的所有节点;

2025-08-08 21:09:13 189

原创 C语言字符函数和字符串函数

这个头文件中说明 的,C语言程序启动的时候就会使用⼀个全局的变量 errno 来记录程序的当前错误码,只不过程序启动的时候errno是 0,表示没有错误,当我们在使用标准库中的函数的时候发生了某种错误,就会将对应的错误码,存放在 errno 中,而⼀个错误码的数字是整数很难理解是什么意思,所以每⼀个错误码都是有对应的错误信息的。比较str1和str2的前num个字符,如果相等就继续往后⽐较,最多比较num个字母,如果提前发现不⼀ 样,就提前结束,大的字符所在的字符串大于另外⼀个。那么如何判断两个字符串?

2025-07-31 20:11:32 976

原创 C语言深入理解指针(4)

⼆维数组的数组名表示的就是第⼀行的地址,是⼀ 维数组的地址。根据上面的例子,第⼀行的⼀维数组的类型就是 int [5]那就意味着⼆维数组传参本质上也是传递了地址,传递的是第⼀行这个⼀维数组的地址,那么形参也是可以写成指针形式的。解释:p先和*结合,说明p是⼀个指针变量,然后指针指向的是⼀个大小为10个整型的数组。先和 [ ] 结合,说明 parr1是数组,数组的内容是int (*)(),所以第⼀行的地址的类型就是数组指针类型 int(*)[5]数组指针变量是存放的是数组的地址,能够指向数组的指针变量。

2025-07-31 15:54:51 163

原创 C语言深入理解指针(3)

arr[0]和&arr[0]+1相差4个字节,arr和arr+1 相差4个字节,是因为&arr[0] 和 arr 都是首元素的地址,+1就是跳过⼀个元素。同理,arr[i] 应该等价于 *(arr+i),数组元素的访问在编译器处理的时候,也是转换成首元素的地址+偏移量求出元素的地址,然后解引用来访问的。parr[i]是访问parr数组的元素,parr[i]找到的数组元素指向了整型⼀维数组,parr[i][j]就是整型⼀维数组中的元素。组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素。

2025-07-31 15:14:30 319

原创 C语言深入理解指针(2)

我们现在要解决的就是当调用Swap函数的时候,Swap函数内部操作的就是main函数中的a和b,直接将a和b的值交换了。那么就可以使用指针了,在main函数中将a和b的地址传递给Swap函数,Swap 函数里边通过地址间接的操作main函数中的a和b,并达到交换的效果就好了。如果明确知道指针指向哪里就直接赋值地址,如果不知道指针应该指向哪里,可以给指针赋值NULL. NULL 是C语言中定义的⼀个标识符常量,值是0,0也是地址,这个地址是无法使用的,读写该地址会报错。版本中,直接就是优化掉了。

2025-07-30 20:04:58 948

原创 C语言深入理解指针(1)

前面的内容我们了解到,32位机器假设有32根地址总线,每根地址线出来的电信号转换成数字信号后是1或者0,那我们把32根地址线产生的2进制序列当做⼀个地址,那么⼀个地址就是32个bit位,需要4 个字节才能存储。同理64位机器,假设有64根地址线,⼀个地址就是64个⼆进制位组成的⼆进制序列,存储起来就需要 8个字节的空间,指针变量的大小就是8个字节。计算机上CPU(中央处理器)在处理数据的时候,需要的数据是在内存中读取的,处理后的数据也会放回内存中,内存划分为⼀个个的内存单元,每个内存单元的大小取1个字节。

2025-07-30 17:42:09 552

原创 C语言数据在内存中的存储

但是,我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存⼊内存时E的真实值必须再加上⼀个中间数,对于8位的E,这个中间数是127;以32位浮点数为例,留给M只有23位,将第⼀位的1舍去以后,等于可以保存24位有效数字。型(要看具体的编译器),另外,对于位数大于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于⼀个字节,那么必然存在着⼀个如何将多个字节安排的问题。对于32位的浮点数(float),最高的1位存储符号位S,接着的8位存储指数E,剩下的23位存储有效数字M。

2025-07-28 22:47:37 1344

原创 C语言结构体

而对齐的内存访问仅需要⼀次访问。下图是网络协议中,IP数据报的格式,我们可以看到其中很多的属性只需要几个bit位就能描述,这里使用位段,能够实现想要的效果,也节省了空间,这样网络传输的数据报大小也会较小⼀些,对网络的畅通是有帮助的。如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。3.4、当⼀个结构包含两个位段,第⼆个位段成员比较大,无法容纳于第⼀个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。

2025-07-28 20:04:55 795

原创 C语言编译和链接

前面我们非常简洁的讲解了⼀个C的程序是如何编译和链接,到最终生成可执行程序的过程,其实很多内部的细节无法展开讲解。程序同时也可以使⽤静态(static)内存,存储于静态内存中的变量在程序的整个执行过程 ⼀直保留他们的值。翻译环境是由编译和链接两个大的过程组成的,而编译又可以分解成:预处理(有些书也叫预编译)、编译、汇编三个过程。编译过程就是将预处理后的文件进行⼀系列的:词法分析、语法分析、语义分析及优化,生成相应的汇编代码文件。链接是⼀个复杂的过程,链接的时候需要把⼀堆文件链接在⼀起才生成可执行程序。

2025-07-27 22:48:15 746

原创 C语言的文件操作

我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输⼊输出 操作各不相同,为了⽅便程序员对各种设备进⾏⽅便的操作,我们抽象出了流的概念,我们可以把流 想象成流淌着字符的河。如果没有⽂件,我们写的程序的数据是存储在电脑的内存中,如果程序退出,内存回收,数据就丢失 了,等再次运⾏程序,是看不到上次程序的数据的,如果要将数据进⾏持久化的保存,我们可以使⽤⽂件。⽂件的内容不⼀定是程序,⽽是程序运⾏时读写的数据,⽐如程序运⾏需要从中读取数据的⽂件,或 者输出内容的⽂件。

2025-07-27 20:44:19 933

原创 基础扫雷游戏的实现

把除10个雷之外的所有非雷都找出来,排雷成功,游戏结束。.游戏可以通过菜单实现继续玩或者退出游戏。如果位置不是雷,就显示周围有几个雷。.使用控制台实现经典的扫雷游戏。如果位置是雷,就炸死游戏结束。扫雷的棋盘是9*9的格子。.扫雷游戏的代码实现。默认随机布置10个雷。

2024-12-15 18:03:21 167

原创 C语言分支和循环语句

三.while,do while,for,这三种循环往往会嵌套在一起才能更好的解决问题。||:逻辑或运算符,就是或者的意思(两侧至少有一个表达式为真,则为真,否则为假)&&:逻辑与运算符,就是并且的意思(两侧的表达式都为真,则为真,否则为假):switch后的expression必须是整形表达式。case后的值,必须是整型常量表达式。:逻辑取反运算符(改变单个表达式的真假)(在C语言中,0为假,非0表示真)if(a==b) ==判断相等。if(a=b) = 赋值。”>=“大于等于运算符。

2024-12-01 20:20:37 286 1

空空如也

空空如也

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

TA关注的人

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