- 博客(95)
- 收藏
- 关注
原创 array和vector
array是栈上的,把C数组给“标准化”,有大小信息,不会弱化为指针,不可以动态扩大。vector管理堆内存,可以动态扩容。
2024-04-14 02:11:28
242
原创 vector的clear能清除其内存吗
然而,clear函数并不会立即释放向量所占用的内存。向量仍然会保留其已分配的内存,以备后续添加元素时使用。在C++中,std::vector的clear函数会移除向量中的所有元素,使得它的大小变为0。size和capacity是两个值,capacity才是实际内存的容量,size代表其大小。如果你想要立即释放内存,可以考虑使用交换技巧(swap trick)。
2023-09-12 10:56:15
1444
原创 访问者模式
可以看到在保证accepter的数据结构不发生变化的情况下(没有新增或者删除),可以非常方便增加新的一种访问方法,只需要新增加一个访问类即可,但是如果我们数据结构发生变化之后,就需要修改继承自Visitor类的所有类了,这也违背了开闭原则,因此我们应该认真考虑,到底我们的数据结构是定死的还是经常变化的。没有任何一种设计模式是十全十美的,总是有所取舍,有所利弊,根据实际情况来选择才是最好的设计方法。
2023-09-09 08:58:08
296
原创 迪杰斯特拉C++
每次遍历到始点距离最近且未访问过的顶点的邻接节点,直到扩展到终点为止。算法理解不难,要初始化的条件很多,最后输出的结果页不明显。从起始点开始,采用贪心算法的策略,迪杰斯特拉单源点最短路径算法。
2023-09-03 16:44:40
235
原创 Git基本操作
总之,merge和rebase都可以实现代码的合并,但是它们的工作方式和使用场景有所不同。git add . 将当前目录所有文件放到暂存区如果git commit 没有加文字,就会进入vim模式在顶行输入提交信息,也就是每次commit必须有提交信息。vim的用法和Linux中一致,i–插入模式,ESC–回到普通模式,:–底行模式,wq保存。(只提交暂存区中的内容,也就是被git add的才会被commit)在Git中,merge和rebase是两种不同的合并代码的方式。
2023-09-03 14:12:08
535
原创 1090. 受标签影响的最大值
有两个比较首先是让labels标签升序,选不超uselimit重复的所有标签,并且当标签相同时,让value更大的靠前,也就是第二比较册略是升序value。去重后,还要对unique_vec进行value排序,因为之前的排序是为了去重,同时尽可能保留每一组标签的值最大。此时unique_vec的性质是,每个标签不会多于uselimit,并且保留的标签都是那一组标签的值最大的。还没有完,这样得到的集合,还要进行去重,重复限制是uselimit。两个数组,要形成映射,也就是要组合起来才能排序,求子集和最大。
2023-05-23 11:04:05
125
1
原创 算法训练-二分查找
题目链接while(left <= right) //区间不为空,则可以继续去找 {这样写不会越界,如果left和right都很大,相加就可能越界 if(nums [ mid ] == target) {int i;i --) /*找到target不能立即存放到ret中,因为题目要求找到第一个和最后一个target位置,先从mid往前找,相同 就给ret[0]赋当前下标,对mid右变处理相同。
2023-05-21 14:25:52
459
原创 mysql
当我们看书时,寻找书中的某个内容,如果一页一页去找,那么效率非常低,,通常都是在前面几页的目录中去查找关键字,之后既可以快速定位页码,从而大大提高查询效率。BST的问题在于,很容易出现树的高度非常高,每层存储的结点个数却并不多,这就导致存储海量数据时,如果要查询,需要递归很深才能找到,查询效率不高,最差情况会退化到O(n)但是,在一个事务内可能会出现不可重复读或者幻读的情况。那么为什么不用上面这些数据结构呢,因为数据库的存储是海量,数据量非常大,即使用了这些结构,树高依然很大,如果降低树高,就有了。
2023-05-17 14:16:26
262
原创 算法训练-双指针
我的想法:排序,先找0,然后从0位置向前向后遍历,找相加=0,之后找一个正数的情况,和一个负数的情况,注意当区间之和大于0或小于0时,剩下的元素就不用判断了,没写完。这三道题都是双指针解决,基本都是一个模子,外循环遍历结点,内循环while判断区间条件,最后出while对区间长度计算,返回结果。这一题虽说是滑动窗口,但其实和双指针差不多,可以看到的是在核心的代码也是for遍历内部加while判断。能看懂思路,但是写不出来,特判好多,以及何时就应该移动指针。没有想到转换成两数求和。我的想法:(这是有问题的)
2023-05-16 12:03:01
488
原创 stack和queue
平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 )。该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * )。逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。queue:先进先出,队尾插入push,队头删除pop。stack:后进先出,只能在栈顶操作。提到栈,就不得不提及逆波兰表达式。
2023-05-07 13:59:07
61
原创 list容器
没有像vector总的capacity那些方法,因为链表的增效率是O(1),vector设置capacity是为了减少申请内存,扩容,提高效率,这一点list链表的数据结构是不必考虑的。但是pos要插入的位置,总头需要遍历才能获得,所以O(n),但是这样理解也不太合适,因为考虑算法的时间复杂度是针对算法本身,而不应去看参数的获取效率。list的erase删除操作会造成迭代器失效,不过这是这个位置的迭代器失效,不同于vector,因为它是链表,地址不是连续的。//不用给出迭代器位置,这是尾插头插,对应的。
2023-05-06 22:37:32
387
原创 vector
将容器当中的数据一个个拷贝过来时不能使用memcpy函数,当vector存储的数据是内置类型或无需进行深拷贝的自定义类型时,使用memcpy函数是没什么问题的,但当vector存储的数据是需要进行深拷贝的自定义类型时,使用memcpy函数的弊端就体现出来了。例如,当vector存储的数据是string类的时候。我理解的是,因为string类确定要存储的就是char,而vector容器类是根据模版参数来实例化容器类的,无法确定其类型,所以要使用对应的迭代器,迭代器是带有类型的指针,也只能这样处理。
2023-05-05 17:32:25
674
原创 string类
string可以说是使用起来很方便的一个类,也非常常用,较之于C字符串,可以说是string是很强大的,方法有很多,所以日常中药多加练习,才真正能够随心所用,并且string是stl容器其中一只,stl容器中很多类的方法都是比较相似的如:push_back,earse,find,[],begin,end,insert,当然针对不同的容器,还是有一些特有的方法。
2023-05-04 13:30:00
563
原创 扑克牌中的顺子
首先想到的思路是排序,然后找差值dis和zero个数比较,差值是要不连续的那种差就是 例如两数:a,b 这里的差值是 dis=a-b-1 还要再减一,如果zero==dis那说明变一变可以变成顺子,直接写出。但是其实不用判断可扩展,因为可以两头扩展,这个序列是5个,小于13,所以只要修改之前true的判断,对于zero大于dis也是true,而不仅仅只是zero==dis才返回true。解决:这种情况说明此时zero > dis 大小王有富裕,判断序列是否可扩展。
2023-04-07 22:48:50
197
原创 希尔排序(复习)
因此必须执行O(N^2)的交换次数,这就是为啥冒泡、插入等算法只能到平方级别的原因,容易看出排序的本质就是消除逆序数,可以证明对于随机数组,逆序数是O(N^2)的,假设我们要从小到大排序,一个数组中取两个元素如果前面比后面大,则为一个逆序,而如果采用“交换相邻元素”的办法来消除逆序,每次正好只消除一个,反过来,基于交换元素的排序要想突破这个下界,必须执行一些比较,交换相隔比较远的元素,使得一次交换能消除一个以上的逆序,希尔能突破O(N^2)的界,可以用逆序数来理解,
2023-03-28 20:59:26
83
原创 单例模式~
单例:对于一些类来说,只有一个实例很重要。保证类只有一个实例,并提供一个访问它的全局访问点。声明一个getInstance()静态方法来返回其所属类的一个相同实例。拷贝构造函数,赋值运算符重载,做delete处理。对构造函数做私有化处理,
2023-03-28 11:17:15
62
原创 sar和strace命令
cat -n test.log | tail 查看最后十行系统调用信息,可以看到在系统底层实际调用的是write系统函数。strace:跟踪系统调用和信号。kill -pid 杀掉即可。一行数据对应一个CPU核心。
2023-03-26 22:43:48
61
原创 网络编程2(套接字编程)
套接字编程:如何编写一个网络通信程序1.网络通信的数据中都会包含一个完整的五元组:sip,sport,dip,dport,protocol(源IP,源端口,对端IP,对端端口,协议)五元组完整的描述了数据从哪来,到哪去,用什么数据格式2.网络通信–两个主机进程之间的通信:客户端&服务端客户端:用户使用,发起请求服务端:网络应用提供商提供服务的程序(后台开发)
2023-03-26 14:37:02
989
原创 1574. 删除最短的子数组使剩余数组有序
从前往后遍历,找到删除中间的序列,这里的序列都是子数组(必须是连续的),要注意一个问题就是会出现left指针大于right指针的情况,此时应该让right向后移动。让或操作,并让left == 0在前面这样就不会出现数组越界问题,因为left=0时,不会去判断后面的语句。left停下的位置,之前都是有序的,只要保证此时arr[left] <= arr[right]即可。这个for里的判断条件:left==0 || arr[left-1] <= arr[left]注意不需要删除的情况和边界判断。
2023-03-25 12:33:02
58
原创 socket通信
TCP(传输控制协议)是一种可靠的面向连接的协议,它提供了一种可靠地数据传输方式,保证了数据的准确性和完整性。绑定socket:使用bind()函数将socket与本地IP地址和端口号绑定。创建socket:使用socket()函数创建一个socket。创建socket:使用socket()函数创建一个socket。监听socket:使用listen()函数将socket设置为监听状态,等待客户端的连接请求。接受连接:使用accept()函数接受客户端的连接请求,建立连接。
2023-03-22 18:16:08
295
原创 网络编程1(网络背景知识)
中间相邻设备进行转发是就使用mac地址进行表示,因为交换机就是通过mac地址进行确定转发(每个交换机上都有一个mac地址表,标识了当前交换机的设备连接的是自己的哪个插口(端口))协议–约定,网络协议就是网络通信中的数据格约定,不同的主机必须遵循先攻的网络通信协议栈(一组协议)才可以实现实质通信,不是某一个协议就可以,需要一组多个协议,协议分层处理。物理层–负责物理光电信号的传输;协议分层:按照网络通信环境,不同层次所提供的服务,使用的协议,使用的设备,提供的接口对整个网络通信环境进行了分层。
2023-03-19 12:42:16
336
原创 二叉排序树
//BST:Binary Search Tree//根节点左子树 < 根 < 根节点右子树//对BST进行中序遍历得到升序序列#include<iostream>using namespace std;#include<vector>template < class T>class BSTNode{public: BSTNode(const T& data = T()) :_left(nullptr) , _right(n
2023-03-15 09:27:41
43
原创 多线程~~
编译时要链接上pthread库, gcc thread.c -o thread -l pthread带信息头的查看线程信息更详细的线程信息等待:等待指定线程退出,获取退出返回值,回收未被完全释放的资源在线程中,有个分离属性,默认值是joinable状态,表示线程退出后不会自动释放所有资源,需要被其他线程等待等待线程指定的线程终止分离:将线程的分离属性社会为detach,表示线程退出后自动释放所有资源,则这种线程退出后不需要被等待(不关心其返回值时采用)分离一个线程。
2023-03-12 22:05:41
466
原创 模版初阶~
总结:函数模版特化要有原始泛型版本,模板类要在中显式给出类型,必须给出,对于成员函数实现参数尽量都带上const,能用引用就用引用,一些成员函数和运算符重载要给出const对象版本和非const两个都要实现。告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码。类模版必须显式实例化。
2023-03-05 16:03:59
44
原创 进程控制~
写时拷贝技术:子进程创建出来后,有自己的虚拟地址,有自己的页表,但是并没有给子进程重新开辟数据的空间进行拷贝,而是等到“写时”–这块空间中的数据即将要发生变化时,给子进程重新开辟,避免了申请空间但子进程不用,而造成的效率降低。实现:通过exec函数族(execl,execlp,execle,execv,execvp,execve),将新程序加载到内存中,修改当前pcb的页表映射信息,初始化虚拟地址空间,这时候pcb将调度新的程序运行。父子进程,数据独有,代码共享,各有各的地址。
2023-03-05 10:27:48
465
原创 进程概念~
通过虚拟地址中的页号直到对应的页表项,得到了一个物理内存块的起始地址,加上页内偏移就是实际的访问位置,不同的地方在于应用方向不同,分段式利于地址管理,分页式更倾向于碎片化管理,提高内存利用率和内存访问控制。pcb描述的信息:标识符(进程ID),内存指针(程序数据在内存中的地址),程序计数器,上下文数据(切换cpu寄存器中的数据会保存下来,这是其一),进程状态,io信息,…fork创建子进程,父子进程的运行顺序是不一定的,在操作系统中,进程按照异步方式运行,按各自独立的、不可预知的速度向前推进。
2023-03-05 10:25:11
406
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人