自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 C++的单例模式

为了只实例化出一个对象,会将默认构造函数私有,将拷贝构造函删除,由于实例出是的同一个对象,当这个对象被多个线程使用(线程安全问题)或多个模板类使用(重复调用析构函数),需要将析构函数私有,并需要锁进行安全保护,我们需要在public下写能够调用默认构造函数(只调用一次)和析构函数的两个自定义函数。2.更重要的原因:单例模式的对象是自引用,就是我包含我自己,我自己就是我的成员,发生delete时,如果成员有自定义类型,要调用成员的析构函数,而单例对象的成员就是自己,导致无线死循环。分为懒汉模式和饿汉模式。

2025-06-24 15:02:43 499

原创 C++智能指针

可见,并没有成功释放空间,sp1等待着sp2的_prev释放,sp1走了,同时带走了sp1的_next,也就是sp2的一个_pcount,但sp2的_pcount没有减减,导致sp2走了,也没有释放空间。有了计数就要考虑线程安全问题,因为什么时候析构依赖于*_pcount,当线程冲突导致*_pcount少于实际存在的智能指针的数量时,导致重复释放空间。共享指针,一块资源可以有多个智能指针管理,但为了只允许释放一次(最后一个智能指针释放),添加了计数器,当减减之后为计数为0就释放。

2025-06-24 09:55:04 466

原创 C++异常

3. 抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象,所以会生成一个拷贝对象,这个拷贝的临时对象会在被catch以后销毁。C++异常概念 异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接的调用者处理这个错误。catch: 在想要处理问题的地方,通过异常处理程序捕获异常.catch 关键字用于捕获异常,可以有多个catch进行捕获。1.异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个catch的处理代码。

2025-06-23 20:07:42 327

原创 C++11的内容

步骤 1:优先匹配std::initializer_list 构造函数 如果类型 F定义了 接受 std::initializer_list的构造函数 (如 F(std::initializer_list<U>)),编译器会优先尝试调用它。此时,花括号内的所有参数会被打包成一个 std::initializer_list<T>临时对象,其中 T 是花括号内元素的统一类型(需支持隐式转换)。

2025-06-23 19:28:47 1276

原创 C++位图

比如,存在或不存在,通过0或1也可以用多个位图记录多种状态,如 01,10,00,11(在两个位图下,可以记录4种状态,当然也可以横向记录,比如将某个位图的4个位记录状态,这样可以最多记录16种状态)通过不同的方式将(拿string举例)string映射到多个位置(多个位置的位设为1),布隆过滤器不支持删改,当某个位被多个值映射了,删除会影响其他值的检查。将位改为计数器,vector<unsigned char> vc,当映射到了vc[index],v[index]++ (v[index<255)。

2025-06-19 22:39:09 307

原创 C++哈希

在之前使用计数排序的时候,是通过对应的下标对该数组下标对应的空间进行标记,但是如果数分布不均匀就会造成浪费空间(比如1,2,3,999)。于是,哈希就来解决这问题。

2025-06-19 17:05:31 437

原创 用红黑树实现map和set

通过一个_kv就完成了赋值,对于map类型,KV就是pair<K,V>,key就是_kv的first,value就是_kv的second。迭代器是由一个红黑树节点和一些成员函数构成,迭代器的目的就是遍历,获取数据,而获取的数据都是KV类型的,因为_node的成员变量就是kv。map是一种KV模型,在传参时,需要用pair将两个参数耦合,创建了一个类型,而set只需要传一个key值,所有需要统一接口。用结构体创建一个新的类型,再将该类型作为模板传到RBTree类中实例化,调用函数获取键值。

2025-06-16 20:50:08 10

原创 C++红黑树

先定义插入节点(cur)的父节点定义为p(parent),p的父节点定义为g (grandpa) ,g的另外一个孩子定义为u(uncle)。在调节的过程中,cur可能在p的左边,也可能在p的右边,p可能在g的左边,p也可能在g的右边,这些情况交替出现,需要我们用if调节去判断。4. 对于每个结点,从该结点到其所有后代叶结点的简单路径上,均 包含相同数目的黑色结点。当我们向上调节,会出现这种情况(这里只讲p在g的左边的情况)在这里,只讨论p在g的左边情况,p在g的右边同样的思路。cur也可以在p的右边。

2025-06-15 20:35:43 184

原创 AVL树的实现

AVL树是一种自平衡二叉搜索树,通过平衡因子(右子树高度减左子树高度)保证每个节点的左右子树高度差不超过1。本文详细介绍了AVL树的插入操作及四种旋转调节方法(左单旋、右单旋、左右双旋、右左双旋),并提供了代码实现和测试验证。关键点在于:插入节点后需要向上调整祖先节点的平衡因子;当平衡因子变为±2时进行相应旋转;旋转后需要调整相关节点的平衡因子。测试结果表明该方法能正确构建平衡树。

2025-06-14 21:21:53 592

原创 二叉搜索树

二叉搜索树又称二叉排序树,它或者是一棵空树或者是具有以下性质的二叉树:1.若它的左子树不为空,则左子树上所有节点的值都小于根节点的值。2.若它的右子树不为空,则右子树上所有节点的值都大于根节点的值。3.它的左右子树也分别为二叉搜索树。

2025-06-12 18:58:10 417

原创 virtual继承与虚函数

摘要: 本文系统解析了C++虚函数机制中的关键数据结构。虚函数表(vtable)是存储虚函数指针的数组,实现多态时派生类会覆盖基类对应函数地址。虚基类偏移表(vbtable)用于解决虚拟继承问题,记录了this指针和成员偏移量。文章详细分析了不同继承场景下的内存布局:单继承中派生类虚函数可扩展基类虚表;多继承按声明顺序合并多个虚表;钻石型虚拟继承会创建独立的派生类虚表并保留基类虚表。通过内存模型图解,揭示了虚函数覆盖、虚基类指针等核心机制的工作原理。

2025-06-10 16:34:04 724

原创 C++中的多态

摘要:本文探讨了C++中的多态实现机制,重点分析了虚函数重写条件和特性。多态需要满足两个条件:通过基类指针/引用调用虚函数,且派生类必须重写该虚函数。文章详细介绍了虚函数重写的规范写法,指出协变和析构函数重写两种特殊情况。同时讲解了C++11的final和override关键字用法,以及抽象类和纯虚函数的概念。通过多个代码示例展示了多态的具体应用场景,包括指针/引用调用时的多态表现,以及传值调用时失去多态性的情况。

2025-06-10 10:30:56 422

原创 C++中的继承基础

继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。(被继承的类称为基类)继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用。通过直接在类后面继承,可以在stu和tea实例化的对象中看到person的成员(已经成为stu和tea的成员了)

2025-06-10 09:44:34 1029

原创 C++中的模板

2. 模板实例化阶段:当代码中实际使用模板(如 std::vector<int>)时,编译器才会根据模板生成具体的类或函数代码(即实例化)。声明文件(.h):仅包含模板的声明,编译器在编译其他源文件(.cpp)时无法看到定义,导致实例化失败。4. 函数形参表: 必须要和模板函数的基础参数类型完全相同(可以大于一个,但要与形参类型的个数匹配)定义文件(.cpp):虽然定义了模板,但其他源文件无法访问它(除非显式实例化),导致链接错误。作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用。

2025-06-09 15:47:26 328

原创 实现最小栈和优先队列

本文介绍了三种常见数据结构的模板实现:栈、最小栈和优先队列。基础栈通过模板类实现,利用容器适配器(list或vector)的push_back和pop_back操作。最小栈在此基础上增加一个辅助栈来实时跟踪最小值。优先队列采用堆结构实现,包含向上调整和向下调整算法来维护最大堆性质。每种结构都提供了完整的接口实现和测试用例,展示了它们的基本功能和操作流程。这些实现充分体现了C++模板和容器适配器的灵活性,为不同应用场景提供了高效的数据结构解决方案。

2025-06-05 21:43:01 332

原创 数据结构堆

本文介绍了堆排序的基本原理和实现方法。主要内容包括:1)通过数组下标表示完全二叉树,父节点与子节点的下标关系;2)大小堆的定义及特点,小堆根节点最小,大堆根节点最大;3)建堆过程,从最后一个非叶子节点开始调整;4)堆排序算法,升序用大堆,降序用小堆,每次交换堆顶元素后调整剩余堆;5)提供完整的大堆和小堆调整函数实现代码,以及升序和降序排列的具体算法;6)测试结果展示了算法的正确性。时间复杂度分析表明,建堆过程为O(logN),整体排序效率较高。

2025-06-04 20:15:59 434

原创 数据结构树

节点的度:节点拥有的子树的数目。叶子:度为零的节点。分支节点:度不为零的节点。树的度:树中节点的最大的度。层次:根节点的层次为1,其余节点的层次等于该节点的双亲节点加1。树的高度:树中节点的最大层次。无序数:如果树中节点的各子树之间的次序是不重要的,可以交换位置。有序数:如果树中结点的各子树的次序是重要的,不可以交换位置。森林:0个或多个不相交的树组成。对森林加上一个跟,森林即成为树;删去跟,树即成为森林。

2025-06-03 21:02:32 295

原创 归并排序(递归和非递归)

摘要:本文介绍了归并排序的单趟排序原理及其实现方法。单趟排序通过开辟新空间合并两个有序数组,再将结果拷贝回原数组。文章详细讲解了递归实现(MergeSort)和非递归实现(MergeSort2)两种方式,其中非递归实现通过控制gap间隔逐步扩大有序区间,效率更高但需要考虑边界处理。两种实现都使用辅助数组进行合并操作,最终完成整个数组的排序。代码展示了完整的排序过程,包括区间划分、合并和边界条件处理。

2025-06-03 11:14:55 762

原创 插入排序和希尔排序

插入排序就是将第k个数插入区间[0,k-1](该区间已经是有序的)中,使之成为一个新的有序区间 [0,k]。如图将第一个数作为最开始的区间(必然是有序的),从第2个数开始依次作为k插入前面的区间中时间复杂度:o(n^2) 空间复杂度o(1)

2025-06-02 19:00:54 202

原创 快速排序递归和非递归

快速排序的核心思想是通过选取基准值(key)将数组划分为左右两个子区间,左区间小于基准值,右区间大于基准值,再递归处理子区间。文章介绍了三种单趟排序实现方法:左右指针法、前后指针法和挖坑法,以及递归和非递归的实现方式。关键点在于通过三数取中优化基准值选择,避免最坏情况下的O(n^2)时间复杂度。快速排序平均时间复杂度为O(nlogn),空间复杂度O(logn),但最坏情况下会退化为O(n^2)。该算法不稳定,且递归过深可能导致栈溢出。非递归实现通过栈结构存储待处理区间来避免递归风险。

2025-06-02 13:28:46 716

原创 C++中的内存分配和管理

程序内存布局与动态内存管理摘要 内存布局分为数据段(.data、.bss、.rodata)和代码段。数据段存储全局/静态变量,代码段存放机器指令和常量数据,具有只读特性。动态内存方面,malloc/free与new/delete存在关键差异:new会调用构造函数/析构函数,且通过异常处理失败;而malloc仅分配原始内存。内存泄漏指程序失去对已分配内存的控制,长期运行会导致系统性能下降,需特别注意资源释放。理解这些机制对编写高效、安全的程序至关重要。

2025-06-01 20:58:16 588

原创 C++中的类和对象

1. 声明和定义全部放在类体中 需注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。2.类声明放在.h文件中,成员函数定义放在.cpp文件中,注意:成员函数名前需要加类名::(做项目更通用)

2025-06-01 13:27:09 779

原创 C++的一些基础知识总结

C++库中的所以的东西都是放在std命名空间中 ,如果将命名空间全部展开,自定义变量不能于std命名空间的变量冲突。自己也可以创建命名空间,命名空间可以嵌套。

2025-05-31 17:33:15 860

原创 C++中vector的实现

本文详细介绍了vector容器的实现原理和关键操作。vector采用动态数组实现,包含三个迭代器成员变量(_start、_finish、end_of_storage)分别指向数组首元素、末元素后位置和存储空间边界。文章分析了构造函数、resize/reserve扩容机制,指出浅拷贝在vector<string>时会导致野指针问题,必须使用深拷贝。此外还阐述了push_back、insert、erase等操作的实现细节,以及operator[]的重载方式。

2025-05-31 14:57:19 1362

原创 C++中string的实现

string如其名,就是一个字符串,string的成员对象有char* _str(指向存储的字符串),size_t _size(记录该字符串所含的字符个数),size_t _capacity(该指针指向空间的大小容量)。

2025-05-30 20:45:58 478

原创 C++中List的实现

文章详细讲解了双向链表(list)的实现原理。通过定义包含前驱/后继指针和数据的_node结构体构建链表基础,并使用迭代器(_list_iterator)封装节点访问操作,支持++、--、解引用等功能。通过模板技术实现了const与非const迭代器的区分,确保类型安全。具体实现包括默认构造函数、begin/end获取、push_back尾插、erase删除、clear清空、insert插入等核心操作,并分析了迭代器传值设计的原因。最后展示了链表的打印功能,完整呈现了一个STL风格的双向链表实现框架。

2025-05-29 21:29:10 797

原创 用队列实现栈

用栈实现队列

2025-05-06 14:32:00 143

空空如也

空空如也

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

TA关注的人

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