![](https://img-blog.csdnimg.cn/20201014180756919.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
数据结构与算法
文章平均质量分 60
斯沃福德
这个作者很懒,什么都没留下…
展开
-
0-1 背包问题
dp[3][5] = 6,其含义为:对于给定的⼀系列物品中,若只对前 3 个物品进⾏选择,【当背包容量为 5 时】,最多可以装下的价值为 6。][0] = 0,即没有物品和没有容量时,背包装的价值为0;:由于wt[] 和 val[ ] 数组索引从 0 开始,⽽定义dp数组中的 i 是从 1 开始计数的,个物品的重量为wt[i],价值为 val[i],现在让你用这个背包装物品,最多能装的价值是多少?,根据这个定义,所求的最终答案就是 dp[N][W]。状态有两个,就是「可选择的物品」和「背包的容量」;....原创 2022-08-08 19:20:19 · 102 阅读 · 0 评论 -
二分查找法
基本的二分查找法原创 2022-06-01 20:50:15 · 174 阅读 · 0 评论 -
无向图的广度优先搜索(BFS)
一.概述所谓的广度优先搜索,指的是在搜索时,如果遇到一个结点既有子结点,又有兄弟结点,那么先找兄弟结点,然后找子结点。如图:从0开始,想找与0相同通的所有顶点。从0开始,搜索到6, 6有兄弟节点 2、1、5, 找完了兄弟节点再找子节点,找到6的邻接表,0搜过,找4的子节点然后分别遍历2、1、5邻接表 …回顾二叉树的层序遍历:从上到下打印二叉树nodes先存root节点开始循环: poll()弹出nodes的一个节点,其key放que中将弹出节点的左、右子结点放入nodes二.概述原创 2022-04-21 11:45:17 · 2450 阅读 · 0 评论 -
加权有向图的实现
一.概述之前学习的加权无向图中,边是没有方向的,并且同一条边会同时出现在该边的两个顶点的邻接表中;而在加权有向图中,边只出现在起点的邻接表中!二.实现加权有向边://加权有向边public class DirectedEdge implements Comparable<DirectedEdge> { private final int v; private final int w; private final double weight; publ原创 2022-04-18 22:09:43 · 434 阅读 · 0 评论 -
加权无向图的实现
一.概述加权无向图是一种为每条边关联一个权重值或成本的图模型。这种图能够自然地表示许多应用。在一副航空图中,边表示航线,权值则可以表示距离或是费用。在一副电路图中,边表示导线,权值则可能表示导线的长度即成本,或是信号通过这条先所需的时间。此时我们很容易就能想到,最小成本的问题。二.实现加权无向图中的边我们就不能简单的使用v-w两个顶点表示了,而必须要给边关联一个权重值,因此我们可以使用对象来描述一条边。加权边类://加权边对象public class Edge implements Comp原创 2022-04-17 20:47:35 · 430 阅读 · 0 评论 -
kruskal算法的实现
一.概述kruskal算法是计算一副加权无向图的最小生成树的另外一种算法,它的主要思想是按照边的权重(从小到大)处理它们,将边加入最小生成树中,加入的边不会与已经加入最小生成树的边构成环 ,直到树中含有V-1条边为止。kruskal算法和prim算法的区别:Prim算法是一条边一条边的构造最小生成树,每一步都为一棵树添加一条边。kruskal算法构造最小生成树的时候也是一条边一条边地构造,但它的切分规则是不一样的:kruskal将多个顶点看作多颗树,它每一次寻找的边会连接一片森林中的两棵树。如果一原创 2022-04-17 19:50:02 · 798 阅读 · 0 评论 -
并查集的实现
一.概述并查集是一种树型的数据结构 ,并查集可以高效地进行如下功能:①查询元素p和元素q是否属于同一组 (即看两个元素所在的树是不是同一棵树,即看树的根节点是否相同)②合并元素p和元素q所在的组(本质是合并两棵树,让一棵树的根节点被另一棵树的根节点所指向)并查集的结构并查集也是一种树型结构,但这棵树跟我们之前讲的二叉树、红黑树、B树等都不一样,这种树的要求比较简单:每个元素都唯一的对应一个结点;同一组数据中的多个元素都在同一颗树中;一个组中的数据对应的树和另外一个组中的数据对应的树之间原创 2022-04-14 22:58:52 · 337 阅读 · 0 评论 -
最小生成树和贪心算法
一.最小生成树之前学习的加权图,它的边关联了一个权重,那么就可以根据这个权重解决最小成本问题,但如何才能找到最小成本对应的顶点和边呢?最小生成树相关算法可以解决。1.1.最小生成树定义及约定定义: 图的生成树是它的一棵含有其所有顶点的无环连通子图一副加权无向图的最小生成树 是它的一棵权值(树中所有边的权重之和)最小的生成树约定:①只考虑连通图。最小生成树的定义说明它只能存在于连通图中,如果图不是连通的,那么分别计算每个连通图子图的最小生成树,合并到一起称为最小生成森林。②所有边的权重都各不相同原创 2022-04-06 22:22:47 · 1328 阅读 · 0 评论 -
图的拓扑排序: 基于dfs的顶点排序
一.概述dfs深度优先搜索有一个特点,那就是在一个连通子图上,每个顶点只会被搜索一次,要将搜索过的顶点进行排序,只需要将搜索的顶点放入到线性序列的数据结构中即可此处用栈存顶点,栈是后进先出,压栈时是由递归出口依次往回压入栈中,弹栈后顶点为正序排列。排序过程:从0出发,遍历0的邻接表: 2、3,搜索到2,遍历2的邻接表:4,搜索到4,遍历4的邻接表:5 ,遍历5的邻接表,没了,dfs递归结束,将5放入栈。在5顶点处递归结束,回到上一层dfs, v=4,4进栈 ,4没有兄弟节点,递归结束,;再回到原创 2022-03-31 22:15:38 · 1889 阅读 · 2 评论 -
图的拓扑排序:检测有向环
一.概述拓扑排序:给定一副有向图,将所有的顶点排序,使得所有的有向边均从排在前面的元素指向排在后面的元素,此时就可以明确的表示出每个顶点的优先级。 最终得到一个有序序列。如果要使用拓扑排序解决优先级问题,需要先保证有向图中没有环!API:检测有向环的过程:判在API中添加了onStack[] 布尔数组,索引为图的顶点,当我们深度优先搜索时:在如果当前顶点正在搜索,则把对应的onStack数组中的值改为true,标识进栈;如果当前顶点搜索完毕,则把对应的onStack数组中的值改为fa原创 2022-03-30 22:04:30 · 1459 阅读 · 0 评论 -
图的路径查找
一.概述我们实现路径查找,最基本的操作还是得遍历并搜索图,此处基于深度优先搜索来完成。其搜索的过程是比较简单的。我们添加了edgeTo[]整型数组,这个整型数组会记录起点s到任意顶点的路径。如果我们把顶点设定为0,那么它的搜索可以表示为下图:edge[2]=0 即顶点0到顶点2路径上的上一个顶点为0edge[1]=2 即顶点0到顶点1路径上的上一个顶点为2以此类推。。。要找整个完整路径时:如要找从0到1的路径,找到edge[1]=2,继续往回找,edge[2]=0,到了起点,路径为0-2-原创 2022-03-30 21:31:54 · 1564 阅读 · 0 评论 -
无向图的深度优先搜索
一.概述所谓的深度优先搜索,指的是在搜索时,如果遇到一个结点既有子结点,又有兄弟结点,那么先找子结点,子节点找完了,再找兄弟结点。无向图中,一条边在邻接表中出现两次,搜索子节点的时候需要判断此边是否之前被搜索过,如0-6 6-0 ,不能从6再往0方向区搜索,会重复。从顶点0出发,遍历0的邻接表,找到第一个6 ;继续递归dfs从6出发 ,遍历6的邻接表,0搜索过,找到4 ;继续递归dfs从4出发,找到5;继续递归dfs从5出发,遍历5的邻接表,找到3;继续递归dfs从3出发,遍历3的邻接表原创 2022-03-29 21:58:41 · 1928 阅读 · 0 评论 -
有向图的实现
一.概述定义:有向图是一副具有方向性的图,是由一组顶点和一组有方向的边组成的,每条方向的边都连着一对有序的顶点。出度:由某个顶点指出的边的个数称为该顶点的出度。入度:指向某个顶点的边的个数称为该顶点的入度。有向路径:由一系列顶点组成,对于其中的每个顶点都存在一条有向边,从它指向序列中的下一个顶点。有向环:一条至少含有一条边,且起点和终点相同的有向路径。一副有向图中两个顶点v和w可能存在以下四种关系:没有边相连;存在从v到w的边v—>w;存在从w到v的边w—>v;原创 2022-03-29 21:09:55 · 884 阅读 · 0 评论 -
无向图的实现
一.概述1. 基本概念相邻顶点:当两个顶点通过一条边相连时,我们称这两个顶点是相邻的,并且称这条边依附于这两个顶点。度:某个顶点的度就是依附于该顶点的边的个数路径:是由边顺序连接的一系列的顶点组成环:是一条至少含有一条边且终点和起点相同的路径连通图:如果图中任意一个顶点都存在一条路径到达另外一个顶点,那么这幅图就称之为连通图;否则为非联通图2. 存储结构常见的图的存储结构有两种:邻接矩阵和邻接表2.1. 邻接矩阵使用一个V*V的二维数组int[V][V] adj,把索引的值看原创 2022-03-29 20:57:46 · 517 阅读 · 0 评论 -
最大、最小优先队列的Java实现
一.概念普通的队列是一种先进先出(尾插头取)的数据结构,元素在队列尾追加,而从队列头删除。在某些情况下,我们可能需要找出队列中的最大值或者最小值,例如使用一个队列保存计算机的任务,一般情况下计算机的任务都是有优先级的,我们需要在这些计算机的任务中找出优先级最高的任务先执行,执行完毕后就需要把这个任务从队列中移除。普通的队列要完成这样的功能,需要每次遍历队列中的所有元素,比较并找出最大值,效率不是很高,这个时候,我们就可以使用一种特殊的队列来完成这种需求,优先队列。需要基于堆的思想来实现,由堆的特性,原创 2022-03-03 16:52:31 · 1024 阅读 · 0 评论 -
堆排序的Java实现
一.堆的构造堆的构造,最直观的想法就是另外再创建一个新数组,然后从左往右遍历原数组,每得到一个元素后,添加到新数组中,并通过上浮,对堆进行调整,最后新的数组就是一个堆。上述的方式虽然很直观,也很简单,但是我们可以用更聪明一点的办法完成它。①创建一个新数组把原数组0 ~ length-1的数据拷贝到新数组的1~ length处(舍弃掉索引0)②再从新数组长度的一半处开始往1索引处扫描(从右往左),然后对扫描到的每一个元素做下沉调整即可。为什么从一半处开始下沉: 因为堆的性质,大于一半的都是叶子结点,原创 2022-03-02 16:26:50 · 539 阅读 · 0 评论 -
堆的Java实现
一.概念堆是计算机科学中一类特殊的数据结构的统称,堆通常可以被看做是一棵完全二叉树的数组对象。堆的特性:1.它是完全二叉树,除了树的最后一层结点不需要是满的,其它的每一层从左到右都是满的,如果最后一层结点不是满的,那么要求左满右不满。保证叶结点只能出现在最下层or次下层快速辨别: 看最后一层的最后一个结点G,G之前是满的就是完全二叉树。而红色的树 G之前未满,则是不完全二叉树规律:①如果一个结点的位置为k,则它的父结点的位置为k/2 ,②而它的两个子结点的位置则分别为2k和2k+1。这样原创 2022-03-01 15:31:33 · 1315 阅读 · 0 评论 -
二叉树的最大深度问题 / leeCode 104题
一.概念深度:树的根节点到最远叶子结点的最长路径上的结点数,即层数二.方法1.如果根结点为空,则最大深度为0;2.计算左子树的最大深度;3.计算右子树的最大深度;4.当前树的最大深度max=左子树的最大深度maxL和右子树的最大深度maxR中的较大者+1代码: public int maxDepth() { //计算整个树的最大深度 return maxDepth(root); } private int maxDepth(Node x) { //计算指定树的最大原创 2022-02-26 16:58:40 · 203 阅读 · 0 评论 -
二叉树的层序遍历(BFS 广度优先算法)
一.概念所谓的层序遍历,就是从根节点(第一层)开始,依次向下,获取每一层所有结点的值,有二叉树如下:那么层序遍历的结果是:EBGADFHC二.实现需求: 使用层序遍历,获取整个树中的所有键步骤:创建两个队列,一个nodes存储每一层的结点,另一个que存储树的key ;使用循环从队列nodes中弹出一个结点:2.1获取当前结点的key放到que中;2.2如果当前结点的左子结点不为空,则把左子结点放入到队列nodes中2.3如果当前结点的右子结点不为空,则把右子结点放入到队列nodes原创 2022-02-26 15:41:24 · 670 阅读 · 0 评论 -
二叉搜索树的Java实现
一.树的概念树的定义:树是由n(n>=1)个有限结点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。树的特点:1.每个结点有零个或多个子结点;2.没有父结点的结点为根结点;3.每一个非根结点只有一个父结点;4.每个结点及其后代结点整体上可以看做是一棵树,称为当前结点的父结点的一个子树;补:树的检索效率较高!结点的度:一个结点含有的子树的个数称为该结点的度; —如E有两个子树,度为2; F有 KLM三个子树,度为3。根节点原创 2022-02-24 16:37:04 · 1796 阅读 · 1 评论 -
二叉树的前、中、后序遍历的Java实现
概述1.前序遍历; (根左右)先访问根结点,然后再访问左子树,最后访问右子树2.中序遍历; (左根右) ★★★先访问左子树,中间访问根节点,最后访问右子树3.后序遍历; (左右根)先访问左子树,再访问右子树,最后访问根节点前序遍历 //获取整个树中所有的键key public Queue<Key> preErgodic(){ //Queue为接口,功能为队列(尾插头取) Queue<Key> keys=new LinkedList();原创 2022-02-24 17:49:15 · 585 阅读 · 0 评论 -
符号表的java实现
一.概述符号表最主要的目的就是将一个键和一个值联系起来,符号表能够将存储的数据元素是一个键和一个值共同组成的键值对数据,我们可以根据键key来查找对应的值value。在符号表中,根据键key来找值value,所以键key要有唯一性 。 (类似Map的key①无序②不可重复)二.java实现public class SymbolTable<Key,Value> { //在此规定几种泛型 private Node head; private int N; priv原创 2022-02-19 22:03:07 · 538 阅读 · 0 评论 -
队列的Java实现
一.概述队列是一种基于先进先出(FIFO)的数据结构,是一种只能在一端进行插入,在另一端进行删除的特殊线性表, 它按照先进先出的原则存储数据,先进入的数据,在读取数据时先读被读出来。插入元素时:每次直接插到末尾即可(尾插法),新插入的元素即为新的尾结点last。(区别于栈的头插法)取出元素时:返回首结点指向的下一个元素即可。(先进先出),此时和弹栈一样。总结:队列为尾插头取,栈为头插头取二.用链表实现队列public class Queue<T> implements Ite原创 2022-02-17 22:16:36 · 2391 阅读 · 0 评论 -
栈的Java实现
一.概述栈是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。我们称数据进入到栈的动作为压栈,数据从栈中出去的动作为弹栈。(类似弹夹装子弹)栈是一种逻辑层面的数据结构,最终要使用物理存储结构来实现。物理存储结构有顺序存储结构(数组)和链式存储结构(链表)。栈既可以用数组实现也可以用链表来实现。二.用链表实现栈首先...原创 2022-01-21 20:19:43 · 822 阅读 · 0 评论 -
快慢指针解决约瑟夫环问题
一.概述传说有这样一个故事,在罗马人占领乔塔帕特后,39 个犹太人与约瑟夫及他的朋友躲到一个洞中,39个犹太人决定宁愿死也不要被敌人抓到,于是决定了一个自杀方式,41个人排成一个圆圈,第一个人从1开始报数,依次往后,如果有人报数到3,那么这个人就必须自杀,然后再由他的下一个人重新从1开始报数,直到所有人都自杀身亡为止。然而约瑟夫和他的朋友并不想遵从。于是,约瑟夫要他的朋友先假装遵从,他将朋友与自己安排在第16个与第31个位置,从而逃过了这场死亡游戏 。解题思路:1.构建含有41个结点的单向循环链表,分原创 2022-01-13 17:44:53 · 2487 阅读 · 0 评论 -
快慢指针:链表的中间值问题
一.快慢指针快慢指针指的是定义两个指针,这两个指针的移动速度一快一慢,以此来制造出自己想要的差值,这个差值可以然我们找到链表上相应的结点。一般情况下,快指针的移动步长为慢指针的两倍二.中间值问题利用快慢指针,我们把一个链表看成一个跑道,假设a的速度是b的两倍,那么当a跑完全程后,b刚好跑一半,以此来达到找到中间节点的目的。如下图,最开始,slow与fast指针都指向链表第一个节点,然后slow每次移动一个指针,fast每次移动两个指针。三.代码实现 public static String原创 2022-01-10 15:42:22 · 525 阅读 · 0 评论 -
双向链表的Java实现
一.概述双向链表也叫双向表,是链表的一种,它由多个结点组成,每个结点都由一个数据域和两个指针域组成,数据域用来存储数据,其中一个指针域用来指向其后继结点,另一个指针域用来指向前驱结点。链表的头结点的数据域不存储数据,前指针域为null,其后指针域指向第一个真正存储数据的结点。头节点:不存储真正的数据,其用指针域指向第一个存储数据的节点。头节点的作用主要是用来找到当前这条链表。二.链表的优缺点(和数组相反)优点:随机增删元素效率较高,如果遇到随机增删集合中元素的业务比较多时,建议使用LinkedL原创 2022-01-08 17:49:06 · 621 阅读 · 0 评论 -
单向链表的Java实现
一.概述单向链表是链表的一种,它由多个结点组成,每个结点Node都由一个数据域和一个指针域组成,数据域用来存储数据, 指针域用来指向其后继结点,即保存后继结点的内存地址。链表的头节点的数据域不存储数据,其指针域指向第一个真正存储数据的结点。头节点的作用主要是用来找到当前这条链表。二.链表的优缺点(和数组相反)优点:随机增删元素效率较高,如果遇到随机增删集合中元素的业务比较多时,建议使用LinkedList(因为增删不涉及到大量元素位移)缺点:查询效率较低,每一次查找某个元素的时候都需要从头节点原创 2022-01-05 20:29:52 · 579 阅读 · 0 评论 -
顺序表的Java实现
一.概述顺序表是在计算机内存中以数组(内存地址是连续的)的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元,依次存储线性表中的各个元素、使得线性表中在逻辑结构上响铃的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系。Java中常见的ArrayList集合的底层也是一种顺序表,使用数组实现,同样提供了增删改查以及扩容等功能。二.代码实现首先创造一个sequen类,在sequence类的构造函数中初始化数组e和记录元素个数的N。实现I原创 2022-01-02 21:46:18 · 1219 阅读 · 0 评论 -
高级排序:快速排序
一.概述快速排序是对冒泡排序的一种改进。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。二.原理1.首先设定一个分界值(默认为第一个数),通过该分界值将数组分成左右两部分;2.将大于或等于分界值的数据放到到数组右边,小于分界值的数据放到数组的左边。此时左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值;3.然原创 2021-12-31 23:15:47 · 2230 阅读 · 0 评论 -
高级排序:归并排序
一.概述归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。二.原理1.尽可能的一组数据拆分成两个元素相等的子组,并对每一个子组继续拆分,直到拆分后的每个子组的元素个数是1为止。 (使用递归来分组)2.将相邻的两个子组进行合并成一个有序的大组,在归并的过程中进行排序。3.不断的重复步骤2,直到最终只有一个组为止。总示意图:下面原创 2021-12-29 23:14:56 · 932 阅读 · 0 评论 -
简单排序:插入排序
一.原理类似于洗扑克牌1.把所有的元素分为两组,已排序的和待排序的;2.找到待排序的组中的第一个元素,向已经排序的组中进行插入;3.倒序遍历已经排序的元素,依次和待插入的元素进行比较,直到找到一个元素小于等于待插入元素,那么就把待插入元素放到这个位置,其他的元素向后移动一位;(并非找最大or最小。而是将待排序的第一个元素为a[i],依次和a[i]前面的已排序元素比较,找到已排序中一个<= a[i]的元素便跳出循环)刚开始时,默认第一个数为已排序。第一轮待排序的第一个数索引i为1;待排序原创 2021-12-28 18:21:11 · 201 阅读 · 0 评论 -
简单排序:选择排序
一.原理1.每一次遍历的过程中,都假定第一个索引处的元素是最小值min,并和其他索引处的值依次进行比较,如果当前索引处 的值大于其他某个索他引处的值,则假定其某个索引出的值为最小值min,最后可以找到最小值所在的索引2.最后交换第一个索引处和最小值所在的索引处的值(寻找最小;假定第一个为设定最小值min开始,与后面依次比较,谁小谁的索引就是min,最后将min放到第一,比较个数越来越少)由于原理较简单,直接上代码。二.java代码实现public class selection { p原创 2021-12-28 18:04:38 · 290 阅读 · 0 评论 -
简单排序:冒泡排序
*一.原理从第一个元素起,比较相邻的元素。如果前一个元素比后一个元素大,就交换这两个元素的位置。对每一对相邻元素做同样的工作,从开始第一对元素到结尾的最后一对元素。最终最后位置的元素就是最大值。(寻找最大,两两依次比较,大的放后面,比较的个数越来越少)因为原理较为简单,直接贴代码。二.java代码实现public class Bubble { public static void sort(int[] a){ for(int i=a.length-1;i>0;i原创 2021-12-28 17:49:07 · 120 阅读 · 0 评论 -
高级排序:希尔排序
希尔排序的原理及java实现原创 2021-12-28 17:24:16 · 207 阅读 · 0 评论