Cpp
文章平均质量分 92
楠c
这个作者很懒,什么都没留下…
展开
-
手写AVL树(详解插入时的4种旋转)
二叉搜索树有其自身的缺陷,假如往树中插入的元素有序或者接近有序,二叉搜索树就会退化成单支树,时间复杂度会退化成O(N)。所以科学家对二叉搜索树采取平衡处理,实现出AVL树。当向二叉搜索树中插入新结点后,如果能保证每个结点的左右子树高度之差的绝对值不超过1(需要对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。当这棵树是AVL树的时候,它的左右子树都是AVL树且左右子树高度之差(简称平衡因子)的绝对值不超过1(-1/0/1)如果一棵二叉搜索树的高度是平衡的,它就是AVL树。如果它有n原创 2021-06-03 22:09:01 · 642 阅读 · 3 评论 -
STL容器_map与set
序列式容器与关联式容器之前学的vector、list、deque都是序列式容器,在逻辑结构上是线性表。(栈和队列是容器适配器)而今天所学习的map与set是一棵搜索树,它叫做树型结构关联式容器,之后会学习的哈希表他是一种哈希结构关联式容器。关联式容器:关联式容器也是用来存储数据的,与序列式容器不同的是,其里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点原创 2021-05-31 11:09:50 · 435 阅读 · 1 评论 -
二叉搜索树(KV模型,二叉搜索树删除节点)
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:若它的左子树不为空,则左子树上所有节点的值都小于根节点的值若它的右子树不为空,则右子树上所有节点的值都大于根节点的值它的左右子树也分别为二叉搜索树每个子树均满足这个特征。他可以用来搜索,在我们以前怎么搜索呢,之前的数据结构不仅能存储数据,也能查找数据。最优搜索便是二分查找,但是二分查找前提必须有序,最快的一个排序也是n*logn,并且二分查找必须要在Vector中,头插,中间插,头删,中间删的挪动数据的复杂度也很高。他是一种原创 2021-05-19 19:08:09 · 523 阅读 · 2 评论 -
C++_多态(深入理解虚函数表)
多态多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。比如买票这个行为,当普通人买票时,是全价买票;学生买票时,是半价买票;军人买票时是优先买票怎么构成多态并没有构成多态,形参p对象,全部调用了Person类的成员函数。多态与重写这时候就需要使用虚函数来构成多态。梳理一下,多态的条件:继承类中,需要对虚函数进行重写。基类的指针或者引用都去调用这个虚函数而重写的条件3. 父子类中的函数都是虚函数。4. 函数名参数返回值都要相原创 2021-05-13 20:40:38 · 5190 阅读 · 24 评论 -
C++_继承(菱形继承与虚基表)
什么是继承继承是什么:继承是面向对象程序设计、使得代码可以复用的重要手段,它允许程序员在保持原有特性的基础上进行扩展,增加功能,这样产生的新类,称之为派生类继承的目的:让子类继承和复用父类定义的成员和方法、继承下来的变量是独立的、各自拥有各自的内存空间。继承方式和访问限定符可见在派生类中,子类的访问方式是,MIN(继承方式,基类访问方式)实际基类的private成员在派生类不可见,只是语法上无法访问,假如你调用基类的方法还是可以用的。但是调用继承的方法可以用使用关键字c原创 2021-05-08 12:38:58 · 812 阅读 · 3 评论 -
List的模拟实现(erase的迭代器失效)
vector和string的迭代器是原生指针,无论是解引用还是++,都可以得到自己想要的值。链表的迭代器不能是原生指针了,链表的解引用是想要链表的值,++是想到下一个节点,那么假如是原生指针的话解引用是一个结构体,++是下一个结构体。等等,所以我们要通过重载运算符来模拟我们想要的行为。所以迭代器也被成为一种设计模式。对于不同的类,不需要知道你的内部实现,就可以对你进行访问和修改。而对于赋值重载,需要实现深拷贝吗,不需要,我就是想要你那个节点的值。析构函数,不需要自己实现,因为迭代器是访问数据,修改数据原创 2021-04-24 16:08:45 · 458 阅读 · 2 评论 -
模拟实现vector(insert与erase迭代器失效)
目录1. 迭代器2. 构造函数2.1 无参构造2.2 迭代器构造2.3 拷贝构造2.4 赋值重载3. 析构函数4. 有效元素的个数5. 容量大小6. 重载[]7. 检查容量8. 扩容9. resize10. 插入11. erase插入与删除迭代器失效总结vector实现代码这是STL源码剖析中对于vector逻辑结构的一张图。和之前的顺序表不一样,成员变量我们采用的是一个个指针,start指向数组的首元素,finish指向末尾元素的下一个。endofstage指向数组容量的下一个。扩容Linux下是两原创 2021-04-24 14:51:21 · 603 阅读 · 2 评论 -
非类型模板参数与模板特化
目录1. 非类型模板参数2. 模板的特化2.1 函数模板的特化2.2 类模板的特化2.3 全特化与半特化1. 非类型模板参数之前由于一个类,我们想让里面的参数类型不同,引入了模板,不用重复写冗余的代码。现在有一个静态顺序表,其大小示固定的,假如想让他变化,碰见了和之前类似的问题。其实也可以用模板解决,size_t N=100,他是一个非类型的常量,确实,不是常量他也不可能做数组的大小。注意:不过通常不用静态的顺序表,栈只有8M。注意:非类型模板参数是一个常量浮点数、类对象以及字符串是原创 2021-04-23 11:10:35 · 520 阅读 · 1 评论 -
栈和队列以及认识优先级队列与双端队列(C++STL)
栈最优实现是数组。优点:随机访问,cpu缓存利用率高缺点:头部和中间,删除,插入效率较低。且需要增容队列最优实现是链表。优点:任意位置,插入和删除,O(1)缺点:不支持随机访问,缓存利用率低deque(双端队列):是一种双开口的"连续"空间的数据结构,双开口的含义是:可以在头尾两端进行插入和删除操作,且时间复杂度为O(1)。队列只能先进先出,他和队列没有关系,更像一个vector和list的融合体。与vector比较,头插效率高,不需要搬移元素;与list比较,空间利用率比较高。vector原创 2021-04-22 21:28:59 · 949 阅读 · 5 评论 -
vector的应用练习
这是一个vector模板的声明,实际上实例化需要传入模板参数。第一个是他的参数类型,例如vector<int>,vector<char>,甚至一个二维数组vectoe<vector<int>>,vector<vector<char>>等。第二个参数是空间配置器,空间配置器就是内存池,从内存池里拿内存,避免反复从操作系统申请。不是直接new或malloc,而是从内存池这个中间商去拿,可以提高效率。作为参数就是可以让我们自定义自.原创 2021-04-04 22:31:07 · 502 阅读 · 0 评论 -
模拟实现string(传统写法与现代写法)
目录简易string(无增删查改)深浅拷贝string更多的接口构造,拷贝构造,析构size,重载赋值,重载[]迭代器与范围for简易string(无增删查改)开始必须重新定义一个命名空间,把我们自定义的string放进命名空间里。假如不考虑增删查改,我们先可以做一个简单的string,几乎下意识的就写出了这样的构造函数string(char* str) :_str(str) {}这是非常不合理的,假如外面传入的是一个常量字符串。string s("1234");假如要修改常量字原创 2021-03-31 19:54:58 · 1767 阅读 · 3 评论 -
string类的认识与应用(C++)
string其实是typedef basic_string<char> string;也是是说他实际是一个类模板。写成模板意味着他也可以存其他类型的数据吗?我们大多数使用的是第一个string。在底层大概是这样的。template<class T>class basic_string{private: T* _str; int _size; int _capacity;}默认成员函数自动生成6个构造函数里面包含了拷贝构造。析构函数,赋值原创 2021-03-20 19:21:56 · 705 阅读 · 0 评论 -
C++泛型编程(模板)
我们先来看一个概念泛型编程:使用模板,编写和类型无关的代码。没有模板之前,一些函数或者类,针对不同的类型需要写很多重复的代码。函数:比如交换函数swap,假如传入的数据类型不同,int,char,double。我们要实现不同的类型对象函数。类:比如我们像实现一个数据结构栈stack,stack的多个对象,st1存储int,st2存储double在没有模板之前,我们要针对各个类型写很多个swap函数和stack类,而这些函数和类,逻辑是一样的,只是处理的对象的类型不同。1.函数模板templat原创 2021-03-16 17:59:33 · 221 阅读 · 0 评论 -
内存分布,内存管理,new与delete(c/c++内存管理)
学习之前先做两道题,来复习一下变量的内存分布。int globalVar = 1;static int staticGlobalVar = 1;void Test(){static int staticVar = 1;int localVar = 1;int num1[10] = {1, 2, 3, 4};char char2[] = "abcd";char* pChar3 = "abcd";int* ptr1 = (int*)malloc(sizeof (int)*4);int* p原创 2021-03-15 20:41:34 · 1005 阅读 · 1 评论 -
再谈构造函数,初始化列表,匿名对象,静态成员以及友元(c++)
目录1. 再谈构造函数1.1 初始化成员列表1.2 函数体内赋值和初始化成员列表区别1.3 初始化成员列表的作用1.3.1 const成员变量1.3.2 引用成员变量1.3.3 自定义类型成员变量1.4 初始化列表的顺序2. 匿名对象3. explicit关键字1. 再谈构造函数class Date{public: Date(int year;int month;int day) { _year=year; _month=month; _day=day; }private: i原创 2021-03-07 17:32:49 · 1048 阅读 · 3 评论 -
拷贝构造函数与运算符重载(c++详解)
拷贝构造函数与运算符重载拷贝构造函数引出拷贝构造函数运算符重载引出拷贝构造函数拷贝构造函数引出先给出日期类的定义:class Date{public: Date(int year=1900,int month=1, int day=1) { _year = year; _month = month; _day = day; } void print() { cout << _year << " " << _month &l原创 2021-02-06 20:02:09 · 3395 阅读 · 2 评论 -
构造函数与析构函数(c++详解)
构造函数与析构函数构造函数引出构造函数构造函数的重载与缺省析构函数引出构造函数引出类中什么都不写会被我们成为空类,但是空类的意思真的就是里面是空的吗,并不是一个类,假如我们没有显示定义,会自动生成6个成员函数。当我们对于默认生成的不满意,便可以自己定义其中不满意的函数。下面我们来看构造函数。构造函数构造函数是特殊的成员函数,名字与类名相同,创造自己类型的对象时由编译器自动调用,在对象的每个生命周期只调用一次,让其每个数据成员都有一个合适的初始值。虽然他的名字叫构造但他不负责开空间创建对象,而是初始化原创 2021-02-05 17:32:02 · 888 阅读 · 2 评论 -
浅谈struct与class,深入理解this指针
目录struct与class类类的作用限定符类的作用域类对象大小的计算this指针this指针的引出深入理解this指针struct与classstruct与class有什么区别C++兼容c,所以struct可以继续用于在c++中做结构体定义多个变量,同时struct与class用来定义类,它们不仅可以定义变量,也可以定义函数。struct中无论是成员变量还是成员函数都是public,而在class中默认为private。在编写C++代码中我们更多的用class来定义类。类类的作用限定符pub原创 2021-02-03 22:00:29 · 2806 阅读 · 1 评论 -
内联函数与宏,auto关键字的使用以及认识c++11的指针空值
目 录 内联函数内联的引出内联的特点auto关键字基于范围的for循环指针空值内联函数内联的引出调用函数就要建立栈帧,建立栈帧需要耗费资源。在C语言角度采用了宏函数来解决这一问题,但是宏函数也有缺点。缺点: 1.不方便调试。2.代码可读性差。3.没有类型安全的的检查优点:1.增强代码复用性。2.提高性能。C++用枚举,const,内联,inline函数,代替宏,而内联函数则是在需要经常调用,代码精简的函数前面加上inline。来使他在编译时就展开。编码经常需要交换,这里以原创 2021-02-03 17:43:49 · 305 阅读 · 1 评论 -
C++引用详解,引用与指针的区别
这里写目录标题引用引用的概念引用的注意事项常引用引用引用的概念引用并不是定义一个变量,而是给存在的变量取了一个别名。语法上没有独立空间,和引用的实体共用一块空间。但其实在底层是有空间的,因为他是用指针的来实现的。通过引用直接改变了值。引用的注意事项引用和引用的实体必须是同种类型。b是引用。&b是别名定义的时候必须初始化。一个变量可以有多个引用。一个引用一旦引用一个实体,不会改变。(b,c,d的地址一直没有改变)常引用const修饰不能修改的原因很简单,经过前面原创 2021-02-03 11:26:06 · 684 阅读 · 2 评论 -
腾讯面试题只是“Hello World”?深度理解命名空间与函数重载的原理(C++入门详解)
Cpp入门命名空间命名空间概念命名空间应用命名空间嵌套io流iostream命名空间无论学习编程语言,开始入门的“Hello World”是必不可少的。#include<iostream>using namespace std;int main(){count<<"hello world"<<endl;return 0;}看起来很简单,但是深究起来却有很大的学问。没错这其实是一位学长的腾讯面试题。是不是有点怀疑人生,其实面试官只是借助着一个简单的程序原创 2021-02-01 20:45:35 · 1440 阅读 · 3 评论