自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 二叉搜索树

删除两个孩子的节点,如图中4号节点,要找到一个代替4号节点的值,要么找左边最大的,要么找右边最小的,找这两个节点的值都满足搜索二叉树的特性,那么找右子树最小的值来代替删除节点,根据搜索二叉树特性,一定是最左边的,然后用最左边的代替删除节点,最左边的一个节点,要么是有一个右孩子,要么没有孩子,则还是跟前面一样,节点的父亲指向节点的孩子,然后释放节点。对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。如删除图中1号节点。

2025-09-08 15:40:06 675

原创 【继承+多态)】

5. 总结一下派生类的虚表生成:a.先将基类中的虚表内容拷贝一份到派生类虚表中 b.如果派生类重写了基类中某个虚函数,用派生类自己的虚函数覆盖虚表中基类的虚函数 c.派生类自己新增加的虚函数按其在派生类中的声明次序增加到派生类虚表的最后。2. 基类b对象和派生类d对象虚表是不一样的,这里我们发现Func1完成了重写,所以d的虚表中存的是重写的Derive::Func1,所以虚函数的重写也叫作覆盖,覆盖就是指虚表中虚函数的覆盖。多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。

2025-09-03 10:24:24 592

原创 【 继承 】

下面我们看到Person是父类,也称作基类。Student是子类,也称作派生类。继承可以理解为,在子类中继承了一个父类,可以理解为在子类中多了一个自定义类型,那么,继承的这个父类中的成员在子类中是私有还是共有,跟继承方式有关。继承方式说明:1.只要父类中的成员是私有的,无论以何种方式继承(public、protected、private),在子类中都不可用。2.若父类中的成员是public,在子类中的继承方式是public,则父类成员在子类中是public;

2025-08-16 16:30:41 678

原创 【模版进阶】

即:在原模板类的基础上,针对特殊类型所进行特殊化的实现方式。上面定义的 N是常量,在fun中,进行N++,会报错,模版在检查的时候只会检测语法错误,因此之后,模版实例化的,可以理解为形成一个具体的类,在运行是会检测错误。上面一些成员都是一些很常见的接口,比如迭代器的访问,本质还是一个指针访问,它的本质还是一个静态数组,因此size,empty这些接口一定支持,访问的话,除了迭代器,还有运算符重载[],访问和修改任何一个位置的元素,front,back取数组头的元素和数据尾的元素。

2025-08-16 09:23:05 603

原创 【Stack&Queue】

1. stack是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。2. stack是作为容器适配器被实现的,容器适配器即是对特定类封装作为其底层的容器,并提供一组特定的成员函数来访问其元素,将特定类作为其底层的,元素特定容器的尾部(即栈顶)被压入和弹出。3. stack的底层容器可以是任何标准的容器类模板或者一些其他特定的容器类,这些容器类应该支持以下操作:empty:判空操作back:获取尾部元素操作。

2025-08-13 15:13:51 589

原创 【list&list模拟】

再说一下list& operator= (listlt),注意形参是拷贝构造的一份,和赋值_head,把头地址交换即可,lt在栈桢销毁时,就会销毁交换的那个_head.通过iterator it = it1.begin(),定义一个对象it,把it初始化为第一个节点的位置,然后进行以下运算符重载,!先写·迭代器的行为,在进行封装。带头双向循环链表,非常简单,写尾插即可,通过_head->_prev找到尾巴,尾巴,新节点,头插入即可。先写申请一个节点的类,把节点弄成一个类,相当与搞了一个新的数据类型。

2025-08-11 15:49:48 685

原创 vector剩余问题

erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是没有元素的,那么pos就失效了。2. 如果拷贝的是内置类型的元素,memcpy既高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝。1. memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中。

2025-08-07 09:45:49 426

原创 vector使用&模拟实现

具体上面接口如下,简单的接口不做解释,看看reserve还是那一套,先申请一个指定的空间,把内容拷贝到指定空间,在更新成员变量即可,需要注意的是,上面写法不行,浅拷贝可以,深拷贝不行,假设存储vector < string> v1,存的是string,再扩容时,发生浅拷贝,只是把string里面成员的值拷贝过来,真正字符串在堆上存的空间已经调用析构函数销毁了,这个是不行的,只有赋值调用string的拷贝构造才行。还有erase问题,一些编译器出于安全考虑,删除的位置,将不会被访问,这也是迭代器失效的一种。

2025-08-06 22:14:35 718

原创 【模拟string接口】

把一个字符往后面移动,第一种写法,end指向‘\0’,把end位置的字符向[end+1]位置移动,end- -,这样写可以,有一个问题,end指向第一个位置,end- -之后,变成-1,但是end是size_t类型,出现死循环,基于这样把end定义成int即可。为避免end为-1的情况,直接指向‘\0’的下一个,要为str留下空间,则[end+len]为放最后一个字符的下一个位置,放最后一个字符的位置为[end+len-1],然后end–,就可以了。这个写法,看似偷懒了,还是代码复用,是这样的。

2025-08-03 11:13:06 951

原创 【string类常见接口】

insert设计的很灵活,第一个参数size_t pos,从哪个位置插入,第二个参数插入什么,字符串,string,字符。只能读,*this被const修饰,内容不可变,接受的返回值必须是常量char&,也不可变。pash_back尾插一个字符,append尾插一个字符串,功能很多。+=是运算符重载,接口很多,能想到的都设计进去了,比如+=string,+=字符,+=字符串。构造字符串几个字符。

2025-08-01 23:44:03 733

原创 【C++内存管理、模版初阶】

num1这个变量中存的是1这个元素的地址,1,2,3,4这四个元素在栈内一块连续的内存中储存,下面字符数组同上,char* pChar3 = "abcd"这个字符常量,是把a的首地址存在pChar3这个变量中,而这个只读字符常量存在代码段,只可以读,不可以修改,下面三个变量ptr1,ptr2,ptr3,里面存的是动态内存申请的一块内存的首地址,malloc、calloc申请的空间是在堆区。函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

2025-07-26 14:32:16 1025

原创 【C++类】

上面构造函数,内置类型不初始化或不写初始化参数列表,编译器会生成随机数,进行初始化,像自定义类型,若自定义类型有初始化,并且是默认构造,则自动调用,如不默认构造,则要在初始化参数列表来进行初始化。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访,内部类是朋友,内部可以访问外部,外部不能访问内部。4. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。

2025-07-24 11:29:42 1013

原创 【运算符重载&& Date类】

看上面,没有赋值函数,还是进行赋值了,编译器会默认生成一个赋值函数,对简单的自定义类型可以复制,所谓的值拷贝(浅拷贝),但是不能进行深拷贝,要自己手动写赋值函数,如Stack.C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容!: . 注意以上5个运算符不能重载。

2025-07-21 15:28:19 835

原创 Linux指令

grep是 Linux/Unix 系统中强大的文本搜索工具,用于在文件或标准输入中匹配指定模式(正则表达式)。其名称来源于g/re/p。

2025-07-20 13:41:07 553

原创 【Linux初识】

Linux的命令有很多参数,我们不可能全记住,我们可以通过查看联机手册获取帮助。我购买的是腾讯云,因为毕业了就买了一个月的,上研究生用学生身份购买比较便宜。-a: 列出目录下的所有文件,包括以 .开头的隐含文件。将当前工作目录改变到指定的目录下。ls:罗列当前文件下指定的文件或目录。adduser +(用户名)创建用户。输入命令后,输入密码,则登陆成功。passwd +(用户名)设置密码。修改hello_120用户密码。pwd:显示用户当前所在的目录。-l :列出文件的详细息。touch 创建普通用户名。

2025-07-18 19:14:43 322

原创 【C++类】

/ 类体:由成员函数和成员变量组成 };class为定义类的关键字,ClassName为类的名字,{}中为类的主体,注意类定义结束时后面分号不能省略。类体中内容称为类的成员:类中的变量称为类的属性或成员变量;类中的函数称为类的方法或者成员函数。类的两种定义方式:1. 声明和定义全部放在类体中,需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。2. 类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::看下面代码,初始化不了。

2025-07-11 22:18:49 1131 1

原创 【C++基础语法】

1.实际项目通常是由多个头文件和多个源文件构成,而通过C语言阶段学习的编译链接,我们可以知道,【当前a.cpp中调用了b.cpp中定义的Add函数时】,编译后链前,a.o的目标文件中没有Add的函数地址,因为Add是在b.cpp中定义的,所以Add的地址在b.o中。以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。

2025-07-10 18:19:49 730

原创 C++基础语法

2. using namespace std展开,标准库就全部暴露出来了,如果我们定义跟库重名的类型/对象/函数,就存在冲突问题。在C/C++中,变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。定义命名空间,需要使用到namespace关键字,后面跟命名空间的名字,然后接一对{}即可,{}中即为命名空间的成员。这儿在说一下冲突,我们和库,我们之间的冲突,也就是说,在同一个域下不能用相同的名字,编译器默认的查找规则。

2025-07-06 16:23:48 874

原创 【双向循环带头链表】

这个节点的实现初始化,要注意,两个指针要自己指向自己,在写后面的接口中有大用.ListDestory接口实现定义一个指针cur = phead->next,先保存下一个节点的地址,在free.第一个节点为头结点,后面链接的节点存储数据。一个指向前面的指针prev,一个指向后面的指针next,一个数据。// 双向链表在pos的前面进行插入。ListPrint,遍历直接·打印。LIstPushBack直接尾插,// 双向链表删除pos位置的结点。双向循环带头链表结构如下。

2025-07-06 14:47:14 363

原创 【排序算法】

取key永远为子序列最左边的一个数,定义left指向子序列最左边,right指向子序列最右边,先走最右边,找比key小的值,在走左边,找比keyi大的值,找到之后,两者交换,交换之后,比key小的在左边,比key大的在右边。由此看来,end是有序数组最后一个数的下标,tmp保存的是下一个要放的数,一个无序数组,则end先指向第一个数,tmp保存第二个数,根据上述获得这两个数的正确排序,则end = n-2,tmp = a[end-1]时,进行最后一次排序,整个数组就排好序了。

2025-07-04 18:01:06 876

原创 【二叉树常见题解】

此题注意:给一个二叉树,进行前序遍历,把遍历之后的数据存入malloc的数组中,并且有一个参数给了地址,要求给这个参数赋值这个二叉树有多大。因此,先要计算二叉树的大小,然后malloc一个数组,把前序遍历的值按顺序存入数组中。通过前序遍历,构建这棵树,先根据已给的数组申请节点,然后该节点左边插入左子树,右边插入右子树。解题思路:根与左子树比较是否相等,根与右子树比较是否相等,若根、左子树、右子树都相等,则这棵树全部相等。两棵树同时递归,一棵树从左子树递归,另一颗树从右子树递归,判断两棵树是否相等。

2025-06-29 17:25:40 338

原创 【(Topk问题及其二叉树遍历】

本文主要探讨了两个关键问题:TopK问题和二叉树遍历。首先介绍了TOP-K问题的解决方案,通过建立小堆或大堆来高效筛选前K个最大或最小元素,时间复杂度为O(N)。其次详细讲解了二叉树的三种递归遍历方式(前序、中序、后序),并提供了相应的代码实现。此外,文章还介绍了如何递归计算二叉树节点总数和最大深度的方法。这些算法都体现了递归思想在数据结构处理中的高效应用,通过分解子问题和设置终止条件来解决复杂问题。

2025-06-27 19:12:26 863

原创 【(堆的时间复杂度解析及其堆的一些其他应用】

向下调整叶子节点不管,直接从最后一个父亲依次向下调整,由于倒数第二层的父亲节点是非常多的(2^(h-2)),先向下调整第二层,大大提高了时间复杂度。通过堆的筛选性质来排序,小堆只能找到最小的数,大堆只能找到最大的数,假设排成降序,则要小堆,先筛选出最小的数,放到最后面,在筛选次小数,…当堆建成以后,向上调整算法和向下调整算法插入数据或删除数据重新调成堆,最多调整高度次,则时间复杂度是:O(代码如下,思路简单,第一个数据不参与比较,插入第二个数据依次根据向上调整,进行建堆。

2025-06-26 14:05:02 660

原创 【树的概念及其堆的实现】

现实中我们通常把堆(一种二叉树)使用顺序结构的数组来存储,需要注意的是这里的堆和操作系统虚拟进程地址空间中的堆是两回事,一个是数据结构,一个是操作系统中管理内存的一块区域分段。首先,把10和28交换,交换之后,把堆顶元素10删除,把在0位置的28这个元素,向下调整成堆,具体就是找孩子中两个较小的一个跟父亲比较,进行交换,父亲走到头,循环结束,这是孩子已经越界,用孩子来写循环条件。*孩子节点或子节点:一个节点含有的子树的根节点称为该节点的子节点;* 子孙:以某节点为根的子树中任一节点都称为该节点的子孙。

2025-06-25 14:51:25 877 1

原创 [两个栈实现队列]

/思路:两个栈实现队列,栈是先入后出,队列是队尾入,对头出,(先入先出),那么可以这样干,假设一个栈Pushst,先入1,2,3,4,那么成队列,先要出1,1在一个栈中是不可能出的,那么可以把Pushst的数据出栈放到另一个Popst中,顺序就转过来了,在Popst中出栈,就顺序合适了!队列Pop:在另一个栈中Popst,如果Popst中没有数据,那么把Pushst中的数据全部放到Popst中即可,在Popst中出数据就可以了!综上所述:队列Push:在一个栈中Pushst中如数据就可以了!

2024-03-06 00:00:45 348

原创 预处理大致解析(参见《C语言深度解剖》更好得到学习)

1.C语言设置了一些预定义符号,可以直接使用,这些符号在预处理阶段会被处理!__ FILE __ //进行编译的源文件__ LINE __ //文件当前的行号__ DATE __ //文件被编译的日期__ TIME __ //文件编译的时间__ STDC __ //如果编译器遵循ANSI C,其值为1,否则未定义!//测试 - - -return 0;

2024-03-03 12:16:00 1094

原创 数据结构:队列 || oj(l两个队列实现栈)

[TOC](数据结构:队列 || oj(l两个队列实现栈))

2024-02-29 23:56:57 940

原创 编译与链接

并且包含的头⽂件都被插⼊到.i⽂件中。//翻译环境是由编译和链接两大过程组成,编译阶段也是非常复杂的,它分为(预编译、编译、汇编)三个过程,这三个过程是复杂的,也是非常重要的!编译过程就是将预处理后的test.i文件进行一系列的:词法分析,语法分析,语义分析及优化,生成相应的汇编代码文件!//各个.h,.c文件通过预处理生成.i文件,再把.i文件通过编译编译生成的.s文件,在通过汇编生成.o文件!//• 注:在Windows环境下的⽬标⽂件的后缀是 .obj ,Linux环境下⽬标⽂件的后缀是 .o。

2024-02-28 14:19:28 920

原创 链表和顺序表的优劣分析及其时间、空间复杂度分析

空间复杂度也是一个数学表达式,是对一个算法在运行过程中临时占用存储空间大小的量度。空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是。

2024-02-23 21:46:56 2757

原创 栈的实现及其括号匹配问题

/2.拿到右括号‘)’,‘]’,‘}’,拿到右括号,把入栈的左括号出栈,看是否匹配,如果匹配,则继续执行上面操作,如果不匹配,则返回false。//4.左括号比右括号多的问题,遇到左括号入栈,遇到右括号出栈,则一定左括号的元素没有出完,检测栈是否为空,不为空,返回false。//5.右括号比左括号多的问题,在拿到右括号出栈之前检测栈是否为空,如果为空,则右括号多,返回false!//3.考虑如果左括号和右括号的数量一样多,则入栈,出栈,最后的栈内元素个数为0,栈为空!//获取栈的元素个数。

2024-02-21 12:31:02 867

原创 单向不带头链表

我的理解是链表是一种逻辑上是线性结构,在真正的内存空间中是非线性,一般而言,不连续的结构,它是通过在堆区一块一块申请空间,用指针把各块空间连起来的结构,也就保存各块空间的地址来连接!//要考虑头删怎么写,要删除头,把下一个节点存起来,当做newHead,即使下一个节点是NULL,也可以存起来,所以只有一种情况!//2.保存pos后面的后面节点(NULL没有影响),删除pos之后的节点,在链接保存的节点。//或先把节点插在pos之后节点的前面,在把pos里面存新节点。//删除pos后面的一个节点。

2024-02-20 15:48:03 695

原创 简单贪吃蛇模拟(C语言版本·)

GetAsyncKeyState 的返回值是short类型,在上⼀次调⽤ GetAsyncKeyState 函数后,如果返回的16位的short数据中,最⾼位是1,说明按键的状态是按下,如果最⾼是0,说明按键的状态是抬起;首先,对于现在的我来说,写这样一个贪吃蛇还是很难的,写这个东西,让我感觉最深刻的是枚举类型的运用,这是一个好东西,还有结构体的运用,能够学到大概一个简答的东西,怎么组织,怎么来写,这是很重要的一点,看整个代码,不是很难,但是如果你自己要组织出来,要写出来还是很难得,特别是枚举的应用!

2024-02-19 20:22:36 2105

原创 联合体与枚举

联合体也是由一个或多个成员构成的数据类型,它最大的特点是只为最大的一个成员开辟空间,其他成员共用这个空间,这个东西也叫共用体!联合的成员是共⽤同⼀块内存空间的,这样⼀个联合变量的⼤⼩,⾄少是最⼤成员的⼤⼩(因为联合⾄少得有能⼒保存最⼤的那个成员)。第二个联合体的最大一个占14个字节,不是4个倍数,因此浪费2个字节,成16个字节,成为4的倍数!解析:第一个联合体最大的一个占5个字节,它不是4的倍数,因此成8个字节,浪费三个字节!*当最大成员大小不是最大对齐数整数倍的时候时,要对齐到最大对齐数的整数倍!

2024-02-14 12:39:07 402

原创 结构体,位段问题

第一个char为1个字节,struct S3 s3为16个字节,里面的最大对齐数为8个字节,所以总共是8+16 = 24个字节,最后一个double 是8个字节,正好对齐,来放double ,总共24+8 = 32个字节!解析:(1)第一个char直接放,第二个int对齐数为4,所以前面为4个字节,后面放了4个字节,共8个字节,还有一个char没放,放完之后9个字节,结构体的总大小为最大对齐数的整数倍,最大对齐数为4,所以是12个字节。内存中每个字节分配⼀个地址,⼀个字节内部的bit位是没有地址的。

2024-02-13 22:09:26 811

原创 数据在内存中的存储

bit 位,但是在C语⾔中除了8 bit 的 char 之外,还有16 bit 的 short 型,32 bit 的 long 型(要看具体的编译器),另外,对于位数⼤于8位的处理器,例如16位或者32位的处理器,由于寄存器宽度⼤于⼀个字节,那么必然存在着⼀个如何将多个字节安排的问题。对于64位的浮点数,最⾼的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M.对于64位的浮点数,最⾼的1位存储符号位S,接着的11位存储指数E,剩下的52位存储有效数字M.*2^129表示无穷大!

2024-01-28 12:37:57 1551

原创 环形链表的约瑟夫问题

这个题的思路呢,就是建立一个环形链表,从1计数,计数到m就删除节点,然后返回最后的节点存的值,有个问题是,循环的结束条件是什么?这是一个难点,下面画图解决!cur->next == cur时,循环结束。

2024-01-25 20:48:40 292

原创 [反转链表] [合并两个有序链表][分割链表]

思路2:把指针翻转,把指针反转的意思是,把存节点的地址交换,定义三个指针n1,n2,n3,n1 = NULL,n2 = head,n3 = head->next,n2为第一个节点翻转,n2->next = n1,n2里面原来存的地址找不到,因此要n3存下一个节点的地址,这样这个题就可以反转了!这个题建立一个新链表,取小的数尾插即可,这儿有一些技巧,可以建立一个头结点,直接尾插,这样就省去了考虑newHead为NULL的情况,这个方法,在一些题中有妙用!下面是一个正常的做法!

2024-01-23 23:00:45 423

原创 移除链表元素和链表的中间结点

思路1:很简单,最常规的方法,建立一个新的链表,头为newHead,遍历链表,不是val值的拿下来尾插,注意一些细节,比如,你拿一个节点的时候,你拿的这个节点里面存的是下一个节点的地址,可能在最后一个节点,后面还跟了其它节点,只要把最后一个节点里面的next置NULL就行,在就是特殊情况特殊处理,就能做好这个题。思路2:遍历一遍链表把val在原链表中删除,这个思路说起来简单,做起来难!

2024-01-21 22:41:42 413

原创 移除元素和合并两个有序数组

合并两个有序数组,从小到大排列,nums1 = [1,2,3,0,0,0]和nums2[2,5,6],定义三个指针了l1,l2,l2,l1指向nums1,l2指向nums2,l3指向要放的地方,如果从前向后比较,则比较的元素的覆盖了,因此必须从后向前比较,比较大的元素向后放,如果nums2先放完,则已经完成,如果nums1先放完,则把nums2没有放的元素放进nums1中,思路就是这样!

2024-01-20 15:13:31 409

原创 【动态内存开辟】

首先这儿介绍一本很好很好的书《c指针编程之道》根据这本书中的内容来学习这几个函数!!!1.下面介绍第一个函数malloc,原型:void* malloc(unsigned int num_bytes),此函数在堆区可以占用一块空间,返回的是占用空间的第一个地址,可能开辟失败,一定判断是否开辟成功!开辟失败,返回NULL,对开辟成功的内存不做处理,也就是以前的随机值!• 如果开辟成功,则返回⼀个指向开辟好空间的指针。• 如果开辟失败,则返回⼀个 NULL 指针,因此malloc的返回值⼀定要做检查。

2024-01-18 16:34:53 435

空空如也

空空如也

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

TA关注的人

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