- 博客(19)
- 收藏
- 关注
原创 shared_ptr原理和简单实现
智能指针不是指针,是对象,但是当作指针来用。 原理:对每个所指目标保存一个额外的引用计数,使多个指针可以动态的共享所指对象,即指向一个对象的指针可以增加和减少,当且仅当对象的引用计数为0时才由智能指针调用delete,释放堆上的内存。 思路:交给系统来释放内存。智能指针在栈上,所指对象在堆上,系统自动对栈的对象调用析构函数,这时再由智能指针在析构函数里delete,就可以安全释放内存。 tips:引用计数不能是成员变量也不能是堆上开辟的空间,而是静态变量,存储映射关系。 具体实现: #include <
2020-10-17 18:28:25
788
原创 单链表归并排序
通常,因为单链表不可回头,所以排序可以选择选择排序,冒泡排序。如果在nlogn复杂度下完成,那么可以使用归并排序,思路如下: 1.把链表用快慢指针遍历,找到链表中点。 2.在链表中点把链表断开,分成两个链表,每个链表再分解。 3.当不能分解时,把两个链表合并,变成一个链表。 4.继续向上合并,直到链表唯一。 //单链表排序(要求时间复杂度nlogn)(归并排序) typedef struct node { int value; struct node *next; }Node; Node *create
2020-09-06 17:53:35
675
原创 c++用链表实现一个简单的内存池
如同进程池和线程池一样,使用内存池也是为了提高效率。 如果不使用内存池,那么频繁的malloc小字节内存不仅会降低运行效率,而且也会产生内存碎片,因此合理使用内存池会让进程执行地又快又好。 简单的内存池代码如下: //用链表实现一个简单的内存池 template <class type> class memory_pool { public: memory_pool() :link(Node()), flag(Flag()) {} //释放空间 ~memory_pool() {
2020-08-10 00:07:58
629
1
原创 c++中new的三种用法
测试类: struct test { test(int size = 1) { ary = new int[size]; } ~test() { delete[] ary; ary = nullptr; } int *ary; }; 用法1——当作关键字用,会做2步:1.先开辟空间。2.后调用构造函数。 test *a = new test(10); 用法2——当函数用,相当于malloc,单纯的开辟空间。 test *b = (test *)operator new(size
2020-08-02 14:59:25
3493
2
原创 模版特化和作为萃取器的应用
模版大致分为三种版本:普通版本、部分特化版本、全部特化版本。 普通版本: template <class type> void function(type t){} 部分特化版本: template <class type> void function(type *t){} 全部特化版本: template <> void function<int>(int t){} 其中,全部特化版本只能接受一种参数,范围最小;部分特化版本可以接受一类特定的参数,范围
2020-08-01 16:33:06
150
原创 旅行者售货员问题回溯法
不赘述题目了。思路是回溯法,具体如下: 假设城市=4,出发地=1城市,那么所有可能如下: 1->2->3->4->1 1->2->4->3->1 1->3->2->4->1 1->3->4->2->1 1->4->3->2->1 1->4->2->3->1 可见,本质是对中间三个城市全排列。剪枝方案如下: 先初始化一个最低成本。回溯时计算每一步的成本,如果当前成本比
2020-07-31 17:53:32
1321
原创 n皇后问题回溯法
回溯法类似于穷举法,不过一边穷举一边剪枝,减少计算量。 以3皇后为例来说明穷举法和回溯法的异同: 穷举法: 回溯法: 可以看到,每走一步,回溯法都会判断一下,对于已经错误的情况就不往下走,因此回溯法快一些。 回溯法代码实现: //n皇后问题 #define NUMBER 7//皇后个数 int sum = 0;//解个数 void display(bool chess[NUMBER+1][NUMBER+1])//打印n皇后位置 { for (int row = 1; row <= NUMBER;
2020-07-30 20:04:53
576
原创 哈夫曼树和哈夫曼编码的实现
对于题目和规则不做赘述,进入正题: 要点: 1.逻辑上哈夫曼树是树结构,但程序的物理结构是数组。 2.树构建好后,规定一下左右是0还是1,然后遍历树的每条路径,即可得到每个数据的编码结果。 代码如下: //哈夫曼编码 typedef struct mesage//在优先级队列中用到的结构体 { mesage(int index = 0, int weight = 0) :index(index), weight(weight) {} int index;//下标,用来标识是哪个叶节点 int w
2020-07-29 01:08:20
736
原创 矩阵连乘动态规划
题目我就不赘述了,直接进入正题: 假设有矩阵1,2,3…n 核心思路是——在[1~n]之间每个位置都做一次划分k,最小结果=先算[1-k]和[k+1-n]两部分最小乘积+最后两个矩阵乘积次数。 矩阵[1-n]一共要划分n-1次,相当于一刀一刀挨个儿切过去,每个子问题同样如此,时间复杂度为n^2。 可以看到,问题划分为小规模时是分治的思想,但两个小规模之间数据会重复计算好多次,因此采用动态规划,需要中间结果和辅助标记两个二维数组,用空间换时间。具体代码如下: //求矩阵连乘 void function(int
2020-07-27 19:54:47
456
原创 01背包问题动态规划
问题我就不描述了,直接说步骤。 假设背包空间是space,物品个数是number。物品重量是weight,物品价值是value。 核心思想——缩小规模,寻找递归表达式。 背包空间space下装number个物品的最高价值为: 1)如果第number个物品太重,背包为空也放不下,那么规模缩小为——空间space下装number-1个物品的最高价值。 2)如果第number个物品能装下,那么分两种情况: 1>不装,那么同1)一样,规模缩小为——空间space下装number-1个物品的最高价值。 2>
2020-07-26 16:53:43
748
原创 c++中的运算符重载和衍生的思想
运算符重载的概念我们并不陌生,指的是一个运算符在不同环境下有不同的含义。在c语言中就有运算符重载了,只不过不能程序员自定义而已。例如 * 在两个数字之间时意味着乘号,在一个地址的左边时意味着解引用。 在c++中引入了类和对象,使程序变得更加复杂。为了阅读程序方面,简化按键次数,c++可以自定义运算符重载了。 c++一般对类设置运算符重载,使自定义类型满足和内置类型相同的逻辑。比如设计一个复数类,它可以像整型一样"±*/"等做运算,比调用函数更容易被人理解。 运算符重载可以重载单目和双目运算符,不能重载三目运
2020-07-25 12:52:15
273
原创 辗转相除求两个数的最大公约数
辗转相传求两个数的最大公约数 #include <math.h> //欧几里得辗转相传求两个数的最大公约数 int function(int a, int b) { if (0 == a || 0 == b) return 0; a = abs(a); b = abs(b); if (b > a) { int tmp = a; a = b; b = tmp; } //辗转相除——(b,a mod b)->(a, b) while (b != 0) {
2020-07-11 11:55:49
155
原创 linux中su命令的实现
linux中su命令的实现 //su.c #include <stdio.h> #include <sys/types.h> #include <string.h> #include <unistd.h> #include <termios.h> #include <shadow.h> #include <assert.h> #include <pwd.h> #include <stdlib.h>
2020-07-08 23:59:04
1076
1
原创 C++中类的编译顺序/过程及注意事项
C++中类的编译顺序/过程及注意事项 结论在前: 类的编译分4步: 1.类名 2.成员名称 3.成员函数的返回值和形参 4.成员函数的函数体 注意事项:尽量将类的声明和实现分离。 以下面一个简单的例子说明注意事项: class Test; class Test2 { public: Test2(Test* p):ptr(p) {} int getTestValue(); private: Test* ptr; }; class Test { public: const Test2 generate
2020-06-06 20:16:36
2626
1
原创 笔记本电脑选购参考因素
本文为个人观点,仅供参考,如果能帮到你些许,那再好不过了。 结论:不盲目追求价格,要按需购买。(不差钱例外) 笔记本电脑品牌、型号、套餐多种多样,选择适合自己的着实需要飞一番功夫,以下是几点主要的参考因素。 新旧问题:一般来说,买电脑应该买新不买旧,但新电脑普遍变得更薄更轻便,拓展性变弱(内存1可能会焊在主板上,空间可能不足拓展大容量机械硬盘,CPU可能无法更换,接口可能很少需要拓展坞等等)。如果...
2020-03-01 22:37:37
713
原创 运算符重载和转换构造函数相等的情况
运算符重载: 发生在类类型中,目的是让表达式看起来更加自然,简化程序员工作量。但本质是函数调用,实质并没有简化。 例如创建复数类Complex,两个复数类进行加法。 这时不能把自定义的两个类直接相加,可以写一个成员函数: Complex Complex::plus(const Complex tmp); 加法是使用频繁最高的,这意味着程序员会频繁地调用函数,要多敲好些键盘——这对程序员来说是会心一...
2019-11-20 23:44:46
422
原创 以自制MyArray对象为例说明对象的概念
C++不建议使用内置数组,提供了功能强大的array和vector。因为内置数组有诸多不便:没有下标越界检查,对两个数组而言不能用==,!=,=等运算符,不能把一个数组赋值给另一个数组等等。而array和vector又有些复杂,自带几十个函数,容易让人看花了眼。为什么我们不自己实现一个精简的数组对象呢? 让我们我们模仿array,创建一个自己的int数组"MyArray"对象。先看看测试和运行效果...
2019-10-15 12:43:50
443
原创 统计长整型数字逐位数字的常用方法
当我们看到123,233,66666之类的数字时,人眼读入数字的逻辑是从左往右。当需要检查数字有多长时,对于短数字,我们能一眼看出。对于长数字,则需要从从左到右,仔仔细细心中默念,眼中默看。 对于计算机而言,处理数字同理。这里有两种通常方法,一是从高位到低位处理,二是从低位到高位处理。 以123456789为例,如果计算机选第一种,从高到低。得到第一位1则需要123456789/(10的8次方)=...
2019-10-12 12:24:21
754
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅