
数据结构与算法
文章平均质量分 67
主要介绍包括栈、队列、树、优先搜索、排序、链表、查找等数据结构和算法解析。并分享诸多的算法题目的详细讲解、思路分析以及算法的展示
Hacker_徐
书山有路勤为径,学海无涯苦作舟。
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
并查集(Union-Find Disjoint Sets/DSU)
并(unity)查(find)集(set),即可以合并、查找的树状数据结构,常用于处理不交集查询问题。图1图1中每个箭头两端连接的是两名呈同班同学关系的学生,请问,1号同学和5号同学是同一个班的吗?我们简化一下,就是如果我们能确定任意两个人之间是不是同班同学,我们能不能确定所有同学之间是不是同班同学。在简化,在同一个班的学生里,指定一个老大(t),当查询两个学生(x,y)时,只需要看者两个学生是否与老大间接认识或直接认识,如果都认识,那么者两个学生就在同一个班里。原创 2023-07-22 19:45:53 · 374 阅读 · 0 评论 -
图(Map)
图也是一种非线性的数据结构,它在表示城市交通、多节点网络等关系时非常好用,图的基本示意图如图1所示。原创 2022-12-28 15:52:46 · 521 阅读 · 0 评论 -
二分图(Bipartite Graph)
二分图の定义二分图又叫二部图,是图论中的一种特殊模型。假设S=(V,E)是一个无向图。如果顶点V可分割为两个互不相交的子集(A,B),并且图中的每条边(i,j)所关联的两个顶点i和j分别属于这两个不同的顶点集(i in A,j in B),就可以称图S为一个二分图。简单来说,就是顶点集V可分割为两个互不相交的子集,并且图中每条边依附的两个顶点都分属于这两个互不相交的子集,两个子集内的顶点不相邻。二分图の匹配。原创 2022-12-28 15:55:52 · 14828 阅读 · 2 评论 -
迪科斯特拉算法(Dijkstra Algorithm)
Dijkstra算法是用于解决单源最短路径问题的贪心算法。先求出长度最短的一条路径,再参照该最短路径求出长度次短的一条路径,直到求出从源点到其他各个顶点的最短路径。Dijkstra算法一般的表述通常有两种方式,一种用永久和临时标号方式,一种是用OPEN, CLOSE表的方式,这里均采用永久和临时标号的方式。注意该算法要求图中不存在负权边。原创 2022-12-28 15:45:17 · 519 阅读 · 0 评论 -
贝尔曼-福特算法(Bellman-Ford)
在边权可正可负的图中,环游零环、正环、负环3种。如果包含零环或正环,去掉以后路径不会变长;如果包含负环,则意味着最短路不存在。既然没有环,最短路最多只经过不含起点在内的n-1个节点,可以通过n-1“轮”松弛操作得到。上述算法就是Bellman-Ford算法。我们也可以用FIFO队列来代替上面的循环检查。当负权值存在时,最短路不一定存在,但还是有办法在最短路存在的情况下求出来的。如果最短路存在,则一定存在一个不含环的最短路。以上就是本文的全部内容啦!时间复杂度:O(nm)。原创 2022-12-29 17:21:14 · 388 阅读 · 2 评论 -
弗洛伊德算法(Floyd-Warshall)
弗洛伊德算法又名插点法,是一种利用动态规划的思想寻找给定的加权图中多源点之间最短路径的算法。弗洛伊德算法是一种在具有正或负边缘权重但没有负周期的加权图中找到最短路径的算法。算法的单个执行将找到所有顶点对之间的最短路径的长度(加权)。虽然它不返回路径本身的细节,但是可以通过对算法的简单修改来重建路径。该算法的版本也可用于查找关系R的传递闭包,或在加权图中所有顶点对之间的最宽路径。原创 2022-11-29 17:09:04 · 3220 阅读 · 0 评论 -
线性筛(Linear Sieve)
线性筛,即欧拉筛,比起埃及筛,优点就是每个数直筛一遍。线性筛的思想是“这个合数只会被它的最大非自身因数(对应最小质因数)筛”。线性筛的时间复杂度为O(n)。原创 2022-12-23 18:50:02 · 1024 阅读 · 0 评论 -
时间复杂度(Time Complexity)
预计阅读时间:5分钟 时间复杂度,又叫时间复杂性,也就是我们常说的大O。时间复杂度是不容忽视的衡量算法好坏的重要指标。 时间复杂度是一个函数,用于描述该算法的运行时间。 举个简单的例子:一个20米的木头,一群蚂蚁三年吃一米,那吃掉整个木头要多少年?答案是20*3=60年。那木头是N米呢?那就需要3N年。如果这是一个函数,就可以记作T(N)=3N。 时间复杂度就是把T(N)化简为一个可以是N,,等等的数量级。 那如何推导时间复杂度呢?原创 2022-12-03 15:32:15 · 930 阅读 · 0 评论 -
空间复杂度(Space Complexity)
预计阅读时间:5分钟 随着计算机空间的发展,空间复杂度逐渐变得不那么重要了,但它在比赛中仍然存在。 tips:O(1) < O(logN) < O(N) < O(N^2) < O(2^N) 1、常数 O(1) : 普通常量、变量、对象、元素数量与输入数据大小 N 无关的集合,皆使用常数大小的空间。 如以下代码所示,虽然函数 test() 调用了 N 次,但每轮调用后 test() 已返回,无累计栈帧空间使用,因此空间复杂度仍为 O(1原创 2022-12-03 16:02:12 · 595 阅读 · 0 评论 -
前向星(Forward Star)
前向星是以储存边的方式来存储图的数据结构。构造方法如下:读入每条边的信息,将边存放在数组中,把数组中的边按照起点顺序排序(可以使用基数排序,如下面例程),前向星就构造完了。通常用在点的数目太多,或两点之间有多条弧的时候。一般在别的数据结构不能使用的时候才考虑用前向星。除了不能直接用起点终点定位以外,前向星几乎是完美的。前向星的时间复杂度为O(m),m为边数。总体时间并不会逊色于邻接表。原创 2022-11-05 16:01:24 · 1950 阅读 · 1 评论 -
堆(Heap)
要想真正了解堆,就需要先了解二叉树。树和二叉树(Tree&Binary Tree)_Hacker_徐的博客-优快云博客树是一种非线性的数据结构,它在表示机构的组织关系图等方面非常好用,树的示意图如图1所示。图1 - 树的示意图。堆是所有树中最具有特点的树,因为它是用数组存储的,并且总是完全二叉树。原创 2022-10-22 21:32:31 · 467 阅读 · 0 评论 -
链式前向星(Chain Forward Star)
一、简介其实就是链表写法的邻接表改成数组来实现,不直接使用指针,用数组下标间接代替指针的作用。参考链表实现邻接表:1.链表中每插入一个边,是采用头插的方法,这里的思路也是头插;2.链表访问的结尾采用的是NULL,这里采用的是-1;而且我们经常直接使用(~i)作为循环的结束,因为对-1进行取反操作,可以直接得到0(-1在计算机内以补码存储,为11111111,取反即00000000)原创 2022-11-05 16:18:01 · 618 阅读 · 0 评论 -
笛卡尔树(Cartesian Tree)
笛卡尔树是一种特定的二叉树数据结构,由数组存储。在范围最值、范围top k查询方面广泛应用。树中的元素满足二叉搜索树性质,要求按照中序遍历得到的序列为原数组序列树中节点满足堆性质,节点的key值要大于其左右子节点的key值当按照index从1到n(或者从0到n-1)的顺序将数组中的每个元素插入到笛卡尔树中时,当前要被插入的元素的index值最大,因此根据二叉搜索的性质需要沿着当前已经完成的笛卡尔树的根的右子树链搜索。由于笛卡尔树要满足堆的性质。.........原创 2022-08-28 20:42:58 · 3259 阅读 · 0 评论 -
霍夫曼树(Huffman Tree)
给定N个权值为N的叶子节点,构造一颗二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也成为霍夫曼树。霍夫曼树是带权路径长度最短的树,权值最大的节点离根较近。......原创 2022-08-29 19:00:00 · 2075 阅读 · 1 评论 -
霍夫曼树:霍夫曼编码(Huffman Tree:Huffman Coding)
预计阅读时间:10分钟接上回 之前我们了解了霍夫曼树,今天我们来了解一下霍夫曼编码。 霍夫曼树常处理符号编写工作。根据整组数据中符号出现的频率高低,决定如何给符号编码。如果符号出现的频率越高,则给符号的码越短,相反符号的号码越长。相关术语 霍夫曼编码就是再霍夫曼树上进行实现的。 从树根开始,从待译电文中逐个取码。若编码为0,就往左走;编码为1,就往右走,一旦到达了叶子节点,就是译出了一个字符;在从根出发,直到电文结束。 T:00 ;:00 A:10 C原创 2022-12-03 17:59:14 · 1639 阅读 · 0 评论 -
红黑树(Red Black Tree)
红黑树是一种自平衡的二叉查找树。结点是红色或黑色。根结点是黑色。每个叶子结点都是黑色的空结点(NIL结点)。每个红色结点的两个子结点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色结点)从任一结点到其每个叶子的所有路径都包含相同数目的黑色结点。图1 - 红黑树示意图。原创 2022-09-02 21:51:27 · 244 阅读 · 0 评论 -
树和二叉树(Tree&Binary Tree)
树是一种非线性的数据结构,它在表示机构的组织关系图等方面非常好用,树的示意图如图1所示。图1 - 树的示意图。原创 2022-08-23 17:57:32 · 282 阅读 · 2 评论 -
二叉查找树(BST)
若任意节点的左子树不空,则左子树上所有节点的值均小于它的根节点的值;若任意节点的右子树不空,则右子树上所有节点的值均大于它的根节点的值;任意节点的左、右子树也分别为二叉查找树;没有键值相等的节点。二叉查找树相比于其他数据结构的优势在于查找、插入的时间复杂度较低为 O ( log n )。二叉查找树是基础性数据结构,用于构建更为抽象的数据结构,如集合、多重集、关联数组等。二叉查找树是能够高效地进行如下操作的数据结构。插入一个数值查询是否包含某个数值删除某个数值。原创 2022-10-29 16:34:04 · 1280 阅读 · 0 评论 -
栈(Stack)
栈的顺序结构与链式结构的区别:顺序结构适合数据元素不大的情况,而链式结构适合数据元素变化比较大的情况。我们都知道栈有栈顶指针,链表有头指针,这两者是缺一不可的,所以在进行链栈的设计的时候,我们就把栈顶放在单链表的头部。举个例子,我们经常乘坐的电梯,先进去的人往往会被挤到最里面,而最后进来的人刚好到了门口。再举个例子,手枪的弹夹,先按入弹夹的子弹肯定是最后一个打出去的,而最后按入弹夹的子弹肯定是第一个打出去的。图1是本来的栈,现在来了一个新节点,我们把新节点和a[n]连接起来,再修改栈顶即可(如图2所示)。.原创 2022-08-20 16:30:06 · 1802 阅读 · 2 评论 -
队列(Queue)
进入队列的操作是将新元素追加到rear直销的队尾之后,rear->next=新元素,再将rear指向新元素,此时,新元素成为队尾。循环顺序队列:在顺序队列的基础上进行改造,是队头和队尾可以在数组中循环变化,在数据插入与删除是不需要频繁移动数据。循环队列:就是用数组模拟队列,但数组的插入和删除需要移动数据,比较繁琐。首先,创建头节点,让头和尾两个指针指向它,它的next为NULL。举个例子,同学们排队进教室,肯定是先来的先进教室,后来的后进教室。只清空头节点意外的全部节点,有头节点在,清空万还能够继续操作。.原创 2022-08-29 21:31:49 · 735 阅读 · 0 评论 -
双端队列(Deque)
deque,即双端队列(double ended queue),是一种可以在两端扩展或收缩的序列化容器。deque是C++ 标准模板库的一部分,想要使用deque,需要在程序中包含头文件deque。规定了deque中可以存放哪种类型的元素。为deque名。原创 2022-11-05 15:12:33 · 16929 阅读 · 3 评论 -
快速排序(Quick Sort)
快速排序是由东尼·霍尔所发明的排序算法。事实上,排序算法通常明显比其他算法更快,因为它的内部循环可以在大部分框架上很有效地被实现出来。原创 2022-10-29 13:49:11 · 262 阅读 · 0 评论 -
归并排序(Merge Sort)
归并排序是创建在归并操作上的一种有效的排序算法,与1945年由冯·诺伊曼提出。归并排序的实现分为递归实现与非递归(迭代)实现。递归实现的归并排序是算法设计中分治策略的典型应用,可以讲一个大问题分割成若干个小问题解决,然后用所有小问题的答案解决整个大问题。分递归(迭代)实现的归并排序首先进行的是两两归并,然后是四四归并,接着是八八归并,一只到归并完整个数组。原创 2022-10-29 13:47:57 · 558 阅读 · 0 评论 -
堆排序(Heap Sort)
对排序是指利用堆这种数据结构所设计的一种选择排序算法。堆是一种近似完全二叉树的结构(通常堆排序是用一维数组实现的),并满足性质:以最大堆为例,其中父节点的值总是大于起孩子节点的值。原创 2022-10-29 13:46:34 · 127 阅读 · 0 评论 -
插入排序(Insertion Sort)
插入排序是一种简单直观的排序算法,他的工作原理与抓扑克牌非常类似。插入排序的工作原理是:对于未排序数据(右手抓到的牌),在一排序序列(左手已经排好序的牌)中从后向前扫描,找到相应位置并插入。插入排序在实现上通常采用in-place排序(即志勇到O(1)的额外空间的排序),因此在从后向前扫描的过程中需要反复将以排序的元素逐步向后移位,为新元素提供插入空间。原创 2022-10-29 13:45:00 · 331 阅读 · 0 评论 -
选择排序(Selection Sort )
选择排序也是一种简单直观的排序算法,工作原理是:开始时在序列中找到最小(大)的元素,放到序列的其实位置作为已排序序列,然后从生于未排序的元素中寻找最小(大)的元素,放到一排序序列的末尾。以此类推,直到所有元素均排序完毕。原创 2022-10-29 13:43:05 · 1002 阅读 · 0 评论 -
冒泡排序(Bubble Sort)
冒泡排序(Bubble Sort)的名字由来是因为越小(或者越大)的元素回经由交换慢慢“浮”到数列的顶端,就像气泡一样。原创 2022-10-29 13:41:24 · 496 阅读 · 0 评论 -
顺序表(Contiguous List)
用一组地址连续的存储单元依次存储线性表中每个数据元素的数据结构名叫顺序表。顺序表的逻辑关系相邻的两个元素在物理位置上也相邻。原创 2022-10-24 21:50:28 · 272 阅读 · 0 评论 -
结构体(Struct)
结构体是由一批数据组合而成的结构型数据。组成结构型数据的每个数据称为结构型数据的“成员” ,其描述了一块内存区间的大小及解释意义。//定义学生姓名int num;//定义学生编号//定义语文成绩//定义数学成绩//定义英语成绩//定义总成绩int pg;//定义等级}stu[101];//定义该结构体数组。原创 2022-10-21 23:24:47 · 355 阅读 · 0 评论 -
指针(Pointer)
指针是一种数据类型,指针变量的值是另一个变量在内存中的地址。每一个变量都有一个名字,且在内存中占据一个内存位置(地址),可以通过。计算机的内存中每个存储单元都是有序的,都是按字节编码,字节是最小的存储单位。在定义指针的时候如果不一开始就赋值的话,建议赋空,避免出错。这样的赋值后,p1和p2指向同样的地址,对p2的任何更改都会影响p1的值。这其中,->用于指向结构体的指针,表示结构体内的元素。操作内存上的值,也可以通过地址间接操作内存上的值。而64位编译器的内存中,内存空间的地址最多到。原创 2022-10-15 16:19:46 · 1030 阅读 · 0 评论 -
单向链表(Singly Linked List)
链表是由一系列节点组成的线性结构,每个节点包括两个部分:存储空间元素和下一个节点地址的指针。链表的元素个数不受限制,添加元素时存储个数会随之改变。链表的有点在于确定大小,插入和删除元素都是相当方便;但缺点是不能随机访问。在链表中会有一个头指针变量,这个变量可以用来找到这个链表,头指针指向的是第一个节点。......原创 2022-08-27 21:18:04 · 535 阅读 · 0 评论 -
双向链表(Double Linked List)
虽然单向链表能够100%解决逻辑关系为“一对一”数据的存储问题,但在解决那些需要大量查找前趋节点的问题是,单向链表无疑是不能用了,因为单向链表适合“从前往后”查找,并不适合“从后往前”查找。如果要提高链表的查找效率,那双向链表(双链表)无疑是首选。双向链表字面上的意思是“双向”的链表,如图1所示。图1 - 双向链表示意图双向指各个节点之间的逻辑关系是双向的,该链表通常只有一个头节点。......原创 2022-08-28 18:15:25 · 16210 阅读 · 4 评论 -
哈希表(HashTable)
哈希表,又名做散列表,是根据关键字和值直接进行访问的数据结构。也就是说,它通过关键字 key 和一个映射函数 Hash计算出对应的值value,然后把键值对映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做哈希函数,用于存放记录的数组叫做哈希表。哈希表的关键思想是使用哈希函数,将键 key 和值 value 映射到对应表的某个区块中。哈希函数决定该关键字的对应值应该存放到表中的哪个区块,并将对应值存放到该区块中。...原创 2022-08-30 22:13:56 · 4264 阅读 · 0 评论 -
分治算法(Divide&Conquer)
分治算法从字面上理解就是分而治之,即把一个复杂的大问题分成若干个相同或者相似的子问题,在把子问题划分成更多小问题,直到最后子问题是简单一下就能解出来为止;然后开始把简单的子问题向上合并,最终得到大问题的解。举个例子:16枚硬币,其中有一个假币,假币的重量和真币的重量不一样,请问比较多少次能够找出假币。首先我们把这个大问题分成两个小问题,随机选择8枚硬币作为第一组,剩下来的8枚硬币作为第二组。利用仪器判断假币在那一堆里。在剩下的那组里再取出两组4枚,进行称重,依此类推。最后,找出假币。此过程如图1所示。...原创 2022-08-28 21:35:44 · 647 阅读 · 0 评论 -
贪心算法(Greedy Algorithm)
i=4,排序后的第5个,袋中的重量count=9.1+4.5=13.6,不超过重量极限15,ans=5。i=3,排序后的第4个,袋中的重量count=5.8+3.3=9.1,不超过重量极限15,ans=4。i=2,排序后的第3个,袋中的重量count=3+2.8=5.8,不超过重量极限15,ans=3。i=1,排序后的第2个,袋中的重量count=1+2=3,不超过重量极限15,ans=2。i=0,排序后的第1个,袋中的重量count=1,不超过重量极限15,ans=1。好啦,以上就是本文的全部内容啦!..原创 2022-08-25 19:24:58 · 1322 阅读 · 0 评论 -
动态规划(Dynamic Programming)
我们先举个例子让大家明白动态规划到底是什么?1+1+1+1+1的结果是5,那如果我们在上面等式的前面再加上一个“1+”,那结果是什么呢?很多人都会立刻回答:“是6。”那为什么回答地怎么快呢?是因为我们已经知道1+1+1+1+1是5这就是动态规划。动态规划的基本思想与分治法类似,也是将一个大问题分解成若干个子问题,前一个子问题的解为后一个子问题的解提供了有效的信息。在求解子问题是,列出各种可能的局部解,通过决策保留那些可能达到最优的局部解,丢弃其他局部解。...原创 2022-08-25 19:02:18 · 237 阅读 · 0 评论 -
动态规划:01背包(Dynamic Programming)
例如,一维状态第i轮对体积为 3 的物品进行决策,则dp[7]由dp[4]更新而来,这里的f[4]正确应该是dp[i - 1][4],但从小到大枚举j这里的dp[4]在第i轮计算却变成了dp[i][4]。在二维情况下,状态dp[i][j]是由上一轮i - 1的状态得来的,dp[i][j]与f[i - 1][j]是独立的。当选择1~i个物品,总体积不大于j的集合的最大值可以转化成选择1~i-1个物品,总体积不大于j-V[i]的集合+最后一个物品的价值:dp[i-1][j-V[i]]+w[i]。原创 2022-08-25 14:30:41 · 292 阅读 · 0 评论 -
深度优先搜索(DFS)
广度优先搜索(Breadth First Search)又名宽度优先搜索,是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。图1 广度优先搜索广度优先搜索适合找最优解,如图1所示:1就是从0到1;2就是从0到2;......原创 2022-08-15 23:04:34 · 619 阅读 · 0 评论 -
广度优先搜索(BFS)
广度优先搜索(Breadth First Search)又名宽度优先搜索,是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。图1 广度优先搜索广度优先搜索适合找最优解,如图1所示:1就是从0到1;2就是从0到2;原创 2022-10-29 13:58:27 · 3499 阅读 · 0 评论 -
顺序查找(Sequential Search)
为了避免顺序查找过程的每一步都要检测整个表是否查找完毕,查找之前需要先将key赋予a[0]的关键。如果数据量很大很大,顺序查找显然是不能用了,那我们应该用什么查找呢?按相应顺序进行查找,直到找到目标数据。原创 2022-10-29 16:36:37 · 481 阅读 · 0 评论