
数据结构与算法
文章平均质量分 85
刘扬俊
这个作者很懒,什么都没留下…
展开
-
Java基础——对象的序列化(通俗易懂,排版优美)
Java基础——对象的序列化什么是对象的序列化(Serialization) “序列化”是一种把对象的状态转化成字节流的机制,“反序列”是其相反的过程,把序列化成的字节流用来在内存中重新创建一个实际的Java对象。这个机制被用来“持久化”对象。通过对象序列化,可以方便的实现对象的持久化储存以及在网络上的传输。大致的过程如下图所示: 对象被转换成“字节流”后可以存入文件,内存,亦或者是数...原创 2018-05-23 23:31:23 · 25897 阅读 · 7 评论 -
SQL中关于EXISTS谓词的理解
在SQL语言中,EXISTS(存在)谓词是一个非常重要的查询关键词。让我们先看看EXISTS的用法:EXISTS代表存在量词。带有EXISTS谓词的子查询不返回任何数据,只产生逻辑真值“true”或逻辑假值“false”。例如,以下的SQL语句:SELECT snameFROM studentWHERE exists(SELECT * FROM sc ...原创 2017-12-06 15:35:14 · 12472 阅读 · 12 评论 -
win10配置汇编语言环境(王爽汇编语言环境)
win10配置汇编语言环境(王爽汇编语言环境)前言有不少童鞋在学习“汇编语言”这门课程时,不太满足于课本上的理论知识,想要亲自上机实践一下,从而更能够更深刻的理解汇编语言的基本原理。然而,大多数同学使用的电脑都比较新,用的是WIN10系统,然而自从win7之后,微软就把DOS从系统从去除了,因此,我们必须得自己搭建一个汇编语言的调试环境。...原创 2019-03-30 16:47:20 · 16927 阅读 · 24 评论 -
为什么使用Spring的@autowired注解后就不用写setter了?
为什么使用Spring的@autowired注解后就不用写setter了?刚学习Spring的时候,知道了@autowired注解是非常灵活的,既可以直接写在Properties(属性)上,也可以写在属性相应的setter方法上,亦或者直接写在Constructer(构造器)上,但是有一天,我却惊奇的发现,为什么在Properties上写了@autowired注解后,不写这个属性相应的s...原创 2018-12-16 17:15:01 · 19479 阅读 · 22 评论 -
Java之对象的多态性(使用生活中通俗的例子讲解)
Java之对象的多态性多态概念 (Java)多态(英语:polymorphism),是指计算机程序运行时,相同的消息可能会送给多个不同的类别之对象,而系统可依据对象所属类别,引发对应类别的方法,而有不同的行为。简单来说,所谓多态意指相同的消息给予不同的对象会引发不同的动作称之。多态也可定义为“一种将不同的特殊行为和单个泛化记号相关联的能力”。多态可分为变量多态与函数多态。变量多态是指:基类...原创 2018-04-03 12:48:49 · 29975 阅读 · 27 评论 -
汉明码——计算机网络——全网最通俗的讲解
汉明码——计算机网络——全网最通俗的讲解一、什么是汉明码(hamming code)“汉明码”,也称作“海明码”,英文名为“hanming code”,在通信领域中,“汉明码”有广泛的应用,由理查德·卫斯里·汉明于1950年发明。“汉明码”是一种“错误纠正码”,可以用来检测并且纠正数据从发送端发往接收端中发生的错误。汉明码的发明者理查德汉明在1940年代晚期,运...原创 2019-02-24 15:46:27 · 64771 阅读 · 88 评论 -
操作系统之信号量
操作系统中的信号量在解决线程之间的同步中起着非常大的作用,那么什么是信号量呢?百度百科:信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。维基百科:信号量(...原创 2018-03-29 23:13:32 · 51038 阅读 · 6 评论 -
JAVA基础——接口(全网最详细教程)
Java基础——接口接口概念 官方解释:Java接口是一系列方法的声明,是一些方法特征的集合,一个接口只有方法的特征没有方法的实现,因此这些方法可以在不同的地方被不同的类实现,而这些实现可以具有不同的行为(功能)。 我的解释:接口可以理解为一种特殊的类,里面全部是由全局常量和公共的抽象方法所组...原创 2018-05-10 09:46:42 · 400076 阅读 · 194 评论 -
动态规划之——矩阵连乘(全网最详细博文,看这一篇就够了!)
动态规划之矩阵连乘原创 2019-06-30 20:50:17 · 78917 阅读 · 55 评论 -
图论基础
今天,我们大家来讨论的数据结构为:图结构。图论是计算机科学中非常重要的内容。首先,让我们来了解一下什么是图论:图论〔Graph Theory〕是数学的一个分支。它以图为研究对象。图论中的图是由若干给定的点及连接两点的线所构成的图形,这种图形通常用来描述某些事物之间的某种特定关系,用点代表事物,用连接两点的线表示相应两个事物间具有这种关系。一个图就像下图所示。节点和节点之间用边连接起原创 2018-01-08 17:25:34 · 762 阅读 · 0 评论 -
并查集的路径压缩优化
在上面两节中,我们讨论了基于Size和基于Rank的优化策略,但是这两种优化策略都集中在在优化Unionelements这个操作上,那么,对于并查集来说,是不是还有其他部分可以优化呢?当然,下面我们就来介绍一下优化find查询的优化策略:一.基于循环的路径压缩优化首先,让我们来回忆一下find执行的操作:从一个节点,不停的通过parent数组向上去寻找他的根节点,在这个过程中,我们相当于把原创 2017-12-28 21:41:59 · 21530 阅读 · 13 评论 -
基于Rank的并查集优化
在上一小节中,我们讨论了基于Size的并查集优化方法,即在合并两个集合时,通过判断两个集合元素的数量大小来决定把哪一个集合并入另一个集合当中,从而减少了因为合并集合使得合并后树的层数增多的情况,因此执行find操作所需的步骤数量也大大减少了。但是,没有绝对完美的优化方法,这种基于Size的合并策略在有的时候却并不能很好的解决合并时发生层数增多的问题,例如下面这种情况:我们可以看原创 2017-12-27 21:21:42 · 3374 阅读 · 8 评论 -
基于Size的并查集优化
在上一节中,我们对并查集进行了一个结构上的优化,然而,我们发现在数据量很大时,貌似效率并没有被提升很多,因此,我们今天就来讨论一下并查集的另一种优化方式:基于Size的优化。在上一节中,我们对于两个集合的合并,貌似是随意的进行的,然而,这样会引发一些极端的情况出现,例如,在下图中:如果我们需要把4和9所在的集合合并,对于原来的代码逻辑,我们总是把第一个集合的根元素的父节点指向另一个原创 2017-12-27 17:14:03 · 1159 阅读 · 0 评论 -
并查集的常规实现方法
在上一节中,我们讨论了并查集的简单实现方法,然而我们却发现并查集的效率好像并不是很高,因此,计算机科学家想出了另外一种方法来实现并查集。在新的实现思路中,我们把每一个元素看做是一个节点,该节点只有一个指向其父亲的指针,也就是说parent[i]=j的意思就是i元素的父亲为j元素,因为 i 元素的父亲指针就是指向 j 节点的,如果一个元素没有父亲了,那么它的父亲指针就指向自己,这也是作为原创 2017-12-27 10:54:04 · 712 阅读 · 0 评论 -
并查集基础入门
在计算机科学中,并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。有一个联合-查找算法(union-find algorithm)定义了两个用于此数据结构的操作:Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集。Union:将两个子集合并成同一个集合。并且,在图的相关算法中需要使用到并查集来实现一原创 2017-12-26 18:34:08 · 794 阅读 · 0 评论 -
图的寻路算法
目录 图的寻路算法前言寻路算法的思路核心代码详解测试用例完整代码获取博客文章版权声明 图的寻路算法前言前面我们探讨了有关于图的“深度优先遍历”算法,知道了如何利用dfs算法查找图中联通分量的个数,判断...原创 2018-09-11 17:07:31 · 3683 阅读 · 1 评论 -
图的广度优先遍历和最短路径算法
目录 图的广度优先遍历和最短路径算法前言广度优先遍历算法的探讨核心代码分析测试用例完整代码获取博客文章版权声明 图的广度优先遍历和最短路径算法前言上一次,我们讨论了有关图的深度优先遍历算法,既然二叉树有深度遍历算法,图也有深度遍历算法。那么二叉树还有广度优先遍历算法,图又有没有广度优先算法呢?答...原创 2018-09-12 19:33:42 · 25733 阅读 · 7 评论 -
图的深度优先遍历和联通分量
目录 图的深度优先遍历和联通分量深度优先遍历算法具体的搜索思路联通分量的计算关键代码实现完整代码获取 博客文章版权说明 图的深度优先遍历和联通分量前面已经探讨了图的两种表示方法:邻接表表示法和邻接矩阵表示法。这两种表示法分别用在不同的场景上。邻接矩阵表示法主要用在稠密图中,邻...原创 2018-09-10 18:10:26 · 3935 阅读 · 2 评论 -
有权图
目录 有权图前言带权图的数据结构边Edge的结构设计邻接矩阵的结构改造邻接表的结构改造完整代码获取博客文章版权说明 ...原创 2018-09-18 22:21:36 · 6362 阅读 · 0 评论 -
图的相邻节点迭代器
前面我们探讨了如何把一个抽象的图具体化的用代码去实现,讨论了图的邻接矩阵表示法和邻接表表示法,那么这一小节我们就来探讨一下图算法中最常见的操作,如何去遍历图中的各个节点相对应的临边呢?那么,通过一个点怎么去遍历与这个点相连的临边呢?例如,下图是图中一个节点与其相邻的各个节点,我们需要遍历0节点的邻节点。首先,对于邻接矩阵表示的图来说,我们只需要从表中遍历一遍0元素与其他原创 2018-01-30 15:02:07 · 1776 阅读 · 0 评论 -
二分搜索树的删除节点操作
本节我们来讨论一下对二叉搜索树的删除节点操作。首先,我们先来研究一下稍微简单一点的问题,如何删除二叉树中的最小值和最大值。例如上图的这一棵二叉树中,最小值节点和最大值节点都在哪里呢?我们可以很清楚的从图中看出,13是该树的最小节点,42是该树的最大节点,且13节点位于树的最左边,而42位于树的最右边,这难道是一种巧合吗?当然不是,首先,让我们来回忆一下二叉树的一个非常重要的性质。原创 2017-12-23 21:50:45 · 9765 阅读 · 3 评论 -
二叉堆的实现及其基本存储结构
二叉堆的概念:二叉堆是一种特殊的堆,二叉堆是完全二叉树或者是近似完全二叉树。 二叉堆的特性:父节点的键值总是保持固定的序关系于任何一个子节点的键值,且每个节点的左子树和右子树都是一个二叉堆。最大堆:当父节点的键值总是大于或等于任何一个子节点的键值时为最大堆。最小堆: 当父节点的键值总是小于或等于任何一个子节点的键值时为最小堆。二叉堆一般用数组来表示。类似于二叉树,每一个节点原创 2017-10-21 10:21:24 · 1391 阅读 · 0 评论 -
双路快速排序法
快速排序法的优化——双路快速排序上一节我们自己动手写的一个快速排序的算法,在随机数测试中表现得非常好,然而,我们在用高度有序的数组进行测试的时候,发现快速排序的效率变得异常的低下,比归并排序的效率低得多了,近似退回了O(n^2)的复杂度,这是为什么呢?首先让我们来分析一下归并排序的算法思想,归并排序之所以能够达到O(logn)的复杂度,多亏了递归,递归使得把数组不断的分小分到不能分为止,然后原创 2017-09-22 10:50:09 · 2186 阅读 · 1 评论 -
快速排序法qsort
快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。 让我们来开始理解一下快速排序算法的工作原理,正如上面一段百度百科对于快速排序的解释一样,快速排序可以用递归的思想去解决,原创 2017-09-21 17:11:59 · 446 阅读 · 0 评论 -
归并排序法
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。并过程为:比较a[i]和b[j]的大小,若a[i]≤b[j],则将第一个有序表中的元素a[i]复制到r[k]中,并原创 2017-09-20 10:54:22 · 484 阅读 · 0 评论 -
应用归并排序解决——求逆序对问题
前不久了解了归并排序,那么归并排序有没有什么特殊的应用呢?当然,我们可以运用归并排序来计算一个数组中有多少个逆序对数,然而,求逆序对数好像有更简单的办法,没错,如果一个大小为n的数组,我们可以用两个循环去比较数组中任意的两个值,然后累加出逆序对的数量,这样的算法虽然思路简单,但是解决数组数量较小的问题还是可以的,如果数组数量非常的大,那么作为一个O(n^2)复杂度的算法,计算机算出逆序对将要花费大原创 2017-09-26 22:20:24 · 748 阅读 · 0 评论 -
插入排序与选择排序的比较
插入排序insertsort的基本思想为每一位上的数字都与它前面的每个数字进行比较(顾名思义为把数组上的每一位数字都与其前面的数字进行比较并插入合适的位置),若前面的一个数字比它大,则交换它们两个的位置,然后再次比较该位置前一位数是否仍然比其大,若成立,则继续交换,否则轮到下一个检测位重复上面的操作,这样,所有位上面的数字都能够与其前面的数字进行比较并占到符合自己的位置,相比于选择排序,插入排...原创 2017-09-18 17:36:33 · 11092 阅读 · 1 评论 -
增加测试函数计算排序函数运行时间
要想比较两个函数的效率,最直观的方法莫过于比较两个排序函数排序同一个数组的时间,哪个函数花的时间更少,则该函数的运行效率相对较高,因此,我们需要在头文件中引入一个测试函数,能够较为直观的返回排序函数排序数组所花费的时间。以下为具体的代码实现:首先需要编写一个判断函数,用来判断数组是否已经排序完成,代码如下:template bool issorted(T arr[],int原创 2017-09-17 22:05:35 · 1070 阅读 · 0 评论 -
随机生成算法测试样例
每次测试一个算法时,都需要手工输入数据,这并不能很好的测试算法的效率,因为测试10个数据好测,但是如果要测试1000个100000个数据靠人工输入数据是不实际的,因此,我们需要编写一个能够随机生成特定数量的函数。以下为头文件sortTestHelper的源代码:(使用codeblock的童鞋需要在project>build options中添加头文件的路径,否则编译器将会报错无法找原创 2017-09-17 21:18:01 · 1456 阅读 · 0 评论 -
二叉堆的添加及删除元素方法实现
本次以最大堆来讨论二叉堆的添加以及删除元素的方法,对于最大堆,一定满足两个条件: 1. 二叉堆中的父节点的值一定大于其子节点的值。 2.二叉堆一定为一颗满二叉树。根据上面对于二叉堆的特点,我们可以很简单的找到给二叉堆添加元素的方法,首先二叉堆实际上是以数组来存储的,并且父节点的索引与子节点的索引都相互存在着一定的关系,因此对二叉堆的操作实际上就是对数组的操作。首先我们来原创 2017-10-21 10:38:28 · 3940 阅读 · 3 评论 -
优化的堆排序
优化的堆排序体现在不需要重新生成一个数组,而是直接原地进行所谓的堆排序。首先,对于一个杂乱的数组,我们首先对所有的非叶子节点进行shiftdown操作,使得堆顶arr[0]的元素为最大值,如下图所示:此时,通过heapfiy操作使得max指向的V即为数组中所有数字的最大值,对于一个按照从小到大排序的数组来说,最大值应该在数组的尾端然后第二大的值排在数组的倒数第二位,以此类推。。。。原创 2017-11-06 13:42:05 · 3546 阅读 · 2 评论 -
二叉搜索树的广度优先遍历
在上一节中,我们学习了二叉树的而前序遍历,中序遍历,以及后续遍历。但是我们发现,上述三种遍历方式都使用到了递归,因此无论哪种遍历都是一直往深处遍历到不能遍历为止。那么,有没有什么方法能够将每一层的节点遍历完然后在遍历下一层的节点呢?能够解决这种问题呢,因此,接下来我们就要开始讨论二叉树的广度优先遍历。对于广度遍历,我们需要额外引进一个辅助工具,那就是我们熟悉的数据结构中的一种:队列。让我们原创 2017-12-19 19:28:19 · 1335 阅读 · 0 评论 -
二分搜索树的遍历
对于一棵二叉树来说,如果我们想要把这棵树中的所有节点都给遍历一遍,那么我们就需要了解二叉树的遍历方式。二叉树的遍历方式分为以下三种:二叉树的一个简单的结构如下图所示: 对于其中的“前”。“中”,“后”,我们都可以理解为是根节点的访问顺序。遍历时,我们分为三个阶段:前 中 后对于前序遍历来说:也就是在前阶段访问根节点,中阶段访问左节点,后阶段访问右原创 2017-12-11 22:17:46 · 663 阅读 · 0 评论 -
二叉搜索树的节点插入,查找。
在讲解二分搜索树之前,我想先讲清楚一个东西,那就是递归,因为在后面的插入,查找操作都是利用递归去查找的,而且对于递归的理解也是一个难点,因此,以下是我对于递归的理解。,对于递归,我们不能用人脑去展开来想,所以,我们只需要把递归过程中的两个过程给想清楚就好了,一个是递归发生在终止条件的时候,还有一个是递归在不断缩小规模的过程中其中的一个情况,具体我们可以见下图:我们把最下面的原创 2017-12-04 21:19:34 · 1554 阅读 · 4 评论 -
二分搜索树的基础结构
上一节我们讲到了二分搜索法,这一节我们来讲讲二分搜索树。二分搜索树通常用于实现查找表这种结构,也可以称作“字典”,通过一个键(key),我们就能够查到其值(value),如果key都是整数,而且范围较小,我们则可以直接使用数组表示,但是如果key不能用整数表示或者key分散的较为疏散,则会浪费大量的空间,因此,我们需要一个查找表,最基础的方式也就是使用一个二叉搜索树。二分搜索树具有原创 2017-11-30 16:27:04 · 392 阅读 · 0 评论 -
二分查找法
二分查找又称折半查找,优点是比较次数少,查找速度快,平均性能好,占用系统内存较少。其缺点是要求待查表为有序表,且插入删除困难。因此,折半查找方法适用于不经常变动而查找频繁的有序列表。对于二分查找法,首先我们获取需要查找的数组的左边界l和右边界r,然后在通过左右边界计算出数组中中间的位置mid,但是计算mid不能简单的使用mid=(l+r)/2去计算,因为当l和r都接近于int的最大原创 2017-11-30 11:50:22 · 519 阅读 · 0 评论 -
索引堆
堆(heap)是一种常见的数据结构,经常用来实现优先队列。其中最常见的是二叉堆(binary heap)。由于它特殊的性质(二叉满树)所以可以用数组高效的实现。堆还能用来进行排序,堆排序(heap sort)具有快速(复杂度O(N * logN)),稳定的特点,尤其是非常稳定,因此适用于某些需要排序稳定性的场合。然而,普通的二叉堆却存在以下两个缺陷:1,在堆中的元素体积非常大的情况原创 2017-11-24 17:30:45 · 435 阅读 · 0 评论 -
数组连续交换的优化方法
我们经常在排序算法中会遇见这样的一种情况,数组中连续的两个值会不停的相互交换,类似于我们前面在插入排序和堆排序中的swap()优化,例如:在我们的插入排序算法中:原始的交换操作为:void insertsort(T arr[],int n) { for(int i=1;i<n;i++) { for(int j=i;j>0&&arr[j]<原创 2017-11-27 21:55:37 · 749 阅读 · 2 评论 -
最简单的排序——选择排序
最简单的排序—选择排序的实现选择排序是最基础的排序,基础的思想就是检测数组中的每一个成员,把其记做检测位,然后从检测位后面寻找最小数,用一个mindex标记其位置,在比较mindex标记的数字与检测位的数字大小,从而判断两者是否需要交换,最后每一个检测位都有一次更换位置的机会,待所有检测位都更换完位置后,数组就已经排序完成了,以下是具体的代码实现:#include using原创 2017-09-17 11:30:07 · 832 阅读 · 0 评论