自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(29)
  • 资源 (1)
  • 收藏
  • 关注

原创 数据结构之最小堆

最小堆可以看作是一种优先级队列的实现,有些应用场景需要从队列中获取最小的或者最大的元素,而且不要求数据全部有序,使用最小堆或者最大堆能很好的解决这类问题。最小堆的元素是按完全二叉树的顺序存储方式存放在一维数组中。蓝色数字代表节点元素在数组中的索引位置如上图所示,最小堆的根节点对应数组的第一个元素,后面接着依次从上到下每一层树节点从左往右排列,按照这个顺序将一段线性内存结构映射为一个树结构,并且满足下面的几个性质:用i代表数组下标,n表示数组大小当i为0时,表示树的根节点,没有父节点;节点

2022-05-18 22:15:35 7501

原创 C++实现毫秒级精度定时器

定时器的实现一般需要借助系统提供的超时相关接口,比如select、 条件变量、或者sleep, usleep等,sleep,usleep提供的睡眠功能太有限,无法中途唤醒,这就导致他们其实不适合做定时器中的定时方法。而select和条件变量都可以设置定时时长,而且在中途可以唤醒,精度也很高,因此,可以采用select或条件变量作为定时方法,本文讨论使用条件变量如何实现定时任务。条件变量可以设置超时时间,如果条件变量在没有接收到来自其他线程的条件通知时,将一直阻塞,直到超时。通过这个特性可以按照定时器需要等

2022-05-03 00:14:58 5670 1

原创 使用C++实现一个简单的线程池

线程池类似于内存池,连接池等,在一开始创建好一定数量的线程,当有任务需要处理时,就将该任务丢进线程池的某个线程中处理,而不是每个任务都启动一个线程。使用线程池的好处在于,不需要频繁的创建线程,因为创建线程是一个较耗资源的操作。因此,相对而言一开始创建好线程,要比动态创建线程对性能影响更小。其次,线程池可以更好的将线程管理起来,对外提供简单的接口,内部完成对线程的调度,这也是高内聚的一个思想,将复杂封装起来,对外在满足业务场景的前提下尽可能简单。线程池作为一个独立的非业务模块,任何需要处理多任务的场景都可以使

2022-04-14 23:59:15 2501 1

原创 makefile的使用技巧

从vc6.0到visual studio,编译代码的工作都是由IDE来完成,我们只需要点击编译按钮,即可将源文件编译成库文件或可执行文件,非常方便。到后来,由于跨平台开发和自动构建等需求,转而开始使用CMake作为代码构建的工具,CMake能灵活的组织代码和构建项目,而且跨平台。再后来,工作中发现有些场景下不得不使用makefile进行代码编译。比如,有些系统上未安装CMake工具,而且也不具备安装条件,此时,我们不得不编写makefile来构建项目。makefile的编写逻辑其实很简单,目标:依赖。最终

2022-04-06 23:35:05 743

原创 C语言实现C++多态

C语言实现C++多态C++中多态实现是基于虚函数表实现的,每个具备多态性对象的内部都会有一个隐藏的虚函数表,虚函数表里面的函数指针指向具体的函数实现,可能是父类中的实现,或是子类重写了的方法。C语言没有天然的多态支持,但是按照C++的实现原理,也能写出多态特性的代码。下面代码就是用C实现多态。结构体Animal中有两个函数指针,eat和drink。Cat结构体通过组合的方式包含Animal对象,此时,Cat结构体也间接获得了eat和drink方法,通过Cat结构体实现原本Animal里面的方法。创建一个

2021-11-15 22:31:43 1418

原创 帧同步游戏浅谈

帧同步是游戏中常用的同步方式之一,我们熟知的《王者荣耀》战斗过程中就是用的帧同步。帧同步的原理是什么呢?在我看来,帧同步,其实就是保证不同客户端在相同的帧做相同的操作,一场游戏从开始到结束,每个客户端都跑了相同的帧数,最终都得到相同的结果。这里需要注意:帧同步,同步的是玩家操作,比如某个玩家在第2000帧的时候放了一个技能,那么这个操作需要同步到其他客户端,其他客户端也在2000帧的时候做这个操作,至于技能对周边造成多少伤害,需要由客户端来计算。帧同步的另一个特点:计算任务放在客户端。客户端逻辑就像是一

2021-03-20 00:28:49 929

原创 赋值运算符函数

赋值运算符函数作为类的一个成员函数,主要用于对象之间的赋值。类一般都有默认的赋值运算符函数,然而默认赋值运算符函数只会浅拷贝,无法满足需求,有时还会产生致命错误。如下:class CString{public: CString() : _buf(nullptr) { } CString(const CString& str) : _buf(nullptr) { const int size = strlen(str._buf) + 1;

2021-02-22 23:56:57 1769

原创 std::move的理解和使用

最初接触到std::move,以为std::move具有类似于swap的功能,可以避免内存的拷贝。后来查看资料发现,std::move的实现并没有交换内存的操作。那么std::move是如何避免内存拷贝的呢?看它的实现发现,std::move只是进行了左右值的转换,也就是类型的转换,并没有改变对象本身。这里涉及到左值和右值的概念:左值:简单理解为赋值运算符左边的变量,可以接受右边值,例如 int a = 10; a就是一个左值右值:赋值运算符右边的值,这个值可以是一个变量页可以是一个常量,例如 i

2021-02-21 13:53:45 20502 5

原创 leetcode(14)最长前缀

14. 最长公共前缀这个题目是在多个字符串中寻找最长公共前缀。解体思路有点像冒泡排序的方法,将第一个字符串当成最长前缀串,和第二个字符串判断找出最长前缀串,这个最长前缀串又和第三个字符串判断,找到新的最长前缀串,以此类推,中途如果出现比较不相等的情况,如果是第一个字符不相等,则直接返回“”;否则结束比较,当前找到的前缀即为最长前缀。class Solution {public: string longestCommonPrefix(vector<string>& strs)

2020-10-12 23:01:58 204

原创 leetcode(13)罗马数字转整数

13. 罗马数字转整数这道题目和上一道题目是相反的转换,上一道题目中整数转罗马数字是把整数拆分成每一位,利用罗马数字表示规则从高位到低位拼接即可。那么罗马数字转整数也是一样的道理,从高位到低位(从左到右)拆分每一位整数对应的罗马字符串,然后将每一位整数相加就可以了。例如:“XXVII”代表27,那么需要把“XXVII”拆分成20和7,从左往右“XX”对应20,VII对应7,则“XXVII”对应的整数值为20 + 7,即27。通过例子可以看出来,解题思路很简单,就是识别每一位整数对应的罗马字符串,

2020-10-09 22:17:09 107

原创 leetcode(12)整数转罗马数字

12. 整数转罗马数字这道题是将十进制的整数转换成罗马数字表示,由于罗马字母的限制,只能转换1到3999之间的数。根据题目描述以及示例,可以发现转换原理很简单,就是将十进制对应位上的数字转换成罗马对应的字母就可以了,对应关系如下:字符数值I1V5X10L50C100D500M1000例如转换234为罗马数字,拆解每一位的值,找到对应的字符即可,234分解为:200 “CC”30 “XXX”4

2020-09-29 22:40:26 120

原创 leetcode(11)盛最多水的容器

题目链接:盛最多水的容器拿到这个题目,结合示意图看了下,基本上就是一个给定一组宽,高,求最大面积的题目, 同时很容易让人想到“木桶原理”,即,最短的那块板决定木桶的容量。题目给出了一个数组,里面存放所有的高度值,宽度值可以通过计算数组索引的差得到,因此任意两个值之间面积值为:const index1,index2;// 数组索引,index2 大于 index1const int height1 = heightArray[index1];const int height2 = heightArr

2020-09-28 09:04:02 107

原创 CMake 编译选项设置

在CMakeLists.txt中可以通过修改CMake内置的环境变量来改变C或C++的编译选项.编译选项相关的CMake 变量如下:CMAKE_C_FLAGS = CMAKE_C_FLAGS_DEBUG = -gCMAKE_C_FLAGS_MINSIZEREL = -Os -DNDEBUGCMAKE_C_FLAGS_RELEASE = -O3 -DNDEBUGCMAKE_C_FLAGS_RELWITHDEBINFO = -O2 -g -DNDEBUGCMAKE_CXX_FLAGS = CM

2020-09-10 18:47:05 23264

原创 Linux C/C++程序崩溃bug调试方法

C,C++程序最常见的崩溃问题就是内存问题,内存越界,访问空指针,野指针等都会造成程序崩溃。Linux系统中当程序运行过程中出现非法操作,系统会先发送对应的错误信号,每种错误信号都有默认的处理方式,比如,当我们给一个空指针赋值的时候,系统会检测到这个内存错误,然后向进程发送SIGSEGV信号,该信号默认的处理方式是退出进程,这种情况下,只能看到进程挂掉,但无法定位错误。当出现这种问题的时候一般往往很难查找原因,下面介绍两种方式定位bug。方法一:捕获系统信号Linux操作系统提供了一组接口可以修改信号对

2020-09-10 18:45:32 4991

原创 有穷自动机NFA和DFA的概念理解

有穷状态机(finite automata)分为不确定的有穷状态机(Nondeterministic Finate Automata,NFA)和确定的有穷状态机(Deterministic FiniteAutomata,DFA)。NFA和DFA都是有限状态机,一个是不确定的,一个是确定的,这里的确定和不确定应该这么理解呢?其实确定和不确定指的是一个状态到另一个状态的输入是否是确定的。拿NFA和DFA的状态转换图来说就是:NFA同一个符号可以标记离开同一状态的多条边,并且e也可以作为标记;DFA同一个符号

2020-06-03 08:56:32 5441

原创 KMP算法分析与实现

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。KMP算法的核心是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。KMP算法的时间复杂度O(m+n)。《百度百科》在《编译原理》第二版,第三章讲到了KMP算法,该算法可以以O(m+n)的时间复杂度从一个字符串中找到一个关键字。首先看一个常规的查找子串的算法:bool findSubstring(const .

2020-05-14 22:21:45 537

原创 Visual Studio 2019 创建CMake Linux项目

之前我有一篇文章讲的是使用Visual Studio 2017 创建Linux C++ 项目(使用VS2017调试Linux C++代码),使用IDE的好处就是方便编码和调试。工作中也一直以这种方式开发Linux平台的项目,使用了大概两年多,总体上可以满足开发需求,但是还存在一些bug,或者说令人不太满意的地方。问题1:本地文件和远程同步问题项目中如果有脚本或者配置等文本文件,由于这些文件不参...

2020-04-25 00:03:48 3029

原创 加减运算 “中缀表达式”转“后缀表达式

加减运算 “中缀表达式”转“后缀表达式”我们将a + b 或 a - b这种形式称为中缀表达式,将a b + 或 a b -称为a + b 或 a - b 所对应的后缀表达式。a + b - c 的后缀表达式为 a b + c -,转换过程如下:步骤一:(a b +) - c # 先转换 a + b => a b + 并将a b + 当成一个整体步骤二:(a b +) c - ...

2020-04-17 23:52:47 777

原创 使用Docker+Visual Studio 2019搭建Linux C++开发环境

使用Docker+Visual Studio 2019搭建Linux C++开发环境从Visual Studio 2017开始,Visual Studio就已经支持跨平台Linux项目的开发。使用它作为开发工具可以很方便的进行开发,调试。它的跨平台开发原理是这样的,通过建立一个Linux工程,这个工程在编译时,拷贝本地代码到远程Linux环境,然后在Linux环境下编译,实际上是一个远程编译的...

2019-08-17 22:43:02 4868

原创 Linux下安装禅道项目管理系统

Linux下安装禅道项目管理系统下载xampp环境$wget https://sourceforge.net/projects/xampp/files/XAMPP%20Linux/7.1.11/xampp-linux-x64-7.1.11-0-installer.run 实际下载可能会失败,需要多尝试几次安装xampp环境把下载的xampp包放/opt/下面,给xampp包添加执行权限,然后执

2017-12-16 20:59:27 667

原创 使用VS2017调试Linux C++代码

VS2017版本现已支持开发Linux项目,就是在VS上面写代码,而编译和运行是在Linux环境下。使用场景:假如,代码最终是运行在Linux系统上,而我们又不想在Linux环境下写代码,想借用VS强大的开发功能做开发,那么就可以在VS上面创建一个Linux项目。设置:项目建好之后,需要设置远程连接,指定代码最终要运行的目标平台。编译:项目编译的时候,VS会把代...

2017-11-12 17:26:02 16681 11

原创 glDeleteTextures函数对内存的优化

函数介绍void glDeleteTextures( GLsizei n, const GLuint * textures);从字面意思来理解,该函数是用来删除纹理的。通过官方文档是这样介绍的: glDeleteTextures deletes n textures named by the elements of the array textures. After a texture is d

2017-08-21 22:57:24 12262 9

原创 Android studio 创建一个JNI工程

环境:Android studio 2.1.2android-ndk-r10e创建一个jni工程:首先新建一个Android项目,刚刚建好的项目目录结构如下所示: 然后设置NDK路径,在local.properties文件中加入一行ndk.dir=你自己ndk所在路径新建的项目默认是不包含jni的,因此我们要手动增加一个jni目录 如图,我们在app目录下面创建一个jni目录,这个j

2017-07-29 19:41:21 1962

原创 OpenGL ES 纹理贴图

顶点坐标和纹理坐标在没有投影矩阵的情况下,我们要传给顶点着色器的坐标值都在(-1,1)范围内,超出了这个范围将不可见。因此对于一个四边形的绘制,我们经常看到下面的顶点坐标: GLfloat vertices[] = { // Positions // Texture Coords -0.5, -0.5, 0, 0.0, 0.0, //左下

2017-07-23 16:57:58 859

原创 Longest Palindromic Substring 算法总结

Longest Palindromic Substring 即寻找一个字符串的最长回文子串,这个问题是leetcode上面的一个题目,刚开始自己做的时候用了一个可能是效率最低的方法去实现,但是由于leetcode的代码提交时会评价代码的执行效率,因此,这种实现没能通过。仔细看一下代码的时间复杂度几乎是O(n³),所以慢是很自然的。下面是这个算法的实现:string longestPalindrome

2017-05-23 13:53:07 498

原创 利用函数指针实现父类函数调用子类函数

父子类关系对于继承关系中的父类和子类,我们可以说子类是父类的一种,子类继承了父类的属性和行为。因此,子类可以访问父类的所有非私有成员。相反,父类一般情况下是不能访问子类成员的。然而,我们可以通过一些方法间接的实现父类访问子类,即父类函数访问子类函数。方法一利用多态机制,一个指向子类的父类指针或引用,当调用被子类重写的虚函数时,实际上调用的是子类函数,这是通过多态的方式来实现父类调用子类,该方法需要一

2017-03-29 01:11:11 16193 1

原创 虚析构函数

析构函数C++语言中,每一个类都有一个默认的或者我们自定义的析构函数,析构函数的作用就是当对象销毁的时候做一些资源释放,一般我们都是这样用的。然而,有时候可能由于疏忽或者对语法不熟悉,写出来的程序最终当对象销毁的时候,析构函数并没有被调用。这种情况是存在的,下面我们举一个列子:class Base{public: Base(); ~Base(); int membe

2017-03-19 23:35:48 420

原创 OpenGL 坐标系统 投影

为了将坐标从一个坐标系变换到另一个坐标系,我们需要用到几个变换矩阵,最重要的几个分别是模型(Model)、观察(View)、投影(Projection)三个矩阵。比如一个空间中物体的移动,旋转,缩放或叠加在一起的复合变换都可以用一个4×4的矩阵乘以找个物体的所有顶点来实现,这就是模型矩阵;当我们想在某个特定的位置和角度去观察三维空间中的物体的时候,我们就可以用一个矩阵去乘以找个物体的所有顶点来实现,

2017-02-27 23:16:14 1112

原创 OpenGL 帧缓冲

概念:帧缓冲可以理解为着色器渲染之后将要显示在窗口上的所有颜色信息,深度信息和模版信息的数据集合,这些数据都保存在内存中,最后经由显示器显示在窗口中。窗口都有一个默认的帧缓冲,来存放最终要显示的所有信息。OpenGL允许用户自定义帧缓冲,用户自定义帧缓冲有什么用呢?试想,如果你想实现这样一个功能,就是希望能够在最终显示在窗口中的画面的基础上再对每一帧图片进行处理,也就相当于动态的后处理,对于这种需求

2017-02-24 23:20:31 2134 1

eglDemo Android

Android native层 opengles绘图

2017-07-20

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除