- 博客(41)
- 收藏
- 关注
原创 C++智能指针
智能指针的原理RAII 是一种利用对象声明周期来控制程序资源的简单技术,在对象构造时获取资源,接着控制对资源的访问使之在对象的声明周期内始终保持有效,最后在对象析构时释放资源。实际上是将这份资源交给一个对象去管理,让资源能够自动释放。智能指针的原理就是RAII的方法,保证资源能够被自动释放,其次通过operator*()和operator->()的方法,让对象能够按照指针的方式来运行,然后解决浅拷贝的问题,保证资源不会被释放多次引起代码崩溃。auto_ptrauto_ptr 是C++98标准库
2021-11-02 23:39:37 378
原创 C++位图及应用
位图位图是用一个比特位来表示一个数据是否存在这一状态的信息,1表示存在,0表示不存在。常用于海量的数据,没有重复的时候,快速判断某个数据是否存在1个字节有8个比特位,就能表示8个数据的状态信息,有N个数据,需要N/8+1个字节。例如,有一个整形数据集合 {1,3,7,4,12,16,19,13,22,18};其中最大数据为22,最小数据为1,首先估算需要大概多少个字节,位图中应包含min到max这个范围中所有数据的状态信息。实际需要22个比特位,需要3个字节的空间。第二步将集合中的数据向位图中进行
2021-11-02 18:00:49 531
原创 哈希和哈希桶
概念数据结构中有一类常用于搜索,给定一个元素集合,常见的可用于搜索的算法有遍历,遍历是十分粗暴简单的手段,对于元素的集合没有特殊要求,时间复杂度是O(N)。效率通常较低。二分查找,二分查找要求元素集合有序,时间复杂度为O(logN),二叉搜索树,查找规则简单,但是退化为单支树时间复杂度是O(N),AVL树和红黑树,时间复杂度都是O(logN).上面的这些常用的方法无一例外都有一个关键步骤就是元素的比较,通过比较待查找元素和集合中的元素,来确定该元素在集合中的位置。真实的效率取决于比较的次数。如
2021-11-02 15:35:05 2078
原创 红黑树实现
概念红黑树是一种二叉搜索树,在每个节点都上都增加一个字段表示颜色,红色或者黑色,通过一些条件的限制,达到最长路径中节点个数不会超过最短路径中节点个数的两倍。红黑树可以是空树。因此红黑树是一颗近似平衡的二叉搜索树性质:1.红黑树中的节点不是红色就是黑色。2.根节点一定是黑色。3.如果一个节点是红色,那么它的两个孩子节点是黑色。4.对于每个节点,从该节点到其后代所有节点的简单路径中,均包含相同数目的黑色节点。5.每个叶子节点都是黑色的。通过以上性质的约束,最终可以达到最长路径中节点个数不会超过
2021-10-28 14:09:57 364
原创 AVL树的实现和插入
二叉搜索树虽然可以提高查找效率,但是在数据有序或近似有序的情况下,二叉搜索树会退化为单枝树,查找效率大大降低,1962年两位俄罗斯数学家联合发明了以一种解决问题的办法,在对二叉搜索树进行插入时,保证每个节点左右子树高度之差的绝对值不超过1,那么就可以降低树的高度,进而减少平均搜索的深度。这种结构的二叉搜索树就是AVL树。AVL树实现节点的创建:节点中需要的成员有,左右孩子指针,增加了一个双亲的指针,表示平衡因子的bf,以及值域data。template<class T>struct
2021-10-27 17:56:26 443
原创 二叉搜索树转双向链表
根据描述,排序的双向链表与二叉搜索树的关系可以确定,二叉搜索树的中序遍历结果是一个有序序列,能确定的是中序遍历结果的首元素应是链表的第一个节点。然后就是根据中序遍历结果将树的结构改变为链表的结构,每个节点都有两个指向,一个left一个right,在中序遍历过程中,将拿到的每个节点的left指向比他小的元素中最大的那个,right指向比他大的元素中最小的那个。而在中序遍历过程中,left的指向即是刚刚遍历过的前一个节点,right指向是即将要遍历的后一个节点。class Solution {publi.
2021-10-25 02:51:49 812
原创 从前序和中序序列中构造二叉树
做法是将前序序列中依次拿到的元素作为根节点,在中序序列中找根节点的位置,将数分为左子树根节点右子树,递归创建左子树和右子树class Solution {public: TreeNode* _buildTree(vector<int>& preorder,size_t& index,vector<int>& inorder,size_t left,size_t right){ if(left >= right){ .
2021-10-25 02:31:10 114
原创 二叉树层序遍历(给你一个二叉树,请你返回其按 层序遍历 得到的节点值)
要求是将层序遍历的结果,第一层中节点的值域存在二维数组的第一个vector中,第二层的存在第二个中。依次继续。创建一个二维数组作为最终输出结果,创建一个队列用来取每层的拿到的值域,创建一个vector对象levelval用来保存每层拿到的值域的集合。以示例为例,第一次3所在的节点入队列,此时队列中节点的个数size更新为1个,从队列中拿出size个节点,将它的值域交给levelval,如果这个节点有左右孩子,则依次将左右孩子入队列,从队列中删除3这个节点,将levelval插进二维数组ret中。接下来..
2021-10-25 02:26:34 417
原创 根据二叉树创建字符串
根据示例描述总结一下规律,前序遍历顺序根-左-右先保存根,然后遍历根的左子树,如果左子树为空,要先补一对括号,然后遍历右子树,如果左子树非空,则先用括号扩起左子树,然后递归遍历左子树。右子树如果为空,直接省略,如果非空,用括号括起来,递归遍历右子树class Solution {public: void tree2str(TreeNode* root,string& ret){ if(nullptr == root){ return; .
2021-10-25 02:02:12 79
原创 二叉搜索树
性质二叉搜索树又称二叉排序树,是一类具有特殊性质的树。具体体现在二叉搜索树中,每个节点都比它的左孩子大,比它的右孩子小。中序遍历结果是一个有序序列,树中最左侧的节点是序列中最小的元素,最右侧的节点是序列中最大的节点。相关操作及实现创建一个节点创建一个树的节点,给出指向左右孩子的指针以及值为data的值域。template <class T>struct BSTNode { BSTNode(const T& x = T()) :left(nullptr) ,ri
2021-10-25 01:51:52 310
原创 C++继承
定义继承是C++中实现代码复用的重要手段,核心思想概括为共性抽取,即将一些相同的特性抽取出来,单独实现成一个类,而把关注点放在不同的特性上,方便在类原有特性上进行扩展,增加新的功能。包含共同特性的类称为父类或基类,扩展出来的新的类称为子类或派生类。继承的特性也体现了面向对象设计的层级结构。继承方式继承方式用来控制不同的方式下,基类中具有不同访问权限的成员在子类中的访问权限。例如public:在public继承方式下,基类中的成员不论公有私有保护的都被继承,基类中私有成员在子类中虽然不可见,但是也
2021-10-21 22:56:25 221
原创 栈的压入弹出序列
思路是用栈模拟弹出的过程,pushv来表示入栈序列,popv来表示出栈序列首先如果元素个数不相同肯定不是正确的出栈序列将栈中栈顶元素与出栈序列中的元素进行比较,如果不同,则取入栈序列中下一个元素入栈,如果相同则栈顶元素出栈,与下一个出栈序列中的元素比较。当没有元素可以入栈时,比较剩余的元素,不相同则返回false。全部比较完成都满足条件,则说明是正确的入栈序列。以示例为例子 入栈序列为 1 2 3 4 5 出栈序列为 4 3 5 1 2开始栈为空,取入栈序列第一个元素1入栈,第二趟,栈不为空,将.
2021-09-10 01:11:54 426
原创 逆波兰表达式求值
思路是用一个栈来保存所有数字,如果取到一个数字就入栈,如果取到一个算术符,就从栈中取两个数进行运算,并将它们的结果入栈,因为栈的特性,所以先取出的是右操作数,然后才是左操作数。最后栈中应只剩一个结果,返回栈顶元素就是最终结果。[“2”,“1”,"+",“3”,"*"] 以示例为例,2是数字,入栈,1是数字,入栈,下一个取到+,从栈中先取1 再取 2 计算2+1的结果3 入栈,再取3 是数字 入栈,再取是运算符,从栈中取3 和 3 计算3×3结果9入栈,循环结束 返回栈中仅剩的9。class Solut.
2021-09-09 20:49:36 79
原创 用队列实现栈
每次插入元素后,调整队列中元素的位置,先获取队头元素并删除,再将该元素插入到队尾。实现先入后出的特性。class MyStack {private: queue<int> q;public: /** Initialize your data structure here. */ MyStack() {} /** Push element x onto stack. */ void push(int x) { int size = q.size(); .
2021-09-09 17:22:29 71
原创 用栈实现队列
需要用到两个栈,st1用来入队列,st2用来出队列,将元素入栈的方式进入st1后,从st1中不断取栈顶元素再删除,将取道的元素压入st2中,然后出队列时候从st2中取栈顶元素,就可以满足队列的先入先出特性。class MyQueue { stack<int>st1; stack<int>st2;public: /** Initialize your data structure here. */ MyQueue() {} /** Push.
2021-09-09 17:12:26 88
原创 模拟string类的一些常用接口
#define _CRT_SECURE_NO_WARNINGS#include<iostream>#include<assert.h>#include<algorithm>using namespace std;namespace my{ class string{ public: typedef char* iterator; public: string(const char* str = ""){ if (nullptr == st
2021-08-30 13:58:04 97
原创 vector中迭代器失效
什么是迭代器失效迭代器是将指针的方法封装形成的一种新的类型,和指针的特点类似,当指针指向一段不存在的空间时,该指针就是所谓的野指针,再使用迭代器就相当于在操作一个野指针会导致程序崩溃vector迭代器失效的情况所有的插入操作有可能会导致迭代器失效,如push_back,insert,因为插入元素可能会需要扩容,扩容的过程要释放旧空间使用新空间,如果没有给迭代器重新赋值,那迭代器还指向已经被释放掉的旧空间,就会导致迭代器失效。删除操作earse,vector中erase方法的参数是一个迭代器类型的p
2021-08-30 00:35:40 671
原创 字符串相加
要将两个存放整形数字的字符串进行相加,可以按照小学学竖式的思路进行。定义一个long_num表示num1 的字符个数 short_num表示num2 的字符个数,通过比较让long_num标记较长的字符串。然后定义一个string类型对象用来存放结果。定义一个carry用来标记是否有进位。从两个字符串的末尾开始拿数字进行相加,如果有进位下一轮相加时要加上进位,每次加完后要将进位标记置为0。循环结束时要判断是否还有进位,有要将进位的1也保存起来,没有则要将保存结果的字符串的首位删掉class So
2021-08-26 01:46:32 1616
原创 验证一个字符串是否是回文
因为给的字符串有空格等符号,所以首先判断拿到的字符是否是有效字符,包括大小写字母和数字。然后要将字符串中属于字母的大小写统一起来。begin从前往后拿字符,end从后往前拿字符,拿到有效的字符了就进行比较。class Solution {public: bool isvalidchar(char ch){ if((ch >= '0' && ch <= '9')|| (ch >= 'a' && ch <
2021-08-26 01:37:00 266
原创 求字符串中最后一个单词的长度
主要注意输入时候,cin输入是会过滤掉不可见字符如空格,回车。从第一个非空白符开始读,直到空白符或结束为止。单词是以空格分隔的,从后往前找第一个空格的位置,字符串的有效元素个数减去它,因为有效元素个数是从1开始计的,位置pos是0开始的,所以得再减个1,就是最后一个单词长度。#include<iostream>#include<string>using namespace std;void lenth_of_lastword(string& s) { size_
2021-08-26 01:31:35 256
原创 找出字符串中只出现一次的字符
sting类中的find和rfind方法,从给定字符串的第一个字符开始,find是从前往后找,rfind是从后往前找,如果最后找到的位置相同,那这个字符是唯一字符,如果位置不相同,这个字符是重复的。#include<iostream>#include<string>using namespace std;void find_once_char( string&s ) { for (size_t i = 0; i < s.size(); i++) { if
2021-08-26 01:25:04 2245
原创 深拷贝和浅拷贝实现
浅拷贝在类的默认成员函数的特性中提到,如果类中涉及到资源的管理,那拷贝构造必须要显示提供,否则可能会导致程序崩溃。#include<iostream>using namespace std;class String {public: String(const char* str = "") { _str = new char[strlen(str)] + 1; strcpy(_str, str); } ~String() { delete[]_str; }pri
2021-08-24 15:50:57 115
原创 string类及一些常用接口
string中的常用构造方法string(); 构造一个空字符串。string(const char* s);用C风格字符串构造string类的对象string(size_t n,char c);构造一个含有n个字符c的字符串。string(const string& s);拷贝构造方法。//构造方法void Teststring1() { string s; string s1("hello world"); cout << s1 << endl;
2021-08-24 01:36:44 151
原创 求1+2+3+...+n要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)
思想:①通常我们可以通过循环的方法创造出1~n的每个数字,再累加就可以,因为不能使用循环,所以需要先创建出1到n的所有数字,通过构造函数的特性,每创建一个对象就要调用一次构造函数,在构造函数中记录构造函数调用的次数,再用一个值进行加法。②通过&&运算符,代替循环的方式给出递归出口。①class Sum{public: Sum(){ _count++; _sum+=_count; } Sum(const Sum& s){
2021-08-20 02:20:56 198
原创 C++内存管理
C++内存分布内核空间操作系统相关的数据和代码,有访问硬件设备的权限,用户不允许读写。用户空间栈区 :非静态的局部变量,和函数调用相关的一些信息,函数的参数返回值,包括一些寄存器信息等内存映射段 :共享动态内存库,静态库。堆区 :动态内存分配,如malloc realloc calloc开辟的空间数据段 :全局和静态的数据,如函数内部用static修饰的局部变量,不会随着函数结束被释放,生命周期变长。代码段 :不允许被修改的,可执行的代码,只读常量。C++内存管理malloc
2021-08-20 01:58:48 124
原创 C++日期类实现
#include<iostream>using namespace std;class Date{public: //构造函数 Date(int year = 1900,int month = 1,int day = 1) :_year(year) ,_month(month) ,_day(day) { //判断参数合法性 if (!(year > 0 &&
2021-08-20 00:05:25 70
原创 类和对象总结
1.面向过程和面向对象的区别面向过程的思想重点关注解决问题的过程,主要体现在以函数来驱动程序的进展。面向对象的思想主要将问题分解为多个对象,关注对象之间的交互。2.类和对象的区别类是用来描述对象的一种自定义类型,成员是具有实际属性的一个实体,一个类通过实例化可以创建出多个对象,类定义出来后并没有分配内存空间,只有实例化出对象才开辟空间。3.class关键字class是C++中定义类的关键字,C++兼容C语言,struct也可以定义类,但是class和struct定义出来的类,成员的默认访问权限不同
2021-08-17 02:03:56 193
原创 C++中this指针
在C语言中,定义一个日期类型的结构体,并给出设置和打印的方法函数setDate和printDate中,第一个参数是一个结构体类型的指针,用来接收结构体类型变量的地址,通过这个参数就知道要调用这个方法给哪个变量来设置值或是打印。#include<stdio.h>struct Date { int year; int month; int day;};void setDate(struct Date* p,int year, int month, int day) { p->
2021-08-15 12:01:06 284
原创 C++函数重载
函数重载的概念是指c++中允许在同一作用域中声明几个功能类似的同名函数,函数的名字相同,参数列表不同。类型,次序,个数。调用原理:同名函数存在的情况下,在编译阶段,编译器会对实参的类型进行推算,根据结果来挑选合适的函数来调用,如果没有合适的类型,会在内部尝试进行隐式类型转换。C++如何支持函数重载C语言和C++在编译过程中,都会对函数名变量名进行重新改编,C和C++有不同的名词修饰规则。在C的编译过程中,函数名的修饰就是在原函数名前加下划线 Bubblesort 被修饰为 _Bubblesort。由
2021-08-14 01:18:28 103
原创 二叉树实现
二叉树的链式结构二叉树是一种特殊的树形结构,由根节点加上左右两棵子树组成,每个节点最多有两棵子树,不存在度大于2的节点。没有节点存在时也称为空二叉树。二叉树不适合顺序存储,顺序结构只包含有效元素,没法确定哪个节点有还是没有左右孩子这层关系。链式结构更适合建立二叉树。二叉树有双亲表示法,孩子表示法,孩子兄弟表示法等,这里实现用的是孩子表示法,即节点中表示出与其孩子的关系创建一个二叉树节点的结构,left指针指向左孩子,right指向右孩子typedef int BDatatype;typedef
2021-08-13 22:13:07 108
原创 栈和队列实现
栈栈是一种特殊的线性数据结构,只能在一端进行数据的插入和删除操作。数据插入和删除的一端称为栈顶,另一端称为栈底。数据插入的操作称为入栈,数据删除的操作称为出栈。栈中的元素有后进先出的特性。顺序栈的实现定义一个栈的结构,声明数据的类型,栈结构中定义存储元素的数组。栈的初始容量,当前栈中元素的个数。typedef int Datatype;typedef struct Stack { Datatype* array;//数组 int capacity;//容量 int Size;//栈中的元素个
2021-08-13 14:10:01 91
原创 常用排序算法
插入排序实现原理: 直接插入排序的思想是将一个序列中的元素,按排序规则插入到序列中适当的位置里。 单个元素的插入首先要保证插入的序列已经有序,然后在这个有序的序列中找待插入的位置,将该位置之后的元素向后搬移一位,再将值插入进去。对于一个待排序的序列,只有第一个元素是已经有序的,所以序列中的第二个元素就是第一个要待插入的元素。按照单个元素插入的思想调整它的位置,再找下一个元素进行,直到序列有序。一个排升序的插入排序void InsertSort(int array[], int size)
2021-08-13 02:16:31 108
原创 带头双向循环链表的实现
带头双向链表,比单向链表多了一个头节点,和一个字段一个是指向前一个节点的指针,一个是指向后一个节点的指针。typedef int Datatype;typedef struct SlistNode { struct SlistNode* prev;//指向前一个的指针 Datatype data;//值域 struct SlistNode* next;//指向后一个的指针}Node;创建一个节点Node* BuySlistNode(Datatype data) { Node* newn
2021-08-06 02:49:57 81
原创 无头单链表实现
链表的结构是一个一个节点,每个节点中有指向下一个节点的指针域和自身的值域,typedef int Datatype;typedef struct SlistNode { Datatype data; struct SlistNode* next;}Node;初始化操作这个head是指向链表的指针,链表作为线性结构一定有起始位置,这样才能找到下一个节点的位置。初始化那就让这个指针指向空。void SlistInit(Node** head) { assert(head); *head =
2021-08-06 02:33:14 118
原创 顺序表实现
对顺序表的理解用线性结构来组织元素的方式称为线性数据结构,元素在一段连续空间上按顺序存储,每个元素都有唯一的前驱和后缀。数组和顺序表都是经典的线性数据结构。顺序表采用数组存储元素,也在数组上完成对顺序表操作。动态顺序表实现这里给将数据类型重定义为Datatype类型,如果以后要存其他类型的元素只需要把修改int就够了。typedef int Datatype;typedef struct Seqlist { Datatype* array;//指向动态开辟的顺序表的空间 int size;//
2021-08-06 01:32:42 112
原创 C语言文件的一些操作
这一段代码,展示的是写一个指令,可以拷贝一个文件中的内容到另一个文件中。 FILE* fpIn = fopen("argv[1]", "r"); assert(fpIn != NULL); FILE* fpOut = fopen("argv[2]", "w"); assert(fpOut != NULL); char buffer[256] = { 0 }; char* res = fgets(buffer, 256, fpIn); while (res != NULL) { fputs(
2021-08-01 23:40:08 143
原创 C语言动态内存管理
C语言中的内存分配在写c的代码中,定义不同类型的变量,定义一个变量就在内存上开辟了响应的空间。有个比较基础的概念,内存中有栈区,堆区,静态常量区。常用的一些内容,比如函数调用参数,临时变量都是在栈区开辟空间。全局变量,静态修饰的变量,字符串常量一些都是开辟在静态常量区上的。有时候需要多么大的空间在程序运行中才能计算,就需要动态开辟空间的方法。动态开辟的空间是在堆区进行的。C中提供了动态内存开辟的函数。malloc函数void* malloc(size_t size)这个函数的作用是向内存申请一块连续
2021-08-01 01:40:09 105
原创 C语言结构体内存对齐
关于结构体的几个易错问题结构体主要掌握它的声明,结构体变量的定义和初始化,结构体传参等方法。其中有几个问题需要特别注意。一是结构体的自引用,不能再内部定义自己类型的变量,因为这个结构体还没有声明完成,它没有大小,在内部直接定义自己类型的变量编译器不知道要开辟多大的空间,这是不合法的。但是定义自己类型的指针是可以的,指针变量的大小是固定的。二是C语言中,结构体不允许是空结构体,至少要有一个成员,但是C++种支持空结构体.三是结构体类型不占空间,虽然它有大小,只有实例化后才会开辟相应的空间。四是结构体
2021-07-31 12:26:15 103
原创 C语言字符串函数
C语言中定义字符串的一个问题C语言中一般定义字符串有两种形式,一种是char str[]这种方式只开辟了一个数组空间。另一种char *str这种方式开辟了两个空间,一个指针空间和一个常量区的空间,所以这种方式定义的字符串是一个常量,多在不对其做修改的情况下使用。用相同常量初始化不同数组时会开辟不用空间。例如str1[]={"HELLO"}; str2[]={"HELLO"}; str1 != str2.strlen函数size_t strlen(const char *str);strlen函数
2021-07-30 23:49:18 607
原创 C语言数据类型及在内存中的存储
C语言中的数据类型我们知道C语言中有char,short,int,double等一些内置类型,以及struct,enum,union这样的自定义类型。根据使用情况可以分为,整形,浮点类型,构造类型,指针类型,空类型几类。这是C中最基本的知识。大小端的概念首先在计算机系统中,CPU的编址,寻址和访问内存都是以字节为单位的。以一个十六进制数0x12345678为例,它的12是高权值位,78是低权值位。一个四个字节的连续空间,假设编址为0xF1,到0先F4,如果12,存储在0xF1处,78存储在0xF4
2021-07-27 22:36:08 412
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人