- 博客(41)
- 收藏
- 关注
原创 printf 打印占位符
0. 打印包含占位符的字符串,而却没有提供参数时,会打印出一个魔力数字。2. 打印时用占位符显式指定打印内容。1. 用 % 来转义 %。
2025-02-22 14:33:20
214
原创 wsl 下执行 systemctl 报错:Failed to get D-Bus connection: Operation not permitted
sshd 启动慢也是一样的原因,有一次笔者启动虚拟机后过了几分钟后才启动 sshd,结果瞬间就启动了,另外在关闭 sshd 后,也能马上启动完成,因此怀疑不是 SSH 的问题,转而怀疑是 systemctl 的问题。重启 wsl ,此时 sshd 已经是秒开的了,至于虚拟机启动慢,相比起 5min,,发现无该应用,由于不确定什么 systemd 服务可以关闭或删除,故作罢。取消使能 systemd 后开机速度正常,当然 sshd 也不能启动了。使能 systemd 选项后,虚拟机开机很慢,约 10s。
2024-07-20 02:20:03
863
原创 虚表指针初始化
构造函数中能调用虚函数,也能确定虚表指针的存在。能否通过下面的结果确定虚表指针在构造函数调用前就初始化好了?欢迎赐教class A{ typedef void(*fp)();public: virtual void foo() { cout << "virtual void foo()" << endl; } virtual void bar() { cout << "virtual void bar()" << e..
2021-12-28 22:20:37
659
1
原创 继承构造函数
无论子类没无定义自身的默认构造函数,都会调用父类的默认构造。如果子类没有定义自身的赋值构造函数,会自动调用父类的默认构造函数。若子类定义了,需显式通过初始化列表才能调用父类的赋值构造函数。如果子类没有定义自身的拷贝构造函数,会自动调用父类的拷贝构造函数。若子类定义了,会自动调用父类的默认构造函数。轻松的记忆方法是在初始化列表写上想调用的父类构造函数。class A {public: A() { cout << "A ctor" << endl;.
2021-12-02 19:38:58
1032
原创 2021-11-07翻转链表(带头结点)
struct linknode{ int val; linknode* next;}void reverselinklist(linknode* root){ if(nullptr==root)return; linknode* pre=nullptr,cur=root->next; while(cur){ cur->next=pre; pre=cur; cur=pre->next; }.
2021-11-07 20:11:10
141
原创 字符编码笔记
码位:每个字符在字符集中的编号,如在ASCII字符集中,空白符是编号0,回车是10,以此类推。当字符数量很大的时候,使用分区的方式进行管理,比如GB2312字符集,有94个分区,每个分区内有94个位,这样每个字符的码位就不是从0开始数的,而是分区xx中的xx位。编码:但是这个码位并不是最终在计算机中存储的数据。而是要根据码位以及相应字符集的转换规律,计算得出的数字才是真正的字符集编码。而且为了让计算机能区分不同的编码,各个标准都会设计使得转换后的编码的数值位于不同的区间,比如ACSII码是小于等于1
2021-10-26 21:05:53
138
原创 repeat语句最后一行输出两次
fetch在获取集合最后一行后,再获取一次才会触发02000,这样会导致循坏多进行一次,虽然集合已经到末尾,fetch失败,但其他操作仍然会进行,获取的内容和上一次相同方法是在获取后马上进行标志符判断,一个是if判断,一个是在repeat前先进行一次fetch,使得循坏体内fetch放到最后DELIMITER @@CREATE PROCEDURE processsalary()BEGINDECLARE `max` DOUBLE(10,2);DECLARE `min` DOUBLE(.
2021-08-27 23:01:47
187
原创 抽象工厂
工厂模式以此只能传递一种工厂(虽说可以改接口),若模块中需要多个对象,则需要传递多个工厂,可以把关联的几个工厂抽象合并为一个工厂。class Gpu{public: virtual void work() = 0; virtual ~Gpu(){}};class Gpu_Intel :public Gpu{public: virtual void work() { cout << "Gpu_Intel working" <&l.
2021-08-17 15:14:07
96
原创 工厂方法
构造对象一般用new,但是new后面必须是确定的类型,后续需求变了可能要改new这段代码,不稳定。工厂方法是将构造对象的类型交给函数使用者决定,不在函数中构造,而是通过接口传递。但也可以直接传递对象啊,为什么还要引入工厂来构造对象?class Object{public: virtual void foo() = 0; virtual ~Object(){}};class Object_A:public Object{public: virtual void .
2021-08-17 01:51:59
93
原创 桥模式
和装饰器模式类似,不同点在于装饰器模式是用于追加功能的,桥模式是从现有的库中调用方法,库是独立于实现化角色的,因此后者不用继承自前者。核心还是传递指针,然后调用方法。比如从几个不同平台的库中任意调用及组合方法,参考下例class Implement {public: virtual void func_1() = 0; virtual void func_2() = 0; ~Implement(){}};class Implement_1 :public Im.
2021-08-17 01:22:02
138
原创 装饰器模式
对模块追加功能,比如追加步骤,几行代码,不影响原有功能时使用此模式。对现有的n个模块追加m种功能,且功能可以按排列组合使用,直接在原有模块上派生会产生很多子类,而且代码重复。思路:将追加的功能单独抽象成类(装饰器类),并传入原模块指针,这样就能在实现新功能时调用原模块的方法。除此之外,装饰器类还要继承模块类型,继承了之后能够实现追加 功能的复用,原模块的构造器也能用装饰器类初始化;还能重写方法,不用定义新的方法,调用者不用修改代码;声明对象时也能用统一的形式。下面以扩展component中的f.
2021-08-17 00:41:58
81
原创 bind2nd使用
首先要继承binary_function类,而自定义的函数对象必须是常函数?template<classF,classT>std::binder2nd<F>bind2nd(constF&f,constT&x);从定义看接收的函数对象是常对象,所以要写成常函数。less<T>()也是常函数template<class T>class A :public binary_function<T,...
2021-08-04 13:08:35
240
原创 c++继承内存分布
一般子类继承父类,子类的虚函数会在父类的虚函数表中覆盖同名虚函数,子类中新的虚函数会添加到父类的虚函数表末尾。多继承时,将继承所有父类的虚函数表并覆盖,而子类中新的虚函数会添加到第一个声明的父类的虚函数表末尾。虚继承时子类除继承继承父类的虚函数表,用重写的虚函数覆盖父类的同名虚函数。子类新的虚函数会填入由自己创建的虚函数表中。sizeof(A):vftptr1+char[2]=8,考虑内存对齐,32位vftable1=A::aa()sizeof(B)+vbptr1+char[2]+...
2021-07-31 10:32:29
470
原创 c++异常对象声明周期
演示了抛出前及抛出时构建的对象的释放时机。从结果看,抛出前构建的对象会在异常抛出后捕获前析构。抛出时构建的对象在捕获异常处理完后析构。class A {public: int _a; A(int a=0) { cout << "A construct=" << a << endl; _a = a; } A(const A& a) { cout << "A ..
2021-07-29 01:58:27
115
原创 哈希表部分实现
只做了增删查,基本的数据类型和字符串template<class T>class HashMap { template<class T>//基本数据类型 struct item { T _value; item<T>* _next;//用链表,无需扩容 explicit item(T value = 0) :_next(nullptr), _value(value){} }; .
2021-07-25 05:43:55
128
原创 桶排序
要知道数据范围,然后定划分多少个区间,暂时不支持负数?template<class T>void my_printAry(T* a, int len) { if (a == nullptr || !len)return; for (int i = 0; i < len; i++)cout << a[i] << " "; cout << endl;}template<class T,int NUM>//分成N..
2021-07-23 23:59:41
82
原创 计数排序
void countSort(int* a, int len) { if (a == nullptr || !len)return; int min = a[0], max = a[0]; for (int i = 1; i < len; i++) { if (a[i] > max)max = a[i]; else if (a[i] < min)min = a[i]; } int* cnt = new int[max.
2021-07-23 21:34:23
86
原创 b树 c++
#include<queue>template<class K,int M = 3>struct BTreeNode {//M阶b树 K _key[M];//从0开始,M-1用于溢出时暂时存放 BTreeNode<K, M>* _sub[M + 1];//子树指针,从0开始,M+1暂时存放 BTreeNode<K, M>* _parent; size_t _keynum;//关键字个数 BTree...
2021-07-22 20:57:51
120
原创 平衡树AVL
需要注意的是删除结点,有时删除结点不会影响此结点所在层的平衡,如删除50,会在递归返回时判断出40的平衡受影响当删除30时,用31补充。30所在层的平衡已经被破坏,需要马上调整 40 30 70 2031 5019template<class T>struct BinTree{ T data; BinTree* left, * right; ...
2021-07-16 22:16:01
89
原创 外排序简单实现
就是文件读写+败者树实现,交作业了从特定命名格式的文件(temp0.txt,temp1.txt ...,temp%d.txt)中读取数据然后在内存中排序,再输出到另一个文件败者树初始化操作有部分代码与后面循坏排序的代码重复,但不能合并,必须先单独初始化。而且loser数组必须初始化为data数组中最小值的索引,然后再调用调整函数循环排序的结束条件:排序得出的最小值所在文件已经访问到底(EOF)。当第x个文件访问完毕,在败者树中进行比较时,将视为一个很大的值,一直被压在loser[1-i]中,不.
2021-07-13 17:13:18
175
原创 基数排序
升序时桶数组和下标绑定,不像其他排序算法那样容易从升序改成降序void radixSort(int* a, int len) { int bit = maxBit(a, len), k, radix = 1, bucket[10] = { 0 }; int* temp = new int[len]; for (int i = 1; i <= bit; i++) {//分别按个位,十位,百位。。进行排序 for (int j = 0; j < 10.
2021-07-08 22:52:49
76
原创 堆排序
一般用数组来表示堆,下标为 i 的非根结点的父结点下标为(i-1)/2。下标为 i 的左右子结点分别为 (2i + 1)、(2i + 2)构建堆的思路:n个元素的数组能划分成n/2个子堆进行管理和调整,从下往上调整,但下面的子堆可能受上面的堆调整的影响,是否需要调整子堆,要看移动的结点是否为“叶结点”,或者说是否有左右子结点各个子堆调整。为保持根是最大/最小值,与子结点执行交换操作受影响的下级堆。先判断以被交换的子节点为根的下级堆是否被破坏,是,就重新调整,并再判断下下级堆有无被破坏,一直.
2021-07-07 23:48:02
111
2
原创 直接选择排序
有点像冒泡,但这个是先找到位置然后直接交换,每次确定一个最小的元素,冒泡是一边移动一边比较,每轮确定一个最大/最小的元素。可以改进下,同时找最大和最小的void selectSort(int a[], int len) { for (int i = 0; i < len-1; i++) {//比较n-1次 int min = i; for (int j = i + 1; j < len; j++) {//找最小的元素 if.
2021-07-07 17:06:00
63
原创 希尔排序
这个算法原理不难,结合示意图理解。主要思想是通过增量将数组分成多组并进行排序,后续增量减小,排序完成度增加。但不知道为什么用swap也能完成排序,用swap也不太符合排序的过程,只是交换 j 和 j-gap 位置,没有将前面的增量序列中的(j-2gap,j-3gap,...)完全排序void shellSort(int* a, int len) { for (int gap = len / 2; gap >= 1; gap /= 2) { //cout <<.
2021-07-07 01:47:28
83
原创 插入排序
比直插有所改善,直插是一次次的进行判断移动。可以先找出插入的位置再移动,其实就是在有序数组中找位置void InsertSort(int a[], int len) { int i, j, low, high, mid, temp; for (i = 1; i <= len - 1; i++) {//下标1~len-1都需要排序 temp = a[i]; low = 0; high = i - 1; while (low &l.
2021-07-06 20:04:43
70
原创 查找数组中重复的元素
数组a共n+1个元素,元素取值范围1~n,返回数组中重复的元素之一题目条件限定了数组中一定有重复元素,可以对每个可能的取值1~n计算出现次数。或者划分取值范围为1~m,m+1~n,计算两个取值区间在数组a中出现的总次数,如果范围为1~m的统计次数大于m,说明有重复。但如果有某个符合取值范围的元素数组中出现了0次,那么可能为某个重复次数为两次的元素提供了隐蔽条件,这个重复的元素也无法找出,但说明另一个取值范围内也有元素是重复的int cntRange(int* a, int len, int s.
2021-07-06 17:24:06
2030
原创 二叉树遍历 非递归
先序和中序类似,不同点在于访问结点的时机。后序较难,双栈的较容易,常规思路的较难,要多回顾vector<int> preorder(TreeNode* root){ if(!root)return {}; vector<int>v; stack<TreeNode*>s; s.push(root); while(!s.empty()){ root=s.top(); v.push_back(root->val); s.pop();//后面.
2021-07-05 17:26:31
81
原创 归并排序
主要是对数组的操作区间要明确,网上很多版本,有的直接传数组长度然后就开始递归了,有的划分左右区间时不用mid+1,最后把temp数组复制到原数组也有各种写法。总之找到一个自己试验过的版本就行void _merge_sort(int a[], int* temp, int l, int r) {//lr闭区间 if (l >= r)return;//只有一个不用再分 int mid = (l + r) / 2; _merge_sort(a, temp, l, mid);.
2021-07-04 23:54:13
66
原创 算法题 TOPK问题
牛客网大佬的思路,自己翻译下int partition(vector<int> &input, int l, int r) { int pivot = input[r-1];//以最后一个为基准值 int i = l; for (int j=l; j<r-1; ++j) {//除去最后一个外,进行比较 if (input[j] < pivot) {////小于最后一个的移到前面 .
2021-07-04 16:03:14
100
原创 快排实现和细节
网上的快排很多,差别主要在R侧的while结束发现小于/大于基准值的元素并将其移动到L侧时是否带有++/--的操作,因为已经确定了位置,所以用L++来跳过似乎无可厚非。对于本身是有序的序列,第一个while已经将R减到0了,排序应该结束。但是由于没有进行判断,所以会执行后面的L++,从而出现a[0]=a[1]的操作void quickSort(int* a, int i, int j) { if (i >= j) return; int l = i, r = j, key.
2021-07-03 21:13:15
110
原创 算法题 二叉树中两个结点的最近祖先
代码比较简单,主要理解思路,用dfs搜索,直到找到目标结点或者为空然后返回结果。这两个结点的位置有几种情况:在某个结点的两侧,或者一个节点在另一个结点的子树中。第一种,能够递归地找到左右的两个结点,然后也递归地返回到最近的祖先第二种,由于dfs的结束条件是找到某一个目标结点,而后面的子树不再找了,此时算法会继续遍历剩余的子树,肯定是找不到的,因此返回这个找到的结点就行了int lowestCommonAncestor(TreeNode* root, int o1, int o2) { .
2021-07-02 15:14:20
152
原创 多态相关细节
多态实现基于虚函数表,具体做法是同名函数的覆盖,而且不是引用/指针指向基类就不能实现多态,就算是实现多态,这个基类也只能访问本类的成员void test02() { class Base { public: int b; int* p=nullptr; virtual void Test() { std::cout << "base" << std::endl; .
2021-07-02 12:06:57
100
原创 函数中定义函数的方法
#include<iostream>#include<boost/function.hpp>using namespace std;int g_func(int a, int b) { return a + b;}void test01() { boost::function<int(int, int)> func; func = &g_func; cout << func(1, 2) << en...
2021-07-02 10:13:46
872
原创 LRU实现
动态地维护容量一定的hash表,访问频率高的保留,反之则视剩余容量决定是否保存,一般的hash表直接记录各个键值对就行了,但多了容量有限的情况,要做一点改动。这里可以通过双端链表来保存键值对,key被访问了就移动到链表头部,对应“访问频率高”的情况,而原本的hash表就不能简单的存储键值对了,此时应该记录链表节点的指针,毕竟链表中已经记录了键值对。为什么用双端链表,因为移动结点方便。思路厘清了剩余的就是基本的实现了,就是双端链表和hash表的操作#include <vector>.
2021-07-02 10:11:29
55
原创 dfs 迷宫问题
从第一个状态开始,沿着剩余的符合条件的路径继续搜索,直到找到解/满足结束条件为止比如遍历迷宫,从起点到终点,每次可以上下左右移动,移动了再以此为据点再上下左右移动,就这样一步步移动到终点,但是也要注意重复绕路的情况,这样是会造成死循环的,因此可以用一个数组记录是否走过这个坐标第一个测试用例不用全局声明void test02() {#define max_line 50#define max_col 50 int line = 5, col = 4, minstep = max..
2021-07-01 17:58:00
406
1
原创 动态规划 01背包问题
目前看到的01背包问题都不是递归方法解决的,应该是数量+容量的组合造成的特殊性质?重点是理解状态转移方程。容量够了,可以选择放不放,如果放了会占据一定的容量,而剩余容量用来放其他的。另外还有一个延申的问题,回溯所选组合。这里是逆序回溯,从最终状态dp[num][c]开始,用最大容量和物品[num-1]所需的容量比较,确定能放入再进行判断:是否有放入?有无放入物品i就看除去物品[num-1]之后的收益是否等于放了之后剩余容量的最大收益。其实就是上面的思路template<class T.
2021-06-30 14:30:49
78
原创 使字符串成为回文串插入的最少字符数
本文仅讨论动态规划的方法。状态转移方程容易理解,递归版本不难看懂。自底而上的版本不强求,以实际案例跟着推演一遍,有点感觉即可备忘录递归class my_2DAry {public: //typedef typename T value_type; T** pp; int m_l, m_c; my_2DAry(int l, int c):m_l(l), m_c(c) { pp = new T* [l]; for (int i..
2021-06-29 11:01:22
303
原创 动态规划 过河问题
核心思路:先将n个人的过河速度从小到大排列:a[i],1<=i<=n尽量让速度相近的两个人过河尽量让速度最快的人返回送手电筒
2021-06-26 19:00:48
601
2
原创 c++ traits提取数据类型2
使用说明:用户使用的是func函数,可以传入的参数有两类,class和基本类型当传递class参数时,需要通过classunknow_class封装然后传入,但不支持模板类当传递基本类型参数时,以指针形式传递详情见test03()#include <iostream>using namespace std;//template<class T>//class A {// T* m_a; //注意指针成员//public:// type..
2021-06-24 23:07:19
160
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人