
C++
文章平均质量分 85
C++学习笔记
凌星An
1
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
KMP算法讲解
首先KMP算法使用来匹配字符串的。而且时间复杂度为O(M+N) M,N分别为两个字符串的长度。时间复杂度这么低,是怎么做到的呢?算是用空间换时间的算法。匹配的子串中,若有重复的字段,下一个匹配可以重复使用,避免重头开始匹配。我们可以参考图片理解:我们在暴力算法中,挨个匹配,如果匹配失败了,从头开始,如上图逐步匹配示意的那样,那么时间复杂度为O(M*N)。但我们发现子串中,前四个字符,每两个一组,两组字符相同,所以当第五个字符匹配失败的时候,我们不必从头开始,而可以像上图跳跃匹配.原创 2020-06-09 10:34:40 · 605 阅读 · 0 评论 -
[C/C++]函数重载,三连问,你会吗?
目录1. 什么是函数重载2.为什么C++能够支持函数重载,而C语言不支持函数重载。函数修饰规则总结判断是否是函数重载func(vector& vec)和func(vector& vec)可以构成函数重载吗?func(const int val)和func(int val)可以构成函数重载吗?1. 什么是函数重载首先,本文是在讲函数重载,那么函数重载是什么呢?函数重载是指在相同的作用域中,具有相同的名称而形参列表不同的多个函数。***注:与函数返回值无关 ***。形参列表不同代表:函数原创 2021-08-22 19:31:51 · 1174 阅读 · 10 评论 -
Error:Enable multithreading to use std::thread: Operation not permitted
解决方法: 增加 -Wl,–no-as-needed 选项terminate called after throwing an instance of ‘std::system_error’what(): Enable multithreading to use std::thread: Operation not permittedAborted今天在使用c++11的thread库编写代码测试的时候,编译.cpp文件后,执行对应的可执行文件的时候出现上述错误情况如下:使用编译命令如下:原创 2021-08-04 16:05:08 · 748 阅读 · 3 评论 -
[C++]异常处理,你不会不清楚吧
文章目录异常概念:C语言中处理错误的方式:C++异常:异常的某些规则异常可以重新抛出异常规范异常安全:C++库的异常体系异常概念:异常是C++引入的一种新的处理错误方式,当函数发现一个自己无法处理的错误的时候,就会抛出异常,交给函数调用者进行处理C语言中处理错误的方式:1.使用断言assert() 进行判断2.返回错误码C++异常:C++中引入了三个关键字throw ,catch, try 来支持异常throw: 当出现错误,进行抛出的时候,是使用throw完成的catch: 在可能出原创 2021-06-20 21:06:14 · 241 阅读 · 0 评论 -
[STL]priority_queue(优先队列)的底层实现
namespace queue{ template <class T> struct less{ bool operator()(const T& x1, const T& x2) { return x1 < x2; } }; template <class T> struct greater{ bool operator()(const T& x1, const T& x2) { return x1原创 2020-05-18 15:02:19 · 1121 阅读 · 0 评论 -
STL迭代器失效问题总结
什么是迭代器失效?我们在使用STL时,有时候会出现程序崩溃的结果,而原因如图所示,这便是迭代器失效所导致的哪些操作会引起迭代器失效呢?由于插入元素,或者扩容可能引起的迭代器指向的元素或者空间发生变化,从而导致迭代器失效 由于删除元素使得某些元素次序发生变化使得原本指向某元素的迭代器不再指向希望指向的元素。 由于容器空间被释放导致存放原容器元素的空间不再有效,从而使得指向原空间的迭代器失效。 由于容器元素整体“迁移”导致存放原容器元素的空间不再有效,从而使得指向原空间的迭代器失效。原创 2020-11-21 15:22:55 · 1725 阅读 · 1 评论 -
插入排序:直接插入排序和希尔排序的思想及代码实现
直接插入排序:基本思想将待排序的记录按其关键字的码值的大小逐步插入到一个已经排好序的序列,直到所有的记录插入完为止,得到一个全新的有序序列图型解释代码实现void Insertsort1(int* a, int n)//O(N^2){ //整体排序 for (int i = 0; i<n-1; ++i) {//单趟排序 将tmp插入到[0,end]的有序区间。 ...原创 2020-03-10 13:15:48 · 262 阅读 · 0 评论 -
左值引用与右值引用(C++11)
什么是左值?什么是右值?这里的左右不代表位置,也就是说左值不是左边的值,右值也不是右边的值;这里的左右仅仅是一种叫法。那什么是左值呢? 左值通常来说就是一个变量;例如: int x=10; 则x就是一个左值!那么什么是右值呢?右值通常来说是一种不可改变的值,例如:刚才的常量10,临时对象(表达式计算后的结果;函数返回的值);而右值又可以分为纯右值和将亡值。纯右值是指基本类型的常量或者临时对象,将亡值是指自定义类型的临时对象。int x=10; int y=2; int z=x+...原创 2020-09-03 19:05:37 · 749 阅读 · 0 评论 -
字符串函数的自我实现
#include <string.h>strlen :Get the length of a string.(求字符串长度)size_t strlen( const char *string );“hello bit.\n”这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串。注:字符串的结束标志是一个 \0...原创 2019-10-20 12:01:32 · 226 阅读 · 0 评论 -
C++:智能指针,这就是你想要的
前言:智能指针主要用来释放资源,防止某些情况下导致内存泄漏当我们使用new关键字在堆上申请了一块空间,而没有进行delete,这就造成了内存泄漏;还有如果fopen打开文件后,没有关闭。这也造成了隐患。当然上面这一些明显的错误,还有一些难以察觉的错误。int*p= new int (0);fun();delete p;//在执行fun函数的时候,发生异常情况,直接退出,而此时申请的资源还没有释放,而且不会再执行到下面的delete p这个语句,也就造成了内存泄漏..原创 2020-07-23 23:47:53 · 285 阅读 · 0 评论 -
哈希第五弹:哈希应用之布隆过滤器
前言:我们在使用新闻客户端看新闻时,它会给我们不停地推荐新的内容,它每次推荐时要去重,去掉那些已经看过的内容。问题来了,新闻客户端推荐系统如何实现推送去重的? 用服务器记录了用户看过的所有历史记录,当推荐系统推荐新闻时会从每个用户的历史记录里进行筛选,过滤掉那些已经存在的记录。 如何快速查找呢?如何我们使用哈希表的话,如果太多的新闻,所需要的内存也是个巨大的问题但是我们要使用位图的话,哈希冲突就是一个不可避免的问题!由于推送新闻,我们允许有一定的错误发生!我们就可以将哈希表和位原创 2020-07-10 19:27:49 · 390 阅读 · 0 评论 -
C++ 相对于98而言,11的新特性(C++11)第一弹
前言:虽然11年相较于现在,已经过去了9年时间,而C++11的新特性,我们也在不知不觉中使用。但作为C/C++的一名新手程序员,还想看了解一下11这个神奇的版本,相较于经典的98,做了哪些改动!本文是本人的一些了解。C++11列表初始化C++11扩大了初始化列表的使用范围,使其可用于所有的内置类型和用户自定义的类型,使用初始化列表时,可有=,也可以没有eg:内置类型: 我们习惯于int x=10; 而在C++11我们可以有了新的玩法 int x={10}...原创 2020-07-10 15:28:49 · 920 阅读 · 0 评论 -
typename关键字:几乎令人忽略的typename
前言:typename关键字是我们学习模板的时候,了解到的一个关键字。但在这几天之前,也仅仅是了解到有这个关键字,而几乎不用这个关键字。在个人看来,在template的参数中,由于class的存在这个简单的关键字,使typename变得有些暗淡。而在这几天的一句代码中,才让我迫不及待的了解这个关键字。这是一句什么代码呢?,让我们看正文!typename关键字typedef typename Hash::hash_iterator<K, std::pair<K, V&g.原创 2020-07-09 17:40:33 · 1217 阅读 · 1 评论 -
哈希第四弹:哈希的应用之位图
前言:不知道大家之前有没有了解过位图这个概念。而我初次知道位图这个概念的时候,大概是学习进程通信,信号的时候,用一个位标识一个信号;在信号的注册过程中,如果有该信号则该对应的比特位标志为1.信号注销的时候,该对应比特位更改为0.这个过程就类似于我们给定一个数列该数列为0~10以内的数字例如:1,3,7,5,4,7让你判断哪个数字在数列中出现过!我们的做法无异于开一个大小为11数组,全初始化为0,如果数字出现过,该对应位置的值改为1,表示出现过。最后遍历这个数组我们就可以知道答案。而位图的理原创 2020-07-09 15:59:37 · 230 阅读 · 0 评论 -
error C3203
error C3203error C3203: “MapKeyofValue”: 未专用化的 类 模板 不能用作 模板 变量,该变量属于 模板 参数“KeyofValue”,应为 real 类型参见对正在编译的类 模板 实例化“MAP::unordered_map<K,V>”的引用错误码的原因:这在于第二句报错, MapKeyofValue这我们使用错误;当我们更改为CloseHash::Hashtable<K, std::pair<K,V&...原创 2020-07-05 16:29:12 · 1935 阅读 · 0 评论 -
哈希第三弹:解决哈希冲突之开散列以及unordered_map和unordered_set的自我实现
前文:解决哈希冲突,我们有闭散列和开散列两种。闭散列的线性探测,容易使冲突堆积在一起,因而会造成搜索效率的下降。而二次探测在一定程度上解决了线性探测的问题,但是随着会带来空间浪费的情况。而本文我们所要讲的开散列,既不会造成冲突聚堆的情况,也不会带来空间浪费的问题。这种优势源于开散列的桶结构。开散列(链地址法、开链法)对关键字集合用散列函数计算散列地址,具有相同地址的关键码归于同一个子集合,每一个子集和称为一个桶,各个桶中的元素通过一个单链表连接起来,各链表的头结点存储在哈希表中。...原创 2020-07-09 11:51:23 · 867 阅读 · 0 评论 -
哈希第二弹:避免哈希冲突详解及其代码粗略实现哈希表
前引:我们在哈希第一弹中提到了避免哈希冲突的三种方法,在本篇博文中我们对他们进行更加详细的了解哈希冲突的解决方法闭散列(开放定制法):当发生哈希冲突时,如果哈希表未被装满,说明在哈希表中必然还有空位置,那么可以把关键字存放到冲突位置中的“下一个”空位置中去。如何寻找下一个空位置呢?线性探测:从发生冲突的位置开始,依次向后探测,直到寻找下一个空位置为止二次探测:从发生冲突的位置开始,找下一个空位置,查找...原创 2020-07-05 16:05:57 · 361 阅读 · 0 评论 -
哈希第一弹:哈希的概念、哈希函数以及哈希冲突的解决方法
哈希的概念:哈希表查找的基本思想是:根据当前带查找数据的特征,以记录关键字为自变量,设计一个哈希函数,以该函数按关键码计算该元素的存储位置,并按此存放;查找时,有同一个函数对给定值key计算地址,将key与地址单元中元素关键码进行比较,确定查找是否成功。哈希方法中使用的转换函数称为哈希函数,按这个思想构造的表称为哈希表(散列表)从上面的概念,构建哈希表关键是有哈希函数。那么我们来看看常见的哈希函数有哪些?常见哈希函数:直接定制法:取关键字的某线性函数为哈希地址:Hash...原创 2020-07-03 14:10:37 · 1005 阅读 · 0 评论 -
指针与数组:数组指针、函数指针、函数指针数组
数组:int arr[10]arr:代表数组首元素的地址即&arr[0]&arr:代表整个数组的地址。int* p=arr;int (*p1)=&arr;数组名在两种情况下代表整个数组:sizeof(arr) &arr+1字符串指针int main(){ *str1="hello word";//"hell...原创 2020-04-09 16:39:36 · 325 阅读 · 0 评论 -
map和set的接口及其使用
set:set是一个key的搜索模型,底层是一个平衡二叉搜索树。应用于查找是否有key的场景插入:insertpair<iterator,bool> insert (const value_type& val);//插入一个值iterator insert (iterator position, const value_type& val);//在某个位置插入一个值template <class InputIterator> void in原创 2020-06-10 09:04:58 · 275 阅读 · 0 评论 -
平衡二叉树
概念:二叉搜索树又称为二叉排序树。他要不是一棵空树,要不是一个具备(它的左子树若不为空,则左子树上所有的节点的值全部小于根节点的值;它的有子树若不为空,则右子树上所有节点的值全部大于根节点的值)性质的二叉树。由定义我们可以知道二叉搜索树的中序遍历是有序的;并且二叉树中节点的值是独一无二的。代码实现:二叉树的插入、删除、查找template <class T>struct BSTreeNode{ struct BSTreeNode<T>* _left;原创 2020-06-09 09:30:23 · 162 阅读 · 0 评论 -
为什么要使用父类指针和引用实现多态,而不能使用对象?
class A{public: virtual void func1(int val = 1){ std::cout << "A->" << val << std::endl; }private: int _a;};class B : public A{public: virtual void func1(int val){ std::cout << "B->" << val << std::e...原创 2020-06-01 16:22:14 · 1756 阅读 · 1 评论 -
析构函数是否需要定义成虚函数?
我们用派生类声明出对象的时候,即使不把析构函数定义成虚函数,析构派生类对象的时候,也会自动调用基类的析构函数。这样看来我们似乎不需要将析构函数定义成虚函数,也不存在什么问题。class Person{public: ~Person() { cout << "~Person" << endl; }};class Student :public Person{public: ~Student() { cout << "~Student" &l原创 2020-05-28 18:03:18 · 830 阅读 · 0 评论 -
C++的IO流
输入输出缓冲区:可以屏蔽掉低级I/O的实现。低级I/O的实现依赖操作系统本身内核的实现,如果屏蔽掉这部分差异,很容易写出可移植程序。 使用这部分行为实现“行”读取的行为。计算机本身没有“行”的概念。但是通过这部分,可以定义“行”的概念,然后解析缓冲区的内容,返回一个“行”。流:流是对一种有序连续且具有方向性的数据的抽象描述。C++流是指信息从外部输出设备向计算机内部输入和内存和从内存向外部输出设备输出的过程。 C++ I/O标准类库四个全局流对象:cin co...原创 2020-05-27 17:10:56 · 310 阅读 · 0 评论 -
C++多态
概念:去完成某个行为时,调用不同的对象去完成时会产生不同的结果(状态)。多态的构成条件:必须通过基类的指针或者引用调用虚函数 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写。虚函数:被virtual修饰的类成员函数称为虚函数。虚函数的重写派生类中拥有一个和基类完全相同的虚函数(返回值类型、函数名字、参数列表完全相同),称为子类的虚函数重写了基类的虚函数虚函数的重写例外:在重写基类虚函数时,派生类的虚函数不加virtual,也可以构成重写。(基类的虚函数被继承下.原创 2020-05-31 16:16:41 · 507 阅读 · 0 评论 -
C++继承
概念:继承机制是面向对象程序设计使代码可以服用的最重要手段,它允许程序员在保持缘由类特性的基础上进行扩展,增加功能,这样产生新的类,称为派生类。父类也叫基类。子类也叫派生类。定义格式:class/struct 派生类名称 :继承方式 基类名称注: 基类的private成员在派生类中无论以什么样的方式继承都是不可见的,指派生类对象不管在类里面还是类外面都不能访问它 如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protetced成员。...原创 2020-05-22 17:29:59 · 256 阅读 · 0 评论 -
为什么C++中模板不能分离编译
首先我们需要了解什么是分离编译:分离编译:一个程序(项目)有诺干个源文件共同实现,而每个文件单独编译生成目标文件,最后将所有目标文件链接取来形成单一的可执行文件的过程为分离编译我们可以看下面的代码,具体理解//ADD.hint Add(int x1,int x2);//ADD.cppint Add(int x1,int x2){ return x1+x2;}//main.cppint main(){ cout<<Add(1,2)<&l原创 2020-05-20 17:50:58 · 1256 阅读 · 4 评论 -
STL中vector的底层实现
namespace MyVector{ template<class T> class vector{ public: typedef T* iterator; typedef const T* const_iterator; iterator begin() { return _start; } iterator end() { return _finish; } const_iterator cbegin() const原创 2020-05-14 14:15:30 · 860 阅读 · 0 评论 -
[STL]list的底层实现
在看底层代码之前我们需要了解几个问题问题一:STL链表是一个什么结构?STL链表是一个双向循环链表。问题二:那么list类中怎么构建这样的一个双向链表呢?先构建一个无任何作用的头结点,如果链表需要新增节点,那么只需要插入即可问题三:解决完链表的构造,那么另一个重要的问题:迭代器的实现我们知道迭代器支持前置++ 、- -、后置++ 、- -以及解引用、->等等、*对于string、vector等容器、迭代器可以看作一个指针;++、- -等只需要指针进行++ 、–进行前后移动即可 。原创 2020-05-14 11:07:56 · 510 阅读 · 0 评论 -
有没有玩过空间复杂度O(1)的二叉树中序遍历
二叉树的前序遍历,时间复杂度为O(N),空间复杂度为O(1)原创 2020-04-27 21:23:50 · 1078 阅读 · 0 评论 -
string类成员函数的简单实现
namespace MyStringNew{ class String{ public: //构造,先申请内存,再将内容拷贝到申请的内存上面 String(char* str="") :_str(new char[strlen(str)+1]) { strcpy(_str, str); } ~String() { delete _str; ...原创 2020-04-24 10:54:46 · 437 阅读 · 0 评论 -
string接口的自我实现及其底层逻辑
namespace MyString{ class String{ public: //浅拷贝 //拷贝构造,缺省值为"" ;不能给nullptr指针 String(const char* str="") :_size (strlen(str)) { _str = new char[_size + 1]; strcpy(_str, str); ...原创 2020-04-22 17:20:25 · 224 阅读 · 0 评论 -
C++的模板语法
函数模板:函数模板代表了一个函数家族,该函数与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。原创 2020-04-09 13:08:08 · 820 阅读 · 0 评论 -
内存管理
C、C++内存分配从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。eg:全局变量和static 变量在栈上创建。在执行函数是,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集在堆上分配(动态内存分配)...原创 2020-04-02 16:26:24 · 106 阅读 · 0 评论 -
C++: 命名空间、缺省参数、引用、函数重载
一、命名空间:使用命名空间的目的对标识符的名称进行本地化,以避免命名冲突或名字污染。(一个命名空间定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间)定义命名空间需要使用namespace关键字,后面跟着命名空间的名字,然后接一对{ },{ }中是命名空间的成员。命名空间的内容,既可以定义变量,也可以定义函数。**注:命名空间可以嵌套。同一个工程中允许存在多个...原创 2020-04-01 14:27:04 · 261 阅读 · 0 评论 -
类与对象二:static、友元、内部类
static:声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态的成员变量一定要在类外进行初始化一个类的静态成员函数只产生一个而无论生成的对象有多少个,且静态函数只能使用静态成员特征:1. 静态成员为所有类对象所共享,不属于某个具体的实例2. 静态成员变量必须在类外...原创 2020-04-01 15:20:14 · 221 阅读 · 0 评论 -
c++类与对象
常识c语言中,结构体中只能定义变量,在C++中,结构体不仅可以定义变量,也可以定义函数。C++把类型分成内置类型(基本类型)和自定义类型。内置类型就是语法已经定义好的类型:如int/char...,自定义类型就是我们使用class/struct/union自己定义的类型类## 类的定义class className{ //类体:由成员函数和成...原创 2020-03-28 17:56:21 · 223 阅读 · 0 评论