- 博客(43)
- 收藏
- 关注
原创 算法沉淀五:位运算
给定一个数组,包含从 1 到 N 所有的整数,但其中缺了两个数字。2,3,4其实就是一类问题,本质就是一个哈希表,很多情况下就是一个数组。&上一个1,要么让第x位右移,要么让1左移,一般用右移x位, (n>>x)&1。如何表示-n:n的按位取反再加1,本质就是将最右侧的1的左边区域全部变成相反。:由于其他数字出现三次,该位的总次数对3取余即为唯一数字在该位的值(0或1)。n-1:将最右侧的1的右边的区域(包含1)全部取反。,因为有 2 个数字,所以所有的数字都在范围。2 是丢失的数字,因为它没有出现在。
2025-03-14 18:42:57
791
原创 【Linux网络】:数据的跨网传输
那么就要引入一个新的概念了。端口号和ip地址,都是用来起到一个标识的作用,其中对于端口号来说是用来标识唯一的一个进程,而ip地址是用来标识唯一的一个主机,那么借助这两个信息就可以在偌大的网络系统中找到一个特定的主机上的一个特定的进程,进而进行相关的信息输送或者是数据传递,也就是说,实际未来在进行通信的时候,根本就不是两个主机在进行通信,而是两个主机上的进程在进行通信,网络的本质不也是进程间通信吗?简单来说,ip地址可以保证的是全网的唯一性,而Mac地址只是运用在局域网中,在局域网中可以保证自己的特定性。
2025-03-10 12:30:00
694
原创 Linux:进程控制
对于所有进程的管理者操作系统来说,它需要知道关于进程的一系列信息,比如进程有没有退出,进程最后运行的结果如何,如果出错了是为什么出错的,而对于父进程来说,它创建的子进程也应该要有一定的返回值,通过不管何种形式的返回值,必须要让父进程知道,自己创建的这个子进程有没有完成自己当初交代给它的任务,如果完成了要返回完成,如果没有完成要知道没有完成的原因是什么,因此就引出了进程退出的概念。fork是Linux中一个很重要的函数,主要是在已经创建的进程中基础创建一个新的进程,新的进程为子进程,原来的进程被叫做父进程。
2025-03-01 18:56:20
1334
原创 Linux:Shell环境变量与命令行参数
比如,Linux中有ls命令,用来查看文件夹中的内容,如果使用的是ls -a或者是ls -l这些选项,就会产生不同的结果,实际上这样的结果也是通过这个原理,通过读取argv数组中的内容就可以实现各种目的。而在上面的测试中,像ls,mkdir这样的命令,都是shell通过fork创建子进程来执行的,而这里的PATH路径已经被用户破坏了,因此找不到搜索的路径,因此找不见是当然的事,但是为什么pwd可以找到?因为不同用户的家目录中的配置文件不一样,所以不同用户下的环境变量 HOME 也是不一样的。
2025-02-27 20:49:06
976
原创 Linux:进程的认识
Process:在 Linux 中,每个执行的程序都称为一个进程。每一个进程都分配一个 ID 号(PID,进程号)。与 Windows 下的任务管理器中的进程意思相同。在官方的定义中,进程通常被解释为“运行起来的程序”或“在内存中的程序”。这种定义虽然简单,但严格来说并不容易理解,因为进程和程序显然是不同的概念。程序是静态的,它是一组指令和数据的集合,存储在磁盘中;而进程是动态的,它是程序在内存中的执行实例,拥有独立的内存空间和系统资源。
2025-02-23 17:00:00
768
原创 C++:指针避坑指南
目录错误一:野指针错误二:忘记删堆内存错误三:解引用空指针错误四:delete指针后继续使用错误五:数组用单个delete删除错误六:指针运算越界错误七:返回局部变量的指针错误八:指针类型不匹配错误九:多重指针不打基础错误十:const和指针的位置摆错错误十一:构造函数漏初始化指针错误十二:函数参数传递指针没声明const错误十三:指针移动导致内存释放失败错误十四:指针和引用混用错误十五:不安全的指针向下转换错误十六:函数指针调用前未检查错误十七:在类里delete this 指针错误十八:智能指针互相引用
2025-02-22 09:09:08
599
原创 Linux:Makefile和缓冲区的基本概念
因此,可以这样进行总结,我们的代码与头文件再加上库就可以被形成可执行程序。所以,所谓的开发环境的安装,其实就是安装下载并拷贝头文件和库文件到开发环境中的特定路径下,让编译器可以找到。所谓开发环境要做到什么才能被称之为开发环境?1.下载开发环境中include和lib2.设置合理的查找路径3.规定好形成可执行程序的链接方式。
2025-02-17 11:34:10
1005
原创 Linux:shell命令运行原理和Linux权限的概念
人 + 事物属性Linux的权限往往是伴生于文件的,对于文件来说,权限是极其重要的,下面来进行权限和文件的理解。首先,对于一份文件,常常有下面的两类属性:第一个是人属性,即该文件是谁写的,谁有权力看,在Linux中把人的属性分为三种,分别为拥有者,所属者和其他人。第二个是事物属性,即这份文件可以被什么人用什么方式访问,在Linux中把文件的属性分为三种,分别为。
2025-02-16 15:49:55
933
原创 C++:高度平衡二叉搜索树(AVLTree) [数据结构]
AVL 树节点是一个三叉链结构,除了指向左右孩子的指针,还有一个指向其父亲的指针,数据域是键值对,即 pair 对象,还引入了平衡因子,用来判断是否需要进行平衡操作。// AVL树节点的定义(KV模型)// 该节点的左孩子// 该节点的右孩子// 该节点的双亲指针// 键值对int _bf;
2025-02-15 11:31:22
944
原创 C++:Map和Set
在理解这句前,要首先知道insert调用的结果是pair<iterator,bool> insert (const value_type& val),返回的是一个pair键值对,这里通过this指针调用了insert函数,再对所得到的键值对取它的first元素,也就是迭代器,再对迭代器进行解引用,迭代器指向的就是插入元素的位置,对迭代器的second解引用得到的就是Key_Value中的Value值。那就是关联式容器,那么有什么区别呢?关联式容器也是用来存储数据的,与序列容器不同的是,其存的是。
2025-02-13 21:17:52
1197
2
原创 算法沉淀四:前缀和
对于一个给定的数列,它的前缀和数列是这样构成的:前缀和数列的第n项等于原数列前n项的和。例如,有数列a = [1, 2, 3, 4],它的前缀和数列s中,主要用途是可以快速地计算数列中某个区间的和。如果想求数列a中从第m项到第n项(m \leq n)的和,利用前缀和可以通过s[n]-s[m - 1](当m > 1时)或者直接用s[n](当m = 1时)来快速得到结果,而不需要每次都从m项开始逐个相加到n项。还需从题目中发现它的奥秘!
2024-12-10 15:06:19
1084
原创 C++:多态的原理
重写是语法的叫法,覆盖是原理层的叫法。在通过监视窗口,出了有_b成员,还多了一个_vfptr数组,这个指针数组实际上叫做虚函数表指针数组,严格意义来说,一个含有虚函数的类中至少有一个虚函数表指针数组,这个数组中存放的是虚函数的函数地址,虚函数表也叫做虚表。这里 Derive 对象的两张虚表中的重写的 Derive::func1 函数,虽然函数地址不一样,但是当 Base1 或 Base2 指针指向 Derive对象时,调的都是 Derive 中的 func1,是同一个函数。多态的原理到底是什么?
2024-11-26 19:20:01
1443
原创 算法沉淀三:二分查找
什么是二分查找?二分查找(Binary Search),也叫折半查找,是一种在有序数组中查找特定元素的高效搜索算法。基本原理- 它每次比较中间元素与目标元素的大小关系,若中间元素等于目标元素,则查找成功;若中间元素大于目标元素,则在数组的左半部分继续查找;若中间元素小于目标元素,则在数组的右半部分继续查找。- 不断重复这个过程,直到找到目标元素或者确定目标元素不存在为止。适用条件- 数据结构必须是有序的,比如升序或降序排列的数组。时间复杂度。
2024-11-25 21:26:49
1134
原创 C++:多态
1、多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如Student继承了Person。Person对象买票全价,Student对象买票半价。2、必须通过基类的指针或者引用调用虚函数。3、被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写。
2024-11-22 18:01:49
1105
原创 算法沉淀二:滑动窗口
顾名思义,滑动窗口,就是一个可变大变小的区间,左边为left, 右边为right,left 和 right 构成的一个区间,一直往后面遍历,实现O(n) 复杂度的一个算法。
2024-11-18 19:46:04
1082
原创 算法沉淀一:双指针
此章节介绍一些算法,主要从leetcode上的题来讲解,讲解内容为做题思路,附加代码。欢迎与我大家一起学习共同进步!沉淀!passion!双指针的常见形式有两种:对撞指针,快慢指针。
2024-11-16 21:18:08
1415
原创 C++:继承
继承允许你根据基类的实现来定义派生类的实现。这种通过生成派生类的复用通常被称为白箱复用(white-box reuse)。术语 “白箱” 是相对可视性而言:在继承方式中,基类的内部细节对子类可见。继承一定程度破坏了基类的封装,基类的改变,对派生类有很大的影响。派生类和基类间的依赖关系很强,耦合度高。对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象来获得。对象组合要求被组合的对象具有良好定义的接口。
2024-11-14 18:33:43
1172
原创 C++:模板之全
在C语言中是不支持泛型编程的,C++就支持泛型编程。什么是泛型编程?首先回忆一下函数重载:在C语言中是不允许函数重载的,C++中是可以的,C++可以根据参数类型不同,来转汇编成不同的函数名,因此就构成了重载。但是函数重载是存在弊端的,比如同样的代码语句逻辑一模一样,只有函数参数的类型和函数体中的类型不一样。并且代码的复用率比较低,有新类型出现的时候就要重写一个函数,可维护性比较低,一个出错可能所有的重载都会出错。
2024-11-11 18:30:24
1163
原创 C++:vector容器的使用和实现
前面我们介绍了string容器的使用,容器是一通百通的,只要理解了string,那么理解接下来的容器是非常简单的。那么就开始vector的学习之旅吧!1、相信大家都知道数组的使用,vector其实就是表示可变大小数组的序列容器。2、vector和数组一样,采用的是连续存储空间来存储元素,也就是意味着可以采用下标对vector的元素进行访问,和数组一样高效。但是又不像数组,它的大小是可以动态改变的,而且它的大小会被容器自 动处理。3. 本质讲,vector使用动态分配数组来存储它的元素。
2024-11-01 17:48:53
1187
原创 C++: String容器的使用和实现
标准模板库是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
2024-10-30 14:46:56
1032
原创 C/C++内存和内存管理
*栈**:自动管理,访问速度快,适合短期使用的数据。**堆**:手动管理,访问速度较慢,适合长期使用的数据。简单的来说:1.
2024-10-29 15:41:22
1229
1
原创 七、二叉树之链式结构(递归)
我再解释一下:首先创建一个节点,根节点去寻找左孩子,左孩子又是左子树的根节点,继续去找,直到找到叶子节点,叶子节点的左右孩子存在,但是为空,开始返回,返回叶子节点的父亲节点,叶子节点的父亲节点又有右孩子,以此类推,直到返回到根节点(A)的右子树,那么就很好的诠释了树的结构是递归的。如果理解了上面所说的后序,使用后序来销毁是最方便的,因为后序最后才会返回根节点,前序和中序都是途中就会返回根节点,如果根节点已经被删掉了的话,就不方便进行下一步free,但可以定义一个变量来保存它的左右子树,则可以继续进行。
2024-10-17 22:54:48
1240
7
原创 六、二叉树顺序结构之堆
首先理清楚,如果这个小堆/大堆有10个数据,这个堆的堆顶已经是最小/最大的数据了,让这个数组的第一位与最后一位交换位置,这样堆顶就到了最后一位,再对前面9个进行向下调整算法,以此类推,一直重复,就可以得到一个排序数组了。如果排完一个小堆,找到了最小的,但是要找次小的,再找第三小的,.......,继续从它的左右子树分别进行向下调整算法构建堆的话,那么时间复杂度为O(N^2),这就不能体现出堆排序的价值所在。这里的堆和malloc的堆不是同一个意思,这里的堆只是一种数据结构,而后者是操作系统里的区域。
2024-10-16 21:51:55
1198
1
原创 四、栈和队列及其实现
一般可以用数组或者链表进行栈的实现,但数组相对而言更优,因为插入数据时,数组在尾上进行的操作代价更小。大家可以自己试试用队列实现栈,栈实现队列,虽然没有实际意义,但可以加强对栈和队列的理解。栈:一种特殊的线性表,只允许在一端进行插入和删除,进行插入数据和删除数据的是。队列:只允许在一端进行插入数据,另一端进行删除数据,是一个特殊的线性表。压栈:栈的插入叫压栈、进栈、入栈。几乎都是顺序表的操作。出栈:栈的数据删除。接下来展示队列实现栈,栈实现队列。的特质,进行插入的一端叫。重复此操作就可以了。
2024-10-15 18:23:07
459
原创 三、带头双向循环链表
带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了。此head可以叫guard,哨兵位,里面的数据没有什么意义,就是一个带头结点方便增删查改。双向链表,所以肯定有两个指针,一个指向前结点(prev),一个指向后结点(next)。}LTNode;和单链表相比,双向链表的功能比较强大。但是都是按需所取。
2024-10-15 15:37:20
488
1
原创 二、单链表/无头单向非循环链表
1.1.当使用realloc申请新的空间时,会涉及->开辟新的空间->拷贝数据->释放原来的空间,这三个步骤会有不小的消耗。1.2.扩容都是2倍增长,如果没有存储那么多数据就会导致一部分空间浪费,假如100个空间,扩容2倍到200个,但是一共插入的数据只有120个,就会导致有80个空间浪费。所以,单链表就解决了顺序表的这些问题。//结点存放数据//结点指向下一个结点}SLTNode;
2024-10-15 10:29:39
934
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人