- 博客(84)
- 收藏
- 关注
原创 【C++】多态详解——虚函数、重写、原理、抽象类(超详细)
本文深入讲解C++多态的核心概念与实现原理,主要内容包括: 多态概念:同一操作在不同对象上产生不同结果,分为静态多态(编译时)和动态多态(运行时) 实现条件: 必须通过基类指针/引用调用虚函数 被调函数必须是虚函数且子类完成重写 关键机制: 虚函数(virtual修饰) 虚函数重写(函数签名完全相同) 虚表指针(_vfptr)和虚函数表 重要特性: 析构函数必须声明为虚函数以避免内存泄漏 override/final关键字的使用 纯虚函数与抽象类的规范作用 底层原理:多态通过虚表指针查找虚函数表,在运行时确
2026-05-13 15:55:21
682
原创 【C++】继承详解——基类/派生类、作用域、默认函数、菱形继承(超详细)
继承机制详解:面向对象编程的核心特性 本文全面介绍了C++继承机制的核心概念与应用,主要内容包括: 继承基础:继承是类层次的复用机制,通过基类(父类)和派生类(子类)的关系实现代码复用,减少冗余。 继承定义与访问权限:详细讲解了三种继承方式(public/protected/private)及其对成员访问权限的影响,总结为"基类private成员不可见,访问权限取更小值"的实用口诀。 赋值转换规则:介绍了派生类向基类赋值转换的"切片"机制,强调这种转换是单向的。 作用
2026-05-13 15:20:53
511
原创 【C++ 进阶】模板核心:非类型参数、特化、分离编译
模板是给通用类型用的,但是某些特定类型,按照默认模板逻辑会出错,这时候我们就需要特殊处理,这就叫模板特化这个模板对于int、double、自定义类型都没问题,但是如果传入指针呢?可能我们的原意是比较指针指向的内容,但是这里比较的是指针地址,不是指针指向的内容!结果完全错了,这时候,我们就需要对Date*类型特化.h文件放声明.cpp文件放实现最后链接到一起普通函数这样写完全没问题,但模板不行!复用性强,可以快速写通用代码,实现泛型编程模板是STL的基础,没有模板就没有STL。
2026-05-12 16:27:06
396
原创 【C++】编程必备:深入解析priority_queue的使用与实现
本文介绍了C++中priority_queue(优先级队列)的基本概念、使用方法和初步实现。priority_queue本质上是一个堆数据结构,默认实现为大堆(降序排列),通过传入greater仿函数可改为小堆(升序排列)。文章详细讲解了priority_queue的接口使用,包括push、pop、top等操作,并给出了堆排序的示例代码。在实现部分,作者逐步构建了priority_queue的基本框架,包括容器适配器结构、empty/size/top等基础接口,以及关键的push和pop操作(涉及向上调整和
2026-05-12 16:20:46
538
原创 【C++】编程必备:深入解析仿函数与std::sort
本文介绍了C++中仿函数的概念与应用。仿函数本质是重载了operator()的类,使其对象可以像函数一样调用。文章首先通过加法仿函数示例展示了两种使用方法:实例化对象调用和使用匿名对象调用。随后介绍了标准库中的常见仿函数greater和less,以及它们在sort排序算法中的应用。最后讨论了自定义类型排序场景,指出当处理复杂类型时需要手动实现仿函数,并以日期类为例说明了如何重载比较运算符来实现自定义排序规则。仿函数相比普通函数的优势在于可以携带状态信息,并能作为模板参数传递,为C++编程提供了更灵活的功能实
2026-05-11 19:45:08
336
原创 【C++】编程必备:深入解析stack和queue的使用和实现(附源码)
本文介绍了栈(stack)和队列(queue)的基本使用与实现。首先通过示例代码演示了stack和queue的常用接口操作,如push、pop、top等。然后讲解了容器适配器的概念,指出stack和queue是基于其他容器(如vector、deque)实现的特殊容器。重点详细讲解了stack的实现过程,包括使用vector作为底层容器,封装empty、size、push、pop等接口,并提供了完整的测试代码和运行结果。文章最后给出了stack的完整实现源码,展示了如何通过容器适配器模式高效实现栈数据结构。
2026-05-11 19:44:27
435
原创 【C++】STL基础必备:深入解析list容器的实现(含源码)
本文详细介绍了C++ STL中list容器的底层实现。首先分析了list的双向循环链表结构,包括节点定义和list类的基本框架。然后讲解了默认成员函数的实现,包括构造、拷贝构造、赋值重载和析构函数。重点阐述了list迭代器的特殊实现方式,通过封装节点指针并重载运算符来模拟指针行为,解决了链表节点不能直接解引用和++的问题。文章还提供了普通迭代器和const迭代器的实现思路,为理解STL容器的底层机制提供了重要参考。
2026-05-10 16:11:35
368
原创 【C++】STL基础必备:深入解析list容器的使用
本文介绍了C++ STL中list容器的基本使用方法和特性。list是一个双向带头循环链表的类模板,与vector相比具有不同的底层实现但相似的接口。文章详细讲解了list的默认构造、普通构造、拷贝构造等成员函数,以及元素访问、容量查询、迭代器使用等接口。重点演示了push_back/pop_back、push_front/pop_front等修改操作,并通过代码示例展示了insert方法在指定位置插入元素的用法。list作为链表结构,在头部和尾部操作上具有O(1)的时间复杂度优势,适合频繁插入删除的场景。
2026-05-09 20:49:05
359
原创 【C++】编程必备:深入解析vector容器的使用
本文介绍了C++中vector容器的基本使用方法和常用接口。主要内容包括: vector简介:vector是一个类似于顺序表的类模板,属于STL库,比string更加灵活规范。 构造与析构: 默认构造不初始化底层数组 支持n个value构造和initializer_list初始化 拷贝构造和赋值重载采用深拷贝 元素访问接口: 支持[]运算符和at()访问元素 front()和back()分别获取首尾元素 容量相关接口: size()和capacity()获取大小和容量 resize()和reserve()调
2026-05-08 17:22:02
395
原创 【C++】STL基础必备:深入解析vector容器的实现(含源码)
本文详细解析了C++ STL中vector的实现原理与核心接口。文章首先介绍了vector的底层结构,通过分析STL源码指出vector使用三个指针成员(_start、_finish、_endofstorage)来管理动态数组。随后依次实现了vector的容器相关接口(size、capacity、empty)、元素访问接口(operator[]、at、front、back)、迭代器接口以及修改接口(reserve、resize、push_back等)。重点对比了vector与string在实现上的异同,特别
2026-05-07 21:41:13
648
原创 【C++】深入探索string类的实现(下)(含源码)
流插入运算符重载是为了方便我们给string对象手动进行输入,写这个函数要注意的地方还是挺多的,第一个注意的点是我们去读取字符的时候不能直接用cin,因为cin不会读取空格和\n,要想读取所有类型的字符就要用istream对象的成员函数get,等下我们会演示。这两个接口如果n比size大都会填充字符,只是第一个字符填充\0,而第二个接口需要指定填充的字符,所以我们其实可以把这两个接口写成一个接口,其中字符c的默认值为\0就可以了,接下来我们来分析如何实现resize。
2025-03-26 16:03:18
1619
5
原创 【C++】深入探索string类的实现(上)
之前我们也介绍过npos,它其实是一个size_t类型的静态成员变量,并且是一个常量,它的值非常大,这个npos可以给用户使用,所以它的声明要放在类的public的限制下,那么我们怎么给它一个非常大的值呢?这样写是一定没有问题的,但是我们其实还有一个更妙的方法,就是借助编译器帮我们做这些事情,具体思路是在函数中创建一个局部对象,这个对象是str的拷贝,然后我们直接将这个局部对象的资源拿过来,也就是进行交换。
2025-03-18 09:51:20
1582
2
原创 【C++】STL全面简介与string类的使用(万字解析)
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架简单的说就是STL中包含了各种我们之前写过的数据结构与方法,如顺序表、链表等等,被成为STL容器,其中还包含一些简单的算法,如查找、排序、交换等等,以及一些很常用的东西,我们下面都都会一一介绍。
2025-03-12 17:48:13
2273
3
原创 【C++】模板编程入门指南:零基础掌握泛型编程核心(初阶)
问题来了,我们该怎么解决这个问题呢?在上面的例子中,我们使用模板写了一个Swap函数,属于函数模板,编译器按需实例化出一个又一个的Swap函数,比如我们传int类型的参数,编译器就会生成int类型的Swap函数,就跟我们上面讲的草莓玩具的例子一样,根据模具就能很轻松的制作出来草莓玩具。隐式实例化就是不需要程序员指定相应的类型,让编译器自己去根据实参的类型实例化出对应的函数,比如之前我们举的Swap函数的例子,我们使用的就是隐式实例化,因为我们没有指定函数内部的类型,是靠编译器根据实参实例化出的。
2025-03-04 21:47:00
2768
81
原创 【C++】动态内存管理:织梦寻优,在代码世界中编织高效内存的诗篇
1. 调用operator new函数申请空间(operator new的底层封装了malloc,根据malloc的返回值来决定是否抛出异常)2. 在申请的空间上执行构造函数,如果没有传参那么调用默认构造,如果传参了就按照参数完成构造,最终完成对象的构造1. malloc、calloc、realloc以及free是函数,new和delete是操作符2. malloc需要计算开辟空间的大小,并且需要强转类型,new无需计算空间的大小,只需要写出对应的类型。
2025-02-23 20:43:20
3139
90
原创 【C++】类与对象全面剖析(尾卷)(构造深化、类型转换、static成员特性及内部类与匿名对象)
也就是说内部类只是定义在当前类中,当前类实例化出来的对象不会包含内部类,并且这个内部类默认是外部类的友元类,内部类本质也是⼀种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使⽤,那么可以考虑把A类设计为B的内部类,如果放private/protected位置,那么A类就是B类的专属内部类,其他地⽅都⽤不了。这个就要涉及到上面我们才讲过的知识,那就是一个成员变量如果走了初始化列表就不会走后面,而如果一个成员变量没有走初始化列表就会走后面的逻辑。
2025-02-19 23:07:41
2649
88
原创 【C++】类与对象初级应用篇:打造自定义日期类与日期计算器(2w5k字长文附源码)
其实上面我们写的日期加减天数的代码逻辑还有一点问题,因为凡事不一定都是按照我们的预想来的,用户有可能会出现一些我们没有考虑到的情况,在之前的代码中我们都下意识的认为用户会输入一个正数,但是有没有可能用户会输入一个负数呢?也就是说,我们日期加一个负的天数,可以看作想算当前日期n天之前的日期,所以也不能说是无意义的,同理,日期减一个负数逻辑上也说的通,所以我们在这部分主要就是来判断一下,如果用户传给我们的天数是负数怎么办//日期+=一个天数//在进行加等前,先判断day是否为负。
2025-01-25 23:40:55
2897
78
原创 【C++】揭秘类与对象的内在机制(核心卷之运算符重载、赋值重载与取址重载的奥秘)
4. 如果⼀个重载运算符函数是成员函数,则它的第⼀个运算对象默认传给隐式的this指针,因此运算符重载作为成员函数时,参数⽐运算对象少⼀个,比如重载+运算符,如果是成员函数时,左操作数默认就是this,也就是当前对象,不需要写出来,只需要写和当前对象做运算的另一个对象,只有一个参数。上面就是我们日期类的相等运算符的重载函数,是不是一点都不难呢?这里我们还需要知道另一个规则,就是第3、4点,其中第3点中我们知道了,如果重载的运算符中有两个操作数,那么左边的那个参数就是左操作数,右边的那个参数就是右操作数。
2025-01-22 22:16:57
3893
76
原创 【C++】揭秘类与对象的内在机制(核心卷之深浅拷贝与拷贝构造函数的奥秘)
根据上面的分析,编译器确实帮我们自动完成了优化,减少了拷贝,是不是非常神奇,接下来我们来讲一下拷贝构造的另一个大坑,就是我们在用临时对象拷贝构造st2时,有一个小细节,就是临时对象具有常性,可以看作临时对象都被const修饰了,如果要让临时对象拷贝构造给st2,上面的拷贝构造函数的第一个形参必须加上const,否则就会出错。接下来就该进行传值返回了,这里就稍微有点不一样了,因为我们的形参st在函数结束后会调用析构进行销毁,所以我们的形参st是不能直接作为返回值的,那么该怎么办呢?
2025-01-18 16:41:02
3237
82
原创 【C++】揭秘类与对象的内在机制(核心卷之构造函数与析构函数的奥秘)
上面就是默认生成的构造函数的所有行为,**总结一下:**如果是内置类型的成员变量,默认生成的构造函数的处理是由编译器决定,有可能是随机值,也可能是0,如果是自定义类型的成员变量,默认生成的构造函数会调用这个自定义类型的默认构造,如果这个自定义类型没有默认构造编译器就会报错。上面的Date函数就是一个日期类的无参构造函数,我们可以观察一下它的特点,它的函数名就是类名,并且没有返回值,void都没有,当我们这个构造函数写出来之后,编译器就不会帮我们生成构造函数了,会直接调用我们写的构造函数。
2025-01-15 15:36:39
4541
63
原创 【C++】揭开C++类与对象的神秘面纱(首卷)(类的基础操作详解、实例化艺术及this指针的深究)
/结构体的定义int* arr;int size;//要以分号结尾//类的定义int* _arr;int _size;//要以分号结尾上面就是结构体和类定义的对比,可以看到类和结构体的定义几乎一模一样,因为class类本身就是为了修正C语言中结构体的不足而创造,所以定义和结构体几乎一样,那么接下来我们就来说说类的特点、以及C++和C语言结构体、C++结构体和C++类的区别class为定义类的关键字,Stack为类的名字,{ }中为类的主体,注意类定义结束时后⾯分号不能省略。
2025-01-10 20:54:03
3175
90
原创 【C++】穿越编程岁月,细品C++进化轨迹,深化入门基石(续章)——揭秘函数缺省参数的魅力、函数重载的艺术、引用的奥秘与内联函数的效率
引用是C++提出的新概念,它不是新定义⼀个变量,⽽是给已存在变量取了⼀个别名,从语法角度来说,编译器不会为引⽤变量开辟内存空间,它和它引⽤的变量共⽤同⼀块内存空间,就像我们小时候的乳名一样,叫现在的名字是我们,叫乳名也是我们类型 & 别名 = 引⽤对象类型后面跟的就是跟取地址一样的符号,但是要注意区分,那并不是取地址操作符,而是引用操作符,那么为什么这个符号都已经用作取地址了,还要拿来给引用使用呢?
2025-01-07 09:53:45
4463
74
原创 【C++】穿越时光隧道,拾贝史海遗珍,轻启C++入门之钥,解锁程序之奥秘(首卷)
定义命名空间的格式:将namespce关键字写在最前面,随后写上命名空间的名称,然后接⼀对{}即可,{}中即为命名空间的成员。int data;//C++中结构体可以不加struct直接使用在上面的命名空间中,它的名称就是TL,在命名空间中我们什么都可以定义,那么命名空间的定义有什么好处呢?它怎么解决命名冲突的呢?
2025-01-03 14:08:59
5289
101
原创 【初阶数据结构与算法】排序算法总结篇(每个小节后面有源码)(直接插入、希尔、选择、堆、冒泡、快速、归并、计数以及非递归快速、归并排序)
本篇内容将从稳定性与复杂度等角度分析排序算法,列出它们的特点、优点以及缺点,希望大家有所收获,如果想更加细节地学习可以去看我之前写的各种排序算法的文章。
2024-12-31 14:04:09
5764
102
原创 【初阶数据结构与算法】八大排序之非递归系列( 快排(使用栈或队列实现)、归并排序)
其实大致总结一下,如果递归的形式像前序遍历,那么我们才能使用栈来模拟它的行为,如果类似于中序和后序遍历就不行,根本原因还是前序遍历会先处理根,不需要左右子树的信息,而中序和后序遍历时,处理根就会需要左子树或者左右子树的信息,而栈只能模拟先处理根的情况。所以我们就可以写代码来模拟这个过程,首先将数组的一个元素划分为一组,然后两组两组进行合并,只不过将数组两组两组合并完之后,我们要将数组重新进行分组,变成两个元素划分为一组再进行合并,反复进行上面的操作,直到数组不能再划分。结论是不可以,那么这是为什么呢?
2024-12-28 23:34:57
3763
104
原创 【初阶数据结构与算法】八大排序算法之归并排序与非比较排序(计数排序)
那么接下来我们就先来学习如何分解,其实就是利用递归,进行划分,和我们二叉树的后序遍历有点相似,将整个过程看作二叉树的后序遍历,先将给出的数,组划分成左右两部分,然后再将左右继续划分成两部分,这就相当于递归左右子树,这就是分解的过程。然后就是对分解好的序列进行合并,我们可以发现,每一次合并时都是对有序序列进行合并,如果只有单个元素的话,也可以看作有序,两个单独的元素合并后,又变成了有序的序列,如上面演示的图,所以我们的合并其实就是对两组有序序列进行合并。
2024-12-24 17:11:09
2756
110
原创 【初阶数据结构与算法】八大排序算法之交换排序(冒泡排序,快速排序---hoare、挖坑法、lomuto双指针3种版本)
快速排序是Hoare于1962年提出的⼀种⼆叉树结构的交换排序⽅法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两⼦序列,左⼦序列中所有元素均⼩于基准值,右⼦序列中所有元素均⼤于基准值,然后最左右⼦序列重复该过程,直到所有元素都排列在相应位置上为⽌大致含义就是,快排的主要思路就是将一个数组按照给定的基准值不断分成两截,然后对它们进行处理,将所有小于基准值的放在在基准值的左边,大于基准值的放在基准值的右边,最好的情况下可以二分进行排序,非常高效。
2024-12-20 22:36:18
3281
113
原创 【初阶数据结构与算法】八大排序算法之选择排序(直接选择排序、堆排)
可以看到之前的问题被我们完全解决了,这就是我们真正的双向直接选择排序,接着我们分析一下它的时间复杂度,虽然比起单向的循环少了一半,但是还是属于O(N^2)级别,也不算太优,到最后我们再将它们来进行比较,我们继续学习下面的内容。当我们比较完堆排和直接选择排序之后,我们来比较一下单向和双向两个直接选择排序,我们惊讶地发现,单向的直接选择排序居然更快,理论上来说,双向是单向的优化,循环次数更少,为什么还会出现这种问题呢?这里的双向直接选择排序几乎和单向直接选择排序差别不大,那么是否它已经没有问题了呢?
2024-12-16 22:24:31
2576
134
原创 【初阶数据结构和算法】八大排序算法之插入排序(直接插入排序、希尔排序及其对比)
方法就是,记录下来end+1位置的数据,因为end是左边有序的序列的最后一个数据,那么end+1自然就是右边待排序序列的第一个数据,我们要将end+1这个位置的数据插入到左边的有序序列中,首先就是将它用变量tmp记录下来,它就是我们要往左边有效序列中插入的数据。这也正是我们直接插入排序的算法思想,将所有的数据分成两部分,左边就是已经排好序的数据,右边则是待排序数据,就是我们上面扑克牌的思想,随后我们将右边待排序的数一个一个插入到有序的数据中,直到最后一个数据插入完成,所有数据也就有序了。
2024-12-13 15:13:27
5127
118
原创 【初阶数据结构与算法】初阶数据结构总结之顺序表、单链表、双链表、栈、队列、二叉树顺序结构堆、二叉树链式结构(附源码)
二、单链表单链表的特点:单链表是一种线性数据结构,其特点主要体现在以下几个方面:(1)节点分散存储:单链表的节点在内存中不是连续存储的,每个节点包含数据域和指针域(或称为链域),指针域存储着下一个节点的地址。(2)链式存储结构:通过指针将各个节点连接起来,形成一条链式的存储结构。这种结构使得单链表在插入和删除节点时不需要移动其他节点的位置。(3)头指针唯一:单链表通常有一个头指针(或称为头节点),它指向链表的第一个节点(如果链表不为空)。头指针是链表的唯一入口。(4)节点访问需从头开始:由于节
2024-12-11 08:12:40
8618
132
原创 【初阶数据结构与算法】二叉树链式结构刷题训练(Leetcode二叉树遍历、单值二叉树、相同的树、另一棵树的子树、对称二叉树)
这里左边的p节点的左子树3和右边q节点的右子树3进行递归,它们都在外面,所以返回的结果用一个新的变量outside存起来,p节点的右子树4和q节点的右子树4进行递归,它们都在里面,所以返回的结果用新变量inside存起来。这道题是要求我们查看左边的二叉树里面的子树有没有和右边子树相同的,这道题相对于比前面的相同的树要稍微要难一点点,因为我们发现它们都是求树和树是否相同的问题,只是到这道题是查看左边的子树和右边的树是否相同,情况更为复杂。那么我们最后到底该怎么做呢?
2024-12-07 23:37:45
3975
132
原创 【初阶数据结构与算法】二叉树链式结构的定义与实现万字笔记(附源码)
链式二叉树就是⽤链表来表⽰⼀棵⼆叉树,即⽤链来指⽰元素的逻辑关系,通常的⽅法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别⽤来给出该结点左孩⼦和右孩⼦所在的链结点的存储地址,数据域则是当前节点存放的数据,其结构如下: 当我们使用链式结构来表示二叉树时,这个二叉树并不会有很多限制,它对节点的插入删除等操作要求并不高,所以我们后面会手动来创建链式二叉树,本文重要的不是创建二叉树的方法,而是二叉树各种功能的实现 那么什么时候我们不能手动创建二叉树了呢?这个就要等我们后面在C++部
2024-12-05 23:12:35
2311
113
原创 【初阶数据结构与算法】二叉树顺序结构---堆的应用之堆排、Top-K问题
首先我们要对数组进行排序,那么大概率我们会拿到一个乱序的数组,我们需要通过调整,将这个乱序的数组模拟成为一个堆,因为堆的底层也是用数组存储的,我们要是能让数组模拟成为一个堆,就可以不必再写一个堆这样的数据结构辅助排序了。如果这个数据比堆顶大,说明出现了一个较大的值得入堆的数据,那么我们就把当前堆中的堆顶删掉,让这个数据入堆,然后再拿这个堆的堆顶和剩余元素比较,重复上面的操作,那么到最后,这存放k个数据的堆一定就是前k个最大的数据。那么我们能不能将每个节点当作父节点都进行一次向下调整呢?
2024-12-03 15:26:53
2491
134
原创 【初阶数据结构和算法】二叉树顺序结构---堆的定义与实现(附源码)
【初阶数据结构和算法】初识树与二叉树的概念以及堆和完全二叉树之间的关系堆的本质是一颗完全二叉树,只是它的要求比完全二叉树更加严格,它要求每颗子树的根节点都是当前子树的最大值或最小值,当根节点是最大值时,它就是一个大根堆,当根节点是最小值时,它就是一个小根堆在上篇文章中我们也提到了,存储完全二叉树可以使用数组,存储非完全二叉树可以使用链表,而堆就是一种特殊的完全二叉树,所以堆的存储我们就使用数组,也就是顺序表的形式,如图:int size;}HP;
2024-11-30 19:49:17
3332
116
原创 【初阶数据结构和算法】初识树与二叉树的概念以及堆和完全二叉树之间的关系
在上面的三个示例图中,它们的根节点都是A,然后BCD三个节点分别构成了三课子树,BCD可以认为是三颗子树的“根节点”,但是它们并非是真正的树形结构,因为子树之间有了交集,不满足刚刚讲的树的最后一个特点,所以不构成真正的树形结构。⼆叉树的链式存储结构是指,⽤链表来表⽰⼀棵⼆叉树,即⽤链来指⽰元素的逻辑关系。在堆中,子树之间是独立存在的,互不影响,我们只看一颗子树的根节点是否是这颗子树的最小值,在左子树中15是它的最小值,在右子树中56是它的最小值,所以它依然满足堆的定义,因为子树之间是独立存在的,互不影响。
2024-11-27 20:21:52
3945
130
原创 【初阶数据结构和算法】leetcode刷题之设计循环队列
现在我们知道了使用数组,所以循环队列中肯定要有一个数组,但是我们不知道数组的具体大小,需要到时候根据初始化函数的参数确定,所以我们这里直接用一个指针代替,到时候动态申请空间由于队列要遵循头删尾入,所以我们最好像定义队列一样,定义两个下标front和rear分别指向循环队列的头和尾(这个尾相当于顺序表中的size),方便进行操作,还有就是我们要知道申请了多大空间,所以用一个整型变量capacity来存储那么是否要头删使用数组的效率会很低呢?int* arr;int rear;int front。
2024-11-25 23:02:28
5314
137
原创 【初阶数据结构与算法】栈和队列leetcode刷题之用栈实现队列,用队列实现栈
在本节的题目中都会用到数据结构栈和队列,由于我们目前没有介绍C++,以C语言的形式来做,所以我们需要把我们之前实现好的栈和队列复制进去再做,等以后我们讲到C++部分就可以使用STL,不用自己手动写栈和队列了。
2024-11-23 20:04:28
2173
126
原创 【初阶数据结构与算法】线性表之队列的定义与实现
队列和栈一样既可以选择数组做底层,也可以选择链表作为它的底层,那么哪一个更好呢?这个就需要我们去分析一下了如果采用数组,那么我们入队列就可以直接在数组最后添加数据,时间复杂度为O(1),比较方便,但是当我们要从数组头删数据就比较麻烦了,因为数组头删的时间复杂度为O(N),效率并不是很高我们再来分析一下使用链表怎么样,如果我们使用链表实现队列,那么在头部删除没有问题了,时间复杂度为O(1),但是我们要在最后插入数据,对于链表来说,尾插的时间复杂度是O(N),那么到底选哪一个才好?
2024-11-21 21:42:45
2348
136
原创 【初阶数据结构与算法】线性表之栈的定义与实现(含源码和有效的括号练习)
栈结构的定义与顺序表类似,还是需要三个成员,一个需要动态开辟空间的数组,记录数组有效元素个数和总容量的整型//需要动态开辟的数组int top;//有效元素个数//数组总容量}ST;这里我们提一下,如果顺序表学懂了那么栈就会很简单,等我们实现完了栈就会发现,栈其实是特殊形式的顺序表,我们拭目以待吧!
2024-11-19 22:13:43
2376
143
原创 【初阶数据结构与算法】链表刷题之链表分割、相交链表、环形链表1、环形链表I、环形链表II
我们要注意到相交链表的特殊性,直线相交的话它们还会朝着不同的方向继续延伸,想象一下链表相交以后会怎么样,它们相交后一定只有一个方向,而不会像直线相交那样有多个方向,因为如果它们相交,那么相交节点的next指针指向同一个节点,如此循环下去自然就只有一个方向。所以我们还是用上之前学过的知识,怎么保证一个链表默认不为空?这里我们要注意的是,如果我们创建的两个链表初始为空会发生什么,我们每次插入节点时,都要判断要插入的链表是否为空,空和非空的操作不一致,加上我们有两个新链表,操作起来更加的繁琐。
2024-11-17 23:06:16
3438
108
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅