![](https://img-blog.csdnimg.cn/20190828214808259.jpg?x-oss-process=image/resize,m_fixed,h_224,w_224)
数据结构与算法
文章平均质量分 92
所以说,没事别瞎造轮子!
anlian523
人若无名,专心练剑!
展开
-
你真的会写二分查找吗——变种二分查找
其实我已经写过一篇关于变种二分查找的博客了,但最近刷题时发现之前对变种二分查找的理解不够深刻,而且相比之前博客的实现,本文有了另一种不同的实现,虽然只是具体细节不一样。原创 2020-11-07 23:11:39 · 372 阅读 · 1 评论 -
从小顶堆到堆排序——超详细图解——Python3实现
在简单选择排序中,每次选择会从待排序元素中找到最小值,但每次选择都需要遍历完剩余所有元素,而且在遍历时没有记录起来有用信息,这显得很浪费。而堆排序则利用了最小堆(或最大堆)的性质,每次选择最小值都会利用堆的数据结构来保存有用信息,即总是使得整个堆是一个最小堆,以便下一次选择时直接选择索引为0的节点就可以了。注意,本文使用到一个打印完全二叉树的算法方便我们观察整个堆的样子。具体做法是,新建一个printHeap.py,把这个算法除了测试代码都放进去。(不要误会,我绝对不是因为嫌画图麻烦才来写这个算法的原创 2020-08-01 23:54:54 · 1808 阅读 · 0 评论 -
打印一颗基于数组的完全二叉树——Python3实现
最近在复习堆排序的内容,发现基于数组的堆虽然用起来很方便,但打印不方便。所以本文实现了一个简单美观的打印一颗基于数组的完全二叉树的算法(堆就是一种完全完全二叉树嘛,但实现最小堆一般是基于数组的)。原创 2020-08-01 17:37:39 · 649 阅读 · 0 评论 -
你真的会写二分查找吗——分析二分查找变种代码
我们已经知道循环条件是left <= right,所以循环结束条件是left > right,且肯定是right = left -1。而且在key存在的情况下,left 和 right 肯定有一个落在边缘key上(边缘key是指,多个key时的最左key或最右key);如果key不存在,那么left 和 right 肯定right在 刚好小于key的元素上,left在 刚好大于key的元素上。原创 2020-04-05 00:16:31 · 388 阅读 · 0 评论 -
逆序数问题 使用归并排序
在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。比如3 4 1 2这个数组有4对逆序:分别是[3,1] [4,1] [3,2] [4,2]。本文使用归并排序来求逆序数。假设归并排序已经进行到了如上这个状态,正要把两个长度为2的有序子序列,合并成一个长度4的有序序列。i指向前子序列。j指向后子序列...原创 2018-11-13 18:53:09 · 581 阅读 · 0 评论 -
归并排序 改进归并
归并排序归并排序的主要思想是:分治(divide-and-conquer)策略,首先是分,先把问题拆分成规模很小的问题;然后是治,将子问题的答案合并成一个更大的小问题的答案,直到合并成问题本身的答案。分解的过程就是一颗二叉树,既然是二叉树,递归深度也就知道了是log2n\log_2nlog2n。再来看合并的过程,分别会有两个指针指向两个子序列的开头。还会有一个副本数组暂存数据。有两种...原创 2018-11-13 16:09:16 · 1437 阅读 · 0 评论 -
最小生成树算法——Kruskal算法、Prim算法、堆优化的Prim算法
什么叫最小生成树? 已知一个无向连通图,那么这个图的最小生成树是该图的一个子图,且这个子图是一棵树且把图中所有节点连接到一起了。一个图可能拥有多个生成树。一个带权重的无向连通图的最小生成树(minimum spanning tree),它的权重和是小于等于其他所有生成树的权重和的。 生成树的权重和,是把生成树的每条边上的权重加起来的和。一颗最小生成树有多少条边? 已知带权重无向连通图有V...原创 2018-08-27 13:31:52 · 11052 阅读 · 4 评论 -
无向图检测环——Union-Find、Union By Rank and Path Compression
Union-Find原创 2018-08-20 12:58:58 · 3374 阅读 · 0 评论 -
有向图检测环——普通方法、着色法
Detect Cycle in a Directed Graph未优化 给定有向图如上,环是[1,3,4]。 思路:分别对每个点进行深度遍历,在遍历的过程中,一旦发现当前要存入的元素已经在祖先数组中时,就发现环了,此时打印。当没有打印结果时就代表没有环。from collections import defaultdictd = defaultdict(list)#默认值为l...原创 2018-08-18 16:33:03 · 14111 阅读 · 4 评论 -
最大流算法:Edmond-Karp算法——Ford-Fulkerson算法——Dinic算法
问题定义给定有向图G=(V,E),其每条边都有容量cv,wcv,wc_{v,w}.这个容量代表这个边可以通过的最大容量。对于任一条边(v,w)(v,w)(v,w),最多有cv,wcv,wc_{v,w}个单位的流可以通过。 图中有两个特殊点,一个是s,称为源点(source),一个是t,称为收点(sink)。 既不是源点也不是收点的点,总的进入的流必须等于总的发出的流。 最大流问题就是确定...原创 2018-07-26 14:03:36 · 10696 阅读 · 5 评论 -
SPFA算法详解——判断负权环
SPFA(Shortest Path Faster Algorithm)(队列优化)算法是求单源最短路径的一种算法。它是在Bellman-ford算法的基础上加上一个队列优化,减少了冗余的松弛操作,是一种高效的最短路算法。 Bellman-Ford算法虽然可以处理负环,但是时间复杂度为O(ne),e为图的边数,在图为稠密图的时候,是不可接受的。 Bellman-Ford算法的缺点在于,当某一个...原创 2018-07-08 13:47:33 · 11092 阅读 · 6 评论 -
Bellman-ford算法详解——负权环分析
算法描述输入:图(V,E)和起点original 输出:从original到其他任意节点的最短路径(长度和最短路径构成)适用条件Bellman-ford算法适用于单源最短路径,图中边的权重可为负数即负权边,但不可以出现负权环。 负权边:权重为负数的边。 负权环:源点到源点的一个环,环上权重和为负数。算法复杂度:O(VE)算法步骤dist[]:从o...原创 2018-07-07 20:17:48 · 26436 阅读 · 2 评论 -
Floyd算法详解——证明无后效性——寻找最小环
代码Floyd算法代码非常简洁,它是一种基于动态规划的多源最短路径算法(即可以求出每个点对之间的最短路径)。 初步分析来看,代码就是个三层嵌套循环,然后就是k层循环在最外层。其实记住这些,就够使用了,但研究算法还是不求甚解比较好。 private void floyd() { for (int k = 0; k &amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;am原创 2018-07-05 13:36:50 · 2015 阅读 · 0 评论 -
最短路径算法——Dijkstra算法——python3实现
本文参考来自数据结构与算法分析 java语言描述。问题描述问题分析实现过程如何使用数据变化表问题描述现有一个有向赋权图。如下图所示: 问题:根据每条边的权值,求出从起点s到其他每个顶点的最短路径和最短路径的长度。 说明:不考虑权值为负的情况,否则会出现负值圈问题。 s:起点 v:算法当前分析处理的顶点 w:与v邻接的顶点 dvdvd_v:从s到v的距离 ...原创 2018-07-03 10:28:21 · 63244 阅读 · 22 评论 -
最短路径算法——无权最短路径——python3实现
本文参考来自数据结构与算法分析 java语言描述。问题描述现有一个无权图。如下图所示: 问题:使用某个顶点s作为输入参数,找出从s到所有其他顶点的最短路径。 说明:因为是无权图,因此我们可以为每台边赋值为1。这里选择v3为s作为起点。问题分析此时立刻可以说,从s到v3的最短路径是长为0的路径,标记此信息,得到下图。 现在开始寻找从s出发距离为1的顶点。这些顶点...原创 2018-07-02 21:56:30 · 4243 阅读 · 3 评论 -
划分树详解——求解整数区间内第K大的值——python3实现
本文题目与代码参考来自程序设计解题策略。题目重述题目重述:给定一个数组num = [1,5,2,3,6,4,7,3,0,0],求出在索引[x,y]之间第K大的值。 比如,求[1,3]中第2大的值。索引[1,3]对应的子数组为[5,2,3],第2大的值,也是将[5,2,3]排序,排序后为[2,3,5],那么[2,3,5]排第二的值为3,所以这里返回3. 注意:第K大的值,其实是指排序...原创 2018-06-23 21:28:50 · 1173 阅读 · 1 评论 -
线段树——入门
此博客参考了线段树从零开始。考虑读者已阅读参考博客。存储sum用数组的长度参考博客提出,用数组来存储各个节点(每个节点存储的是,该节点代表区间内数的总和)的sum,就不需要弄成,建立树节点的class,还为这个class提供左右孩子的方法之类的,直接用数组来代替原二叉树结构。 但参考博客提出,sum数组的长度为存数数组的长度的4倍,其实不对,只要得到数的层数,再得到...原创 2018-06-22 09:14:32 · 3043 阅读 · 0 评论 -
插入排序算法
插入排序有:直接插入排序、二分法插入排序、希尔排序。下面是直接插入排序的代码: public static > void insertionSort( AnyType [ ] a ) { int j; for( int p = 1; p < a.length; p++ ) { AnyType t原创 2017-10-03 15:02:09 · 308 阅读 · 0 评论 -
数字全排列返回list的list:java实现
程序实际很简单,是一个递归的过程。过程如下:括号里是传进去的begin和end参数,而后面跟的数字是进入之后需要循环的次数。这个程序也更让我理解了,递归程序的过程:好比是一个人在执行任务,在执行过程中有很多分叉,如果有分叉的情况,就分叉的情况扔到栈中去,因为栈是先进后出的,所以符合要求。同地位的分叉总有先后顺序,这个人走到第一个分叉的第一个分叉,一直到第一个到达的终点,到达终点原创 2017-10-01 17:05:08 · 1657 阅读 · 0 评论 -
JAVA实现二项队列
二项队列和其他优先队列的区别在于,它是具有一定顺序的数的集合,即森林。它具有一个数组,每个数组元素存每棵树,通过存每棵树的根节点的引用。数组中,0索引的那颗树存1个元素,1索引的那颗树存2个元素,以此类推。二项队列的设计思想完全利用的二进制的原理。而其中merge函数的switch case判断也是利用二进制的原理。而二项队列中的最重要的操作,合并操作,也可以通过将两个二进制数相加来理原创 2017-10-01 15:15:16 · 595 阅读 · 0 评论 -
java实现左式堆
任一节点X的零路径长(null path length)npl(X)定义为到从X到一个不具有两个儿子的节点的最短路径的长。不具有两个儿子的节点即是叶子节点和单孩子节点。所以叶子节点和单孩子节点的npl都是0,因为自身到自身的距离为0.规定空节点即null,则npl(null)为-1.此规定也为以下定理服务。定理:任一节点的零路径长比它的两个儿子的零路径长的最小值大1,所以说叶子节点原创 2017-09-27 18:33:11 · 449 阅读 · 0 评论 -
优先队列即堆:插入算法与删除算法JAVA
首先介绍下,优先队列的信息。里面有一个数组,0位置不存元素。1位置开始存,第i个元素,左孩子是2i,右孩子是2i+1,父节点是i/2。还有就是根据优先队列的插入算法,所以都是先有左孩子,再有右孩子的。代码来自数据结构与算法分析(Java语言)上面给出的代码,主要是注释有用。public AnyType deleteMin(){ if(isEmpty()) throw newUnde原创 2017-09-16 14:05:21 · 1310 阅读 · 0 评论 -
java实现TreeSet,迭代器使用二叉查找树,每个节点有前驱和后继
代码摘抄自数据结构与算法分析(Java语言)的课后题的答案,但是自己把程序理解了一遍。答案不仅有错,而且错还挺多,基本测试好了,应该没有错误了,但是不排除你们把代码拿去实验又发现有错误,如若发现请回复我下(..•˘_˘•..)解释一下,此二叉树的节点类,除了有左右孩子链之外,还有前驱链和后继链,这个前驱后继就是迭代器的顺序来的,即刚好比当前节点的小的节点,和刚好比当前节点大的节点。此代码重原创 2017-08-26 11:57:42 · 678 阅读 · 0 评论 -
java实现TreeSet,迭代器使用二叉查找树,每个节点有父节点链
代码摘抄自数据结构与算法分析(java语言)的课后题的答案,但是自己把程序理解了一遍,其实答案也有错误,比如原答案无法删除叶子节点,因为写答案的人没有去实现这个功能。注释已经把程序解释得很清楚了。下面放代码,先是TreeSet实现类:package four;import java.util.*;class UnderflowException extends Exception原创 2017-08-24 19:25:26 · 976 阅读 · 0 评论 -
ArrayList链表实现循环队列
首先介绍下非循环队列的实现形式,不管用链表还是数组实现,总会有两个变量记录队头和队尾的位置当头尾都指向了索引0位置时,则代表队列中没有元素。当进行第一次入队操作后,头指向第一个位置。而尾指向最后一个元素的下一个位置。进行了四次入队操作后。当第一次进行出队操作后,头指向的位置往后移动一位。从这里就可以看出,这种队列实现,头永远指向的是第一个元素,而原创 2017-07-26 14:31:40 · 1265 阅读 · 0 评论 -
中缀到后缀表达式的转换:java-stack实现
首先声明中缀表达式的要求,运算符只有+-*/^和()这7种,其余只能是用来代表数字的小写字母,最后是=。程序运行过程是,循环读取每个字符。如果是操作数,那么就直接打印;如果是操作符,则推入一个栈中同时进行判断。判断过程:打印栈元素时,有一个优先级,^最高,其次*/,再其次是+-,最小的是(。如果新读取的操作符是^,那么需要循环出栈打印,优先级大于等于^的运算符,即只有^出栈,再原创 2017-07-25 13:54:14 · 535 阅读 · 0 评论 -
计算后缀表达式的值:JAVA-Stack实现
计算一个后缀表达式的值,首先想到就是可以利用栈来实现。当见到一个数时,就把数推入到栈中去。当见到一个运算符时,就把栈顶的两个元素即数字弹出并删除,计算出结果后,再结果这个数推入到栈中。注意就是,先弹出的数(即代码中的a)在运算符的右边,后弹出的数(即代码中的b)在运算符的左边,这样子进行计算。而加减乘除幂+-*/^这五个运算符都符合这样的逻辑。package three;i原创 2017-07-25 12:05:16 · 2562 阅读 · 0 评论 -
Josephus问题:ArrayList实现
约瑟夫环问题描述: 编号为1,2,3...n的人一词围成一圈,从第k个人开始报数(从1开始),数到m的人退出。接着下一个人又从1开始报数,数到m的人退出,以此类推。问:剩下的人的编号是多少?为了更加清晰理解题意,举例说明编号若为1到7,m为3,那么第一次被去掉的数为4。意思是起点是1,移动了3次,那么移动结束到了4、ArrayList的listIterator这个迭代器,原创 2017-07-23 14:57:55 · 406 阅读 · 0 评论 -
最大连续子序列和:递归和动态规划
问题描述:给定一个整数序列,a0, a1, a2, …… , an(项可以为负数),求其中最大的子序列和。如果所有整数都是负数,那么最大子序列和为0;方法一:用了三层循环,因为要找到这个子序列,肯定是需要起点和终点的,所以第一层循环确定起点,第二层循环确定终点,第三层循环在起点和终点之间遍历。时间复杂度:O(N^3)package secondCHA;public clas原创 2017-07-17 15:21:05 · 25016 阅读 · 10 评论 -
编写一个递归方法,返回数N的二进制表示中1的个数
问题:编写一个递归方法,返回数N的二进制表示中1的个数解决:利用这样一个事实:如果N是奇数,那么它等于N/2的二进制表示中1的个数加1。 通过自己笔算还能发现,如果N是偶数,那么它的个数等于,N一直除以2直到变成一个奇数,这个奇数的个数。第一个版本:package firstCHA;public class two1num { public static原创 2017-07-16 16:10:55 · 2935 阅读 · 2 评论