<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[RetenQ的博客]]></title><description><![CDATA[]]></description><link>https://blog.csdn.net/RetenQ</link><language>zh-cn</language><generator>https://blog.csdn.net/</generator><copyright><![CDATA[Copyright &copy; RetenQ]]></copyright><item><title><![CDATA[7.3 并查集搜索]]></title><link>https://blog.csdn.net/RetenQ/article/details/121418776</link><guid>https://blog.csdn.net/RetenQ/article/details/121418776</guid><author>RetenQ</author><pubDate>Fri, 19 Nov 2021 11:27:54 +0800</pubDate><description><![CDATA[并查集算法
并查集算法是一个利用结点关系，进行分类合组的算法
简介
并查集可以通过一个一维数组来实现
我们把每一个点视作一个"独立的，只有一个结点"的树
之后我们可以通过一些条件，逐渐将这些树合并成一棵大树
合并的过程，其实就是找统一的父节点的过程，我们可以自定两条原则：
1.相异的情况下，把右边的父节点改为左边的父节点。视作二者合并成了一组
2.通过两者最高的父节点来进行比较
另外，既然我们通过层层推进找到了某个点的父节点，那么我们在"统一"之后，也可以顺便的把路上的其它结点修改，这样会方便我们的二次寻找]]></description><category></category></item><item><title><![CDATA[7.2 二叉树与堆]]></title><link>https://blog.csdn.net/RetenQ/article/details/121418685</link><guid>https://blog.csdn.net/RetenQ/article/details/121418685</guid><author>RetenQ</author><pubDate>Fri, 19 Nov 2021 11:24:39 +0800</pubDate><description><![CDATA[二叉树与堆
二叉树是一种特殊的、常见的树
简介
二叉树的特点在于每个结点最多只有两个儿子
如果要使用更严格的递归定义，则是:

二叉树要么为空，要么由根结点、左子树、右子树组成
而左子树、右子树分别是一棵二叉树

二叉树是使用范围极广的树，一棵多叉树也可以转换为二叉树
二叉树类型
满二叉树：如果二叉树中每个内部结点都有两个儿子，这样的二叉树叫做满二叉树
完全二叉树：如果一棵二叉树除了最右边的位置上有一个或几个叶节点缺少外，其他都是丰满的，那么它就是完全二叉树
我们可以把满二叉树理解为一种特殊的，极其完美的完]]></description><category></category></item><item><title><![CDATA[7.1 树的基本介绍]]></title><link>https://blog.csdn.net/RetenQ/article/details/121418499</link><guid>https://blog.csdn.net/RetenQ/article/details/121418499</guid><author>RetenQ</author><pubDate>Fri, 19 Nov 2021 11:17:36 +0800</pubDate><description><![CDATA[树的基本介绍
介绍
树其实就是不包含回路的连通无向图
因为这个特点，我们为树赋予了这些特性：
1.一棵树中的任意两个结点，有且仅有唯一的一条路径连通
2.一棵树如果有n个结点，那么它一定恰好有n-1条边
3.在一棵树中，加上一条边，那么就会得到一个回路

树是指任意两个结点间有且仅有一条路径的无向图
只要是没有回路的连通无向图，就是树

结点节点
我们把树中的每一个点叫做结点，当然也要叫节点的，无伤大雅
根又叫做根节点，即最开始的节点。一棵树有且仅有一个根节点
父亲结点简称父结点，儿子结点简称子结点
如果一]]></description><category></category></item><item><title><![CDATA[6.4 最短路径：Bellman-Ford优化]]></title><link>https://blog.csdn.net/RetenQ/article/details/121418416</link><guid>https://blog.csdn.net/RetenQ/article/details/121418416</guid><author>RetenQ</author><pubDate>Fri, 19 Nov 2021 11:14:58 +0800</pubDate><description><![CDATA[Bellman-Ford优化
我们知道，在最开始的算法中，我们每一次操作后就会进行一次松弛的判断
实际上，这浪费了我们的时间：每次操作后有些顶点的最短路就不会变化了
实际上我们可以这样做：每次仅仅对最短路的估计值发生了变化的顶点的所有出边执行松弛操作
实操
我们可以利用队列来维护这些点
我们每次都选取队首的顶点u，对顶点u的所有出边进行松弛操作
如果通过u-&gt;v这条边，可以使得源点到顶点v的最短路径变短，且顶点v不在当前队列中
那么我们就把顶点v放入队尾
在对顶点u的所有出边松弛完成之后，就将u出队
]]></description><category></category></item><item><title><![CDATA[6.3 最短路径：Bellman-Ford算法]]></title><link>https://blog.csdn.net/RetenQ/article/details/121418151</link><guid>https://blog.csdn.net/RetenQ/article/details/121418151</guid><author>RetenQ</author><pubDate>Fri, 19 Nov 2021 11:06:24 +0800</pubDate><description><![CDATA[Bellman-Ford算法
很强的一个算法，无论是思路、思想、代码实现都很优秀
而且，它可以解决负权边的问题
简介
一句话概括这个算法就是：“对所有的边进行n-1次松弛操作”
一样的，我们用uvw三者表示“从顶点u[i]到顶点v[i]的这条边，权值为w[i]”
随后检查，新的距离会不会比原本的距离短
1.用dis数组初始化估计值，并且把除了起始点之外的，都设置为正无穷大(解释见后)
2.按边的图的数组中的顺序，遍历检查"这条路会不会距离变短"
3.由于起始点到自身的距离是0，所以一定存在它到相邻区域的更小]]></description><category></category></item><item><title><![CDATA[6.2 最短路径：Dijkstra算法与单源最短路径]]></title><link>https://blog.csdn.net/RetenQ/article/details/121417989</link><guid>https://blog.csdn.net/RetenQ/article/details/121417989</guid><author>RetenQ</author><pubDate>Fri, 19 Nov 2021 11:01:27 +0800</pubDate><description><![CDATA[Dijkstra算法——单源最短路径
Dijkstra算法是用来处理"指定一个点，计算该点到其余各个顶点的最短路径"这件事
简介
和上文有点像，因为当我们讨论一点到各个点的距离的时候，我们就不得不计算各种中转站
我们这里得到了一个新定义，松弛，我们认为它是：

如果两点距离通过中转点缩短了距离，我们就把这个过程叫松弛

Dijkstra算法实际就是 “选点，松弛，更新，选点” 的不断循环，直到得到结果
核心
我们这里使用两个数组
二维数组e来存储两点之间的路径关系
一维数组dis来存储一个点到其余各个点的初]]></description><category></category></item><item><title><![CDATA[6.1 最短路径：Floyd-Warshall算法]]></title><link>https://blog.csdn.net/RetenQ/article/details/121417683</link><guid>https://blog.csdn.net/RetenQ/article/details/121417683</guid><author>RetenQ</author><pubDate>Fri, 19 Nov 2021 10:52:41 +0800</pubDate><description><![CDATA[Floyd-Warshall算法
只有五行核心的算法
简介
假设我们有四个点。每个点之间都有一定的距离，或者甚至没有路
现在我们想要知道如何获得两点之间的最短路径
使用之前说的深度优先或者宽度优先当然是可以的，不过有没有更好的办法？
于是我们使用了Floyd-Warshall，先进了一些的算法
算法核心
首先我们要知道，有的时候，通过n个点而从A-&gt;B，是有可能比直达得到更短的路径
基于这个思路，我们逐步推进
1.首先是直达，这个就不用说了
2.然后我们假设“如果允许在点1中转”，得到新的结果比较，更]]></description><category></category></item><item><title><![CDATA[5.0 图与遍历搜索图]]></title><link>https://blog.csdn.net/RetenQ/article/details/121417508</link><guid>https://blog.csdn.net/RetenQ/article/details/121417508</guid><author>RetenQ</author><pubDate>Fri, 19 Nov 2021 10:46:33 +0800</pubDate><description><![CDATA[图的简介与二维数组
图就是由顶点和连接顶点的边组成的
表示图
我们利用二维数组表示图
二维数组的两个参数行列，均表示顶点，二者相交得到的即是距离
我们用正无穷(一般可以用999999代替)表示二者之间没有边，0是某点到自身的距离
比如e[a][b] = 3 ;就代表a到b的距离是3
图还分为有向图和无向图
顾名思义，有向图是有方向属性的，无向图则没有
换言之，对于无向图，我们有：

e[a][b] = e[b][a]

图的遍历
我们上一章学习了深度优先算法和广度优先算法
现在我们就利用它们来完成图的遍历
]]></description><category></category></item><item><title><![CDATA[4.3 深度广度搜索]]></title><link>https://blog.csdn.net/RetenQ/article/details/121409862</link><guid>https://blog.csdn.net/RetenQ/article/details/121409862</guid><author>RetenQ</author><pubDate>Fri, 19 Nov 2021 10:32:34 +0800</pubDate><description><![CDATA[实战：海岛面积
例子
我们有一个海岛，海岛有一个主岛和附属岛屿，总地图大小为10*10
我们使用0代表海洋，1-9代表路段，我们由一个点（比如(6,8)开始）算出所在岛的面积
我们想计算所在岛屿的面积
解决
我们直接利用广度搜索来进行这这件事，我们直接上了

    #include &lt;stdio.h&gt;
    struct node{
        int x ; // 横坐标
        int y ; // 纵坐标

    };

    int main(){
        /]]></description><category></category></item><item><title><![CDATA[4.2 bfs 广度优先搜索]]></title><link>https://blog.csdn.net/RetenQ/article/details/121409696</link><guid>https://blog.csdn.net/RetenQ/article/details/121409696</guid><author>RetenQ</author><pubDate>Thu, 18 Nov 2021 20:40:17 +0800</pubDate><description><![CDATA[广度优先算法 Breadth First Search BFS
深度优先算法的兄弟，包含另外一种搜索思维
也叫宽度优先算法
概述
与深度优先算法不同，广度优先算法注重于"对所有情况的分析搜索"
如果是深度优先算法是刨根问底地分析每种情况，
广度优先就是在在层层扩展中找到题解
例
还是之前的问题，我们想在n*m的迷宫中找到起点到终点的最短路径
分析
我们的核心思想是分析扩展时每发现一个点，就将这个点加入到队列中，直到到达终点
另外，为防止一个点被多次走到，我们还要一个数组来记录一个点是否被走到
队列与搜索路径]]></description><category></category></item><item><title><![CDATA[4.1dfs 深度优先搜索]]></title><link>https://blog.csdn.net/RetenQ/article/details/121409656</link><guid>https://blog.csdn.net/RetenQ/article/details/121409656</guid><author>RetenQ</author><pubDate>Thu, 18 Nov 2021 20:38:39 +0800</pubDate><description><![CDATA[深度优先搜索 Depth First Search DFS
深度优先是比较基础的一种方法，还有一种是它的兄弟广度优先
深度优先顾名思义：先深入搜索到一种情况的"底部"（原谅我用了这么抽象的词），然后再返回搜索其它情况
例题
我们依旧举例说明，比如我们现在想要在A,B,C三个箱子中放入1,2,3三张牌，想知道一个有多少种情况
循环举穷
首先我们一步步尝试每一次，每一个箱子中的放牌情况
我们约定，对于每个箱子，我们都优先放入1，然后是2，最后是3
当然，如果手上一张牌都没有，也就说明某种情况被列举完了
我们用一]]></description><category></category></item><item><title><![CDATA[3.0暴力枚举]]></title><link>https://blog.csdn.net/RetenQ/article/details/121409619</link><guid>https://blog.csdn.net/RetenQ/article/details/121409619</guid><author>RetenQ</author><pubDate>Thu, 18 Nov 2021 20:36:31 +0800</pubDate><description><![CDATA[枚举

枚举，暴力的一种算法，典型利用"计算机算力大大高于人力"这件事的做法
枚举，顾名思义：有序的尝试每一种可能
在书里，枚举被单独列为一章，不过每一节都是各种花式实战
因此只用了一个MD笔记来记录它

鬼畜奥数题
我们现在有一道奥数题，要求使用1-9九个数字填入下方的等式:
[][][]+[][][]=[][][]
注意：每个数字只能用一次
请问一共有多少种组合
    #include &lt;stdio.h&gt;
    int main(){
        int a,b,c,d,e,f,g,]]></description><category></category></item><item><title><![CDATA[2.3.2 使用数组模拟链表]]></title><link>https://blog.csdn.net/RetenQ/article/details/121409563</link><guid>https://blog.csdn.net/RetenQ/article/details/121409563</guid><author>RetenQ</author><pubDate>Thu, 18 Nov 2021 20:33:16 +0800</pubDate><description><![CDATA[链表(数组模拟)
链表也可以使用数组来实现，操作和基础知识比指针简单
但是个人觉得就思路和操作的清晰，以及对链表的理解而言，还是用指针好
模拟链表介绍
我们可以利用两个数组，分别记录链表要的两个东西：数据和地址
我们使用一个数组data，来存储每个结点的数据
使用另外一个数组right，来存储序列中每一个数右边的数的位置
比如现在二者如下：
位置    1  2  3   4   5   06  07  08   09
data:   2  3   5   8   9   10  18  26  32
ri]]></description><category></category></item><item><title><![CDATA[2.3.1 使用指针实现的链表]]></title><link>https://blog.csdn.net/RetenQ/article/details/121409517</link><guid>https://blog.csdn.net/RetenQ/article/details/121409517</guid><author>RetenQ</author><pubDate>Thu, 18 Nov 2021 20:31:06 +0800</pubDate><description><![CDATA[链表(指针)
在存储一大波数的时候，如果使用数组，有时会感到数组显得不太灵活
我们可以在C语言中使用指针和动态分配函数malloc来实现链表

关于指针，这里就不赘述了，默认已经了解相关知识

指针实现
malloc
malloc 函数的作用就是从内存中申请分配指定字节大小的内存空间
malloc(4);  //这样就申请了四个字节大小的内存空间


如果不知道字节大小，那么使用sizeof()查看就好了

malloc 函数的返回值是void*，也就是未确定类型的指针，它可以被强制转换为任何其它类型的指针]]></description><category></category></item><item><title><![CDATA[2.2 栈]]></title><link>https://blog.csdn.net/RetenQ/article/details/121409386</link><guid>https://blog.csdn.net/RetenQ/article/details/121409386</guid><author>RetenQ</author><pubDate>Thu, 18 Nov 2021 20:24:37 +0800</pubDate><description><![CDATA[栈
栈是一种后进先出的数据结构，它就是栈
栈限定了它只能在一端进行插入和删除的操作，这决定了它“后进先出”的性质
栈的实现也比较简单：利用一个一维数组和一个指向栈顶部的变量（称它为top）即可，我们前面所讲的“插入”和“删除”的操作，就是通过这个"top"来实现的
入栈
入栈的操作很简易
top++ ； 
s[top] = x ; //s是定义出来储存的数组/char组

简化一下，就可以化成一行
s[++top] = a[i]; 

代码实战
比如我们想要利用程序来检测一个字符串是否是回文
//首先我们需]]></description><category></category></item><item><title><![CDATA[2.1 队列]]></title><link>https://blog.csdn.net/RetenQ/article/details/121393991</link><guid>https://blog.csdn.net/RetenQ/article/details/121393991</guid><author>RetenQ</author><pubDate>Thu, 18 Nov 2021 09:52:23 +0800</pubDate><description><![CDATA[队列
队列是一种特殊的线性结构，它只允许在队列的首部head进行删除，以及在尾部tail进行插入
这两种操作分别被称为“出队”和“入队”。而当队列中没有元素即head=tail时，称其为“空队列”
我们现在可以将队列的三个基本元素（一个数组，两个变量）封装为一个结构体类型
struct queue{
    int data[100] ; //存储内容的主体
    int head ;  //队首
    int tail ;  //队尾
};

//——————————————————————————
]]></description><category></category></item><item><title><![CDATA[1.3 快速排序]]></title><link>https://blog.csdn.net/RetenQ/article/details/121393791</link><guid>https://blog.csdn.net/RetenQ/article/details/121393791</guid><author>RetenQ</author><pubDate>Thu, 18 Nov 2021 09:46:25 +0800</pubDate><description><![CDATA[#快速排序
快速排序的核心是基准数，基准数理论上是可以随机的一个数，这里我们每次都选择第一个/最左边的数作为基准数
我们可以认为，快速排序的过程，就是不断选择基准数排序的过程。我们大致可以这么描述它的步骤：
【比如我们排序 6 1 2 7 9 3 4 5 10 8 】
1.选择一个数作为基准数，我们这里就是6
2.派出两个变量去“搜索”比6大的数，和比6小的数。这里我们设置变量为i与j
3.i和j从两头开始搜索，i从最左边（第0位），而j从最右边(最后一位)
4.i从左向右搜索，j从右向左进行搜索。当二者都]]></description><category></category></item><item><title><![CDATA[1.2 冒泡排序]]></title><link>https://blog.csdn.net/RetenQ/article/details/121393777</link><guid>https://blog.csdn.net/RetenQ/article/details/121393777</guid><author>RetenQ</author><pubDate>Thu, 18 Nov 2021 09:45:43 +0800</pubDate><description><![CDATA[冒泡排序
核心思想在于“每次比较两个相邻的元素，如果它们顺序错误就把它们交换过来”，那什么是所谓顺序错误呢？
比如，我们想要进行从大到小的排序，则把小的数字往后靠
比如有五个数字12 35 99 18 76 ，我们试图将它们从大到小排序
1.我们首先比较第一12和第二35，显然35大。依据核心思想，替换二者。那么现在五个数的顺序就是： 35 12 99 18 76
2.接着我们去比较现在的第二位12和第三位99，显然12又是更小的那个数，现在顺序变为35 99 12  18 76
3.重复上面的步骤直到比较]]></description><category></category></item><item><title><![CDATA[1.1 桶排序(简陋版)]]></title><link>https://blog.csdn.net/RetenQ/article/details/121392765</link><guid>https://blog.csdn.net/RetenQ/article/details/121392765</guid><author>RetenQ</author><pubDate>Thu, 18 Nov 2021 09:00:20 +0800</pubDate><description><![CDATA[#桶排序（简版）
这是一种对于n个数据排序的方式
这个算法是假设了有n个桶，编号便是0-*(n-1)，共n个桶来装数据
每当出现了一个数，我们就在对应编号的桶中放置一个标志
查看数据时只要看每个桶中有多少数据即可
//比如我们对0-10的数进行排序
    int a[11] ;
    int i,j,t ; 

    for(i = 10 ; i &gt;= 0 ; i++){
        a[i] = 0 ; //讲每个桶的原始值设为0
    }

    for(i =1 ; i &lt;=]]></description><category></category></item><item><title><![CDATA[LeetCode0015-三数之和]]></title><link>https://blog.csdn.net/RetenQ/article/details/121071145</link><guid>https://blog.csdn.net/RetenQ/article/details/121071145</guid><author>RetenQ</author><pubDate>Sun, 31 Oct 2021 22:12:52 +0800</pubDate><description><![CDATA[双指针
利用双指针的搜索，实质上双指针那部分很简单
记录本题主要是为了记录思想
题目
给你一个包含 n 个整数的数组 nums，判断 nums 中是否存在三个元素 a，b，c ，使得 a + b + c = 0 ？请你找出所有和为 0 且不重复的三元组。
注意：答案中不可以包含重复的三元组。
示例 1：
输入：nums = [-1,0,1,2,-1,-4]
输出：[[-1,-1,2],[-1,0,1]]
示例 2：
输入：nums = []
输出：[]
示例 3：
输入：nums = [0]
输出：[]
题]]></description><category></category></item></channel></rss>