<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[暗色光的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/qq_44859952</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; qq_44859952]]></copyright><item><title><![CDATA[通俗易懂的图解二叉搜索树、AVL树和红黑树]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/125647843</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/125647843</guid><author>qq_44859952</author><pubDate>Wed, 06 Jul 2022 21:21:02 +0800</pubDate><description><![CDATA[搜索是一种很常见的需求，当数据较多时，如何找到目标对象时，即需要搜索查找。
那么如何快速找到目标呢，最朴素的思想就是暴力查找，一个一个对比。
显然，当数据量增大时，我们需要优化查找方法获取更快的查找速度，我们可以通过维护一个有序数组，从而实现二分查找，查找速度从O(n)降为O(longn)。
但是数组并不便于插入和删除，链表便成为了最好的选择。
既然是采用二分查找，那么不如直接按照查找的步骤维护一种数据结构，于是二叉搜索树出现了。
二叉搜索树的性质为：
若左子树不为空，则左子树上所有节点值都小于根结点值；
]]></description><category></category></item><item><title><![CDATA[C++智能指针]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/125168007</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/125168007</guid><author>qq_44859952</author><pubDate>Tue, 07 Jun 2022 16:28:03 +0800</pubDate><description><![CDATA[由于使用malloc、new在堆上申请空间后，容易忘记释放对应空间，C++提出了智能指针管理申请的内存，避免内存泄露。
RAII（Resource Acquisition Is Initialization），是一种利用对象生命周期来控制程序资源（如内存、文件句柄、网络连接、互斥量等等）的简单技术。
在对象构造时获取资源，接着控制对资源的访问使之在对象的生命周期内始终保持有效，最后在对象析构的时候释放资源。
借此，我们实际上把管理一份资源的责任托管给了一个对象。.........]]></description><category></category></item><item><title><![CDATA[webserver介绍与实现（利用各模块的封装实现）]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/121425663</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/121425663</guid><author>qq_44859952</author><pubDate>Fri, 19 Nov 2021 16:30:10 +0800</pubDate><description><![CDATA[前言
此博客记录对于TinyWebServer项目的学习，并根据自己的理解做出些许更改。
原项目地址：https://github.com/qinguoyi/TinyWebServer
服务器基本规范

服务器框架
服务器程序虽然种类繁多，但是基本框架都是一样的。

I/O处理单元是服务器管理客户连接的模块。它通常要完成以下工作: 等待并接受新的客户连接，接收客户数据，将服务器响应数据返回给客户端。但是，数据的收发不一定在I/О处理单元中执行，也可能在逻辑单元中执行，具体在何处执行取决于事件处理模式（rea]]></description><category></category></item><item><title><![CDATA[webserver之定时器]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/121291792</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/121291792</guid><author>qq_44859952</author><pubDate>Fri, 12 Nov 2021 17:02:50 +0800</pubDate><description><![CDATA[前言
此博客记录对于TinyWebServer项目的学习，并根据自己的理解做出些许更改。
原项目地址：https://github.com/qinguoyi/TinyWebServer
定时器
网络程序通常需要处理定时事件，例如定期检测客户连接的活动状态，因为非活跃连接占用了连接资源，需要定期检测释放非活跃连接。通常将定时事件封装为定时器类，然后使用排序链表、时间轮等数据结构管理定时器。
linux提供了三种定时方法，
1.socket选项SO_RCVTIMEO和SO_SNDTIMEO
2.SIGALRM信]]></description><category></category></item><item><title><![CDATA[排序算法——十大排序算法的图示与实现]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/121291554</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/121291554</guid><author>qq_44859952</author><pubDate>Fri, 12 Nov 2021 16:59:52 +0800</pubDate><description><![CDATA[十大排序算法概览

比较类排序：通过比较来决定元素间的相对次序，由于其时间复杂度不能突破O(nlogn)，因此也称为非线性时间比较类排序。
非比较类排序：不通过比较来决定元素间的相对次序，它可以突破基于比较排序的时间下界，以线性时间运行，因此也称为线性时间非比较类排序。
前七种为比较类排序，后三种为非比较类排序。
稳定性：如果a=b，且a在b前面，排序之后仍能保证a在b前面，则为稳定的。
插入排序
逻辑
将左端第一个元素视为有序，然后遍历后面的元素，逐步插入到有序序列中。
代码实现
//插入排序
void ]]></description><category></category></item><item><title><![CDATA[webserver之mysql模块]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/120960014</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/120960014</guid><author>qq_44859952</author><pubDate>Mon, 25 Oct 2021 20:44:04 +0800</pubDate><description><![CDATA[前言
此博客记录对于TinyWebServer项目的学习，并根据自己的理解做出些许更改。
原项目地址：https://github.com/qinguoyi/TinyWebServer
mysql模块逻辑：单例模式，RAII机制
使用以空间换时间的思想，使用连接池的模式初始化多个mysql连接，采用单例懒汉模式创建连接池，使用信号量表示空闲连接数，管理连接出池入池，并且在入池出池操作前加锁，避免操作冲突。
使用RAII机制，将外部获取连接封装到类connectionRAII中，在该类的构造函数中获取连接池中]]></description><category></category></item><item><title><![CDATA[webserver之处理HTTP请求]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/120765250</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/120765250</guid><author>qq_44859952</author><pubDate>Thu, 14 Oct 2021 15:36:07 +0800</pubDate><description><![CDATA[前言
此博客记录对于TinyWebServer项目的学习，并根据自己的理解做出些许更改。
原项目地址：https://github.com/qinguoyi/TinyWebServer
测试效果
先放一波效果图

HTTP请求
HTTP GET请求行内容。

第一行为请求行，分为三个部分：请求方法、请求地址URL和HTTP协议版本，它们之间用空格分割。
后面都是头部字段。
在所有头部字段之后，HTTP请求必须包含一个空行，以标识头部字段的结束。请求行和每个头部字段都必须以结束（回车符和换行符)﹔而空行则必须]]></description><category></category></item><item><title><![CDATA[webserver之日志系统]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/120550066</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/120550066</guid><author>qq_44859952</author><pubDate>Wed, 29 Sep 2021 15:45:41 +0800</pubDate><description><![CDATA[前言
此博客记录对于TinyWebServer项目的学习，并根据自己的理解做出些许更改。
原项目地址：https://github.com/qinguoyi/TinyWebServer
Log
日志系统是用来存储程序运行中的通知信息、warning、error等。
首要任务就是格式化输出字符串到一个文件，还应当记录消息产生的时间，此系统选择使用按天作为文件名。
以消费者-生产者模式，使用阻塞队列实现线程异步处理Log消息。
还实现了主线程同步处理Log消息。
Log.h
从头文件可以清楚看出Log类具有的功]]></description><category></category></item><item><title><![CDATA[webserver之使用数组实现阻塞队列]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/120522891</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/120522891</guid><author>qq_44859952</author><pubDate>Tue, 28 Sep 2021 09:52:39 +0800</pubDate><description><![CDATA[阻塞队列
阻塞队列特性，当队列中没有元素时，对这个队列的弹出操作将会被阻塞，
直到有元素被插入时才会被唤醒；当队列已满时，对这个队列的插入操作就会被阻塞，
直到有元素被弹出后才会被唤醒。
queue容器在程序结束时才会释放内存，deque可以动态释放，
也可使用new分配容器再使用delete释放，
vector* vec_ptr = new vector;
delete vec_ptr;
使用数组实现可以预留出固定大小的内存，个人理解使用数组的优势所在。
代码实现
#ifndef BLOCK_QUEUE_]]></description><category></category></item><item><title><![CDATA[线程同步的三种机制]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/120461760</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/120461760</guid><author>qq_44859952</author><pubDate>Fri, 24 Sep 2021 19:35:17 +0800</pubDate><description><![CDATA[线程同步
线程同步：即当有一个线程在对内存进行操作时，其他线程都不可以对这个内存地址进行操作，直到该线程完成操作， 其他线程才能对该内存地址进行操作，而其他线程又处于等待状态。
即是避免同时操作变量，产生冲突。
POSIX信号量
信号量大于0时,等待信号量的线程被唤醒
sem_init(sem_t* sem, int pshared, unsigned int value)初始化信号量,默认为进程共享的,pshared = 0指定为局部信号量,value为初始值
sem_wait(sem_t* sem)阻塞]]></description><category></category></item><item><title><![CDATA[剑指Offer14-剪绳子1&2]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/119887385</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/119887385</guid><author>qq_44859952</author><pubDate>Tue, 24 Aug 2021 12:38:02 +0800</pubDate><description><![CDATA[题目描述–剪绳子1

思路分析
首先要分析出怎么切分是最优方案，显然和一定时，分成相等的数的乘积最大。用简单的数学归纳的思想可以发现，4对应2*2，5对应2x3，6对应3x3，7对应3x2x2，8对应3x3x2，显然分为3是最优选，然后是2。
由不等式也可解出极值点是e约为2.7，距离3最近。

动态规划
首先最直接会想到用动态规划的思想解题，先考虑切3，判断切3后的值是否大于dp中对应的值，依此向前填充dp矩阵，然后考虑切2
int cuttingRope(int n) {
        if(n &l]]></description><category></category></item><item><title><![CDATA[深度优先搜索（解题剑指Offer12、13）]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/119841359</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/119841359</guid><author>qq_44859952</author><pubDate>Sat, 21 Aug 2021 16:30:46 +0800</pubDate><description><![CDATA[剑指Offer12-矩阵中的路径 题目描述

思路分析
显然这是一个深度优先搜索的题，遍历整个矩阵寻找word的首字母，然后对首字母位置的上下左右四个方向进行延展，判断第二个字母是否存在，依此方法直到找到整个word字符串，即为true。为了避免重复遍历某个位置，在一条分支走过该位置时将其置为数字等不影响的字符作为标记，由于不同分支互不影响，所以在该分支结束时需要将标记恢复。
代码
bool exist(vector&lt;vector&lt;char&gt;&gt;&amp; board, string ]]></description><category></category></item><item><title><![CDATA[使用VGG16网络结构训练自己的图像分类模型]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/118969152</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/118969152</guid><author>qq_44859952</author><pubDate>Wed, 21 Jul 2021 16:20:50 +0800</pubDate><description><![CDATA[配置
tensorflow2.4.0
python3.6
猫狗大战数据集
代码
VGG16网络很著名，这里不再介绍。
keras里有预训练好的VGG16，tensorflow2.0以后的版本中已经集成了keras。
解释在代码中。
import tensorflow as tf
import tensorflow.keras as keras
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras import ]]></description><category></category></item><item><title><![CDATA[Select网络模型下的简单CS实例]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/118913748</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/118913748</guid><author>qq_44859952</author><pubDate>Mon, 19 Jul 2021 20:41:31 +0800</pubDate><description><![CDATA[Select网络模型
Select模型属于IO多路复用模型的一种，select使用一个socket数组来存放连接的socket。select会监视数组中所有的socket，可以知道哪些socket可读或者可写，从而避免无效操作（例如去读取不可读的socket，而在select中可以先查询该socket是否可读）。这样多个socket的IO操作能在一个线程内并发交替完成，这就是IO多路复用（复用同一个线程）。

使用select模型实现的简单服务端与客户端
服务端代码
#define WIN32_LEAN_A]]></description><category></category></item><item><title><![CDATA[快速幂算法]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/118527932</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/118527932</guid><author>qq_44859952</author><pubDate>Tue, 06 Jul 2021 19:37:13 +0800</pubDate><description><![CDATA[快速幂算法
假设求pow(2, 20)，一次一次的累乘非常耗时间，需要进行20次运算。
将指数20使用二进制表示为10100。
则2^20 = 216*24
可以看出每当二进制位为1时将对应2的幂指数乘到结果上即可。从最低位开始迭代，在迭代时将底数进行自乘，可得到对应的幂。
而计算机存储数据时正是以二进制存储的，使用二进制不需要进行转换，对于指数需要判断它的最低位是否为1，然后将其右移一位继续判断，直到指数为0。
代码实现
double quick(double x, long long n) {
	dou]]></description><category></category></item><item><title><![CDATA[windows简单TCP通信 C++]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/118466895</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/118466895</guid><author>qq_44859952</author><pubDate>Sun, 04 Jul 2021 20:30:51 +0800</pubDate><description><![CDATA[尝试使用自定义struct和char发送信息。服务器根据客户端发送的不同消息进行回应。
在发送struct时先发送一个“Who”以便客户端确认。
服务器
#define WIN32_LEAN_AND_MEAN
//#define _WINSOCK_DEPRECATED_NO_WARNINGS

#include&lt;windows.h&gt;
#include&lt;WinSock2.h&gt;
#include&lt;stdio.h&gt;
#include &lt;WS2tcpip.h&gt;



]]></description><category></category></item><item><title><![CDATA[百度飞浆ocr配置]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/118222184</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/118222184</guid><author>qq_44859952</author><pubDate>Fri, 25 Jun 2021 15:38:43 +0800</pubDate><description><![CDATA[本次配置基于Windows10平台anaconda3进行配置。
1 建立虚拟环境
可以在Navigator里新建，也可以在Prompt命令窗口内创建
conda create --name ocr
activate ocr


2 安装 paddlepaddle-gpu 2.0.0版
python -m pip install paddlepaddle-gpu==2.0.0b0 -i https://mirror.baidu.com/pypi/simple

安装时如果有报错ValueError: chec]]></description><category></category></item><item><title><![CDATA[剑指offer38题]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/118150091</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/118150091</guid><author>qq_44859952</author><pubDate>Wed, 23 Jun 2021 12:15:28 +0800</pubDate><description><![CDATA[问题描述
剑指offer38题

问题分析
最直观的想法就是使用深度搜索遍历每一个分支，找出所有组合，但是此问题要求结果中的字符串不重复，这就需要我们在使用DFS时进行剪枝，即是在每一层将重复的字符去除。
以abc和aab为例，红色表示被去除的分支。


代码实现
dfs剪枝
vector&lt;string&gt; result;
void perm(unsigned start, string str) {
	if (start == str.size() - 1) {
		result.push_ba]]></description><category></category></item><item><title><![CDATA[01背包问题详解]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/117879703</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/117879703</guid><author>qq_44859952</author><pubDate>Sun, 13 Jun 2021 16:12:13 +0800</pubDate><description><![CDATA[问题描述
有一堆物品，具有各自的重量、价值，有一个一定容量的背包
装取物品，得到最大的价值。由于每个物品都有装或不装两个状态，即01状态，所以称为01背包问题。
暴力破解
最直接的思路是利用深度优先的思想，遍历所有的方案，每个物品有两种状态，共有2^n种可能方案。
动态规划
采用动态规划更加节约空间和时间。
实例分析

最后一块石头的重量 II


class Solution {
public:
   int sum = 0;
   int lastStoneWeightII(vector&lt;int&]]></description><category></category></item><item><title><![CDATA[Pandas+Pyecharts 数据分析与可视化 3D地图+柱状图]]></title><link>https://blog.youkuaiyun.com/qq_44859952/article/details/115256124</link><guid>https://blog.youkuaiyun.com/qq_44859952/article/details/115256124</guid><author>qq_44859952</author><pubDate>Fri, 26 Mar 2021 22:25:25 +0800</pubDate><description><![CDATA[数据格式
手机信令数据，可依据sid判断用户，lon和lat对应位置的经纬度信息，还有时间和地区街道等信息

数据预处理
首先读取数据，按列选取需要用到的数据，并清洗数据。
data = pd.read_csv('./mobile_0.csv',encoding='GBK')
data = data[['sid','ts', 'lon', 'lat', 'region', 'street', 'address', 'area', 'building',
            'category_tags_]]></description><category></category></item></channel></rss>