自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

zp_zhang的博客

但愿不会饿死在技术这条路上...

  • 博客(35)
  • 资源 (2)
  • 收藏
  • 关注

原创 骑士周游(马踏棋盘)问题

1,马踏棋盘算法介绍马踏棋盘问题也被称为骑士周游问题将马随机放在国际象棋的8*8的棋盘中的某个格子里,马按照走棋规则(日子)进行移动。要求每个方格只进入一次,走遍64个方格2,马踏棋盘算法思路分析马踏棋盘算法是对图的深度遍历优先(DFS)的使用,通过递归加回溯实现对问题的解决,同时可使用贪心算法对最终算法进行优化从一点出发,对该点标记为已访问,并寻找该点通过日子走法,下一步可能访问的点坐标的集合如果存在对应的点坐标集合,并且存在点未访问,则按顺序对集合中的未访问坐标点进行递归访问,即重复

2020-07-18 22:28:06 1509

原创 弗洛伊德(Floyd)算(F算法)— 最短寻径问题

1,应用场景—最短寻径问题弗洛伊德算法与迪杰斯特拉算法解决问题完全一致,这是解题思路不同2,弗洛伊德算法介绍和迪杰斯特拉(Dijkstra)算法一样,弗洛伊德(Floyd)算法也是一种用于寻找加权图中顶点间最短路径的算法,该算法创始人为1978年图灵奖获得者罗比特 · 弗洛伊德与迪杰斯塔拉算法不同的是:迪杰斯特拉算法基于一个给定的出发顶点,求出该顶点到其他顶点的最短距离;弗洛伊德算法将每一个顶点作为出发顶点,所以需要求出每一个顶点到其他顶点的最短路径;迪杰斯特拉算法最后给出的结果是一个一维

2020-07-18 22:25:24 2240

原创 迪杰斯特拉(Dijkstra)算法(D算法):最短寻径问题

1,应用场景—最短寻径问题如图,存在7个村庄['A', 'B', C', 'D', 'E', 'F', 'G'],现在有6个邮差,从G点出发,需要分别赶往['A', 'B', C', 'D', 'E', 'F']六个村庄各个村庄的距离通过边的权值表示,如A <-> B = 5问:如何计算G村庄到其他村庄的最短距离注意:之前两篇说的普里姆算法和克鲁斯卡尔算法,都是求图内连接各个节点的最短路径;该问题是从一点出发,到各个顶点的最短路径。注意,此处是到各个顶点,不是总和的最短路径2,迪

2020-07-18 22:15:54 786

原创 克鲁斯卡尔(Kruskal)算法(K算法):公交站问题

1,应用场景—公交站问题某城市从新增的7个站点(A,B,C,D,E,F,G),现在需要把7个站点联通各个站点的距离用边权表示,比如A-B为12公里如何修路保证各个站点都能走通,并距离最短从图和问题可以看出,克鲁斯卡尔算法与普里姆算法解决的问题完成一致,只是解决问题的方式不同2,克鲁斯卡尔算法介绍克鲁斯卡尔算法,是用来求加权连通图的最小生成树的算法基本算法思想:按照边权值大小从小到大的顺序选取n - 1条边,并保证这n - 1条边不构成回路回路的判断标准是连接边的两个顶点的终点重合

2020-07-18 22:10:21 1202

原创 普里姆(Prim)算法(P算法):修路问题

1,应用场景—修路问题如图,此时有7个村庄['A', 'B', 'C', 'D', 'E', 'F', 'G'],现在需要把这7个村庄连通村庄之间的连接线表示可能修路的图示,权值表示举例此时,如果想要把7个村庄连通,怎么才能让连接的路程最短?此时应该尽可能的寻找少的线路,保证每条线路最短,最终达到整体线路最短(该部分有点类似贪心,但是贪心的最终结果不一定是最优解)2,最小生成树问题修路问题本身就是最小生成树(Minimum Cost Spanning Tree)问题,简称MST:给定一个

2020-07-18 22:07:10 2790

原创 贪心(Greed)算法:电台覆盖问题

1,应用场景—集合覆盖问题假设存在下面需要付费的广播电台,以及广播电台可以覆盖的地区。如何选择最少的电台,能实现区域的全覆盖2,贪心算法介绍贪心算法(贪婪算法)是指在对问题进行求解时,在每一步的选择中都选择最优解,从而期望能够导致结果是最优解的算法贪心算法所得到的结果不一定是最优解,但是一定是相对近似最优解的结果3,贪心算法最佳应用演示—集合覆盖问题已知存在多少电台,及电台对应的覆盖城市集合;并且各个电台所覆盖城市存在部分重复,需要最少几部电台可实现全覆盖首先汇总需要覆盖的城市,取

2020-07-18 22:04:42 636

原创 KMP算法:字符串匹配问题

1,暴力匹配算法1.1,基本介绍暴力匹配算法是对字符串及匹配子串的字符进行一一匹配,完全匹配后则说明字符串匹配假设存在字符串str和子串childStr,需要进行字符串的暴力匹配,才从头开始匹配此时取字符串str的索引位置i = 0,子串childStr的索引位置j = 0,用str[0]和childStr[0]进行比较,如果匹配,则进行i++, j++,并依次进行下一个字符匹配此时如果不匹配,说明i = 0处起始匹配是匹配不到的,则进行回溯,重新从i = 1处开始重复以上逻辑进行匹配但是此时

2020-07-18 22:03:00 240

原创 动态规划算法:背包问题

1,应用场景:背包问题问题描述:有一个容量为4磅的背包,需要装入如列表下的物品,在装入物品可重复和不可重复两种场景下,怎样才能使装入机制最大化商品名称商品重量商品价格吉他11500音响43000电脑320002,动态规划算法描述动态规划算法(Dynamic Programming)核心的思想是:将大问题划分为小问题进行解决,从而 一步步 获得最优解的处理算法(这个一步步是重点,等会就发现真是一步步)动态规范算法和分治算法类似,基本思想都是将待

2020-07-18 21:54:42 1177

原创 分治算法:汉诺塔问题

1,基本介绍分治算法是一种重要的算法。基本思想就是“分而治之”,将一个复杂的问题分为多个相似的子问题,然后再把子问题分为更小的子问题,直到最后子问题可以以一种最简单的方式直接求解,原问题的解即为子问题解的合并。分治算法的一些经典算法如:二分搜索,棋盘模型,合并排序,快速排序,汉诺塔等,以下将用汉诺塔举例2,基本步骤分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题解决:如果子问题规模较小,则直接求解;如果规模较大,则递归求解合并:将各个子问题的解合并为主问题的解3,汉

2020-07-18 21:49:26 323

原创 图:深度优先遍历&广度优先遍历

1,图的基本概念1.1,图的基本介绍线性表局限于一个直接前驱和一个直接后继的关系树也只能有一个直接前驱也就是父节点当需要多对多的关系的时候,就应该用到图1.2,图的常用概念顶点(Vertex)边(Edge)路径无向图有向图带权图1.3,图的表达方式图的表示方式有两张:二维数组表示(邻接矩阵),链表表示(邻接表)邻接矩阵:是表示图形中顶点之间相邻关系的矩阵,对于N个顶点的图而言,矩阵的row和column分别表示n个点邻接表邻接矩阵需要为每个顶点分配n个边的空

2020-07-18 21:43:15 225

原创 多路查找树

1,二叉树问题分析二叉树添加到内存中后,如果二叉树的节点少,那没有什么问题。但是如果二叉树的节点很多,在构建二叉树时就需要进行多次I/O操作,同时也会造成二叉树的高度很大,降低操作速度2,B树(2-3树,2-3-4树)2.1,B树基本介绍B树通过重新组织节点,降低树的高度,从而提高操作效率文件系统及数据库系统的设计者利用磁盘预读原理,将一个节点的大小设置为页的倍数(4K的倍数,MySQL一个节点为4页),这样每一个节点只需要一次I/O就可以完全载入将树的度M设置为1024,600E元素最多

2020-07-18 21:36:54 321

原创 树:红黑树

1,红黑树引入红黑树是对AVL树的补充。AVL树要求整个树的高度差不能超过1,超过后需要进行左旋或者右旋操作再次对树进行平衡,虽然这样能够解决二叉树退化为链表的缺点,将查询的时间复杂度控制在O(logN),但却不是最佳的;因为AVL树对高度差的控制太严,在需要频繁进行插入/删除的场景中,AVL需要频繁进行树平衡调整,影响整体性能,为了解决这个问题,引入红黑树2,红黑树性质性质1:每个节点要么是黑色,要么是红色性质2:根节点是黑色性质3:每个叶子节点(NIL)是黑色,NIL表示虚拟节点性质4

2020-07-18 21:30:23 216

原创 树:平衡二叉树

1,二叉排序树问题对于一个有序数组{1, 2, 3, 4, 5},其生成的二叉排序树如下;由图可见,最终形成一个类似单链表形式的二叉树,对插入速度没有影响,但是对于查询速度明显减低,不能通过BST进行查询,时间复杂度为O(n);需要对二叉排序树这种现象进行优化,则引入平衡二叉树(AVL)2,平衡二叉树基本介绍平衡二叉树也叫平衡二叉搜索树(self-balancing binary search tree),又被称为AVL树,可以保证较高的二分查找效率平衡二叉树特点:是一颗空树或者左右子树的高

2020-07-18 21:09:50 152

原创 树:赫夫曼树&赫夫曼编码

1,赫夫曼树1.1,赫夫曼树基本介绍及相关概念给定n个权值作为n个叶子节点,构造一颗二叉树,若该树的**带权路径长度(WPL)**达到最小,称这样的的二叉树为最优二叉树,也称为赫夫曼树,或者哈夫曼树、霍夫曼树赫夫曼树是带权路径长度最短的数,权值较大的节点离根较近路径和路径长度:在一棵树中,从一个节点往下可以达到的孩子和孙子节点之间的通路,称为路径;通路中分支的数量称为路径长度;若规定根节点的层数为1,则从根节点到第L层节点的路径长度为L - 1节点的权及带权路径长度:若将树中的节点赋给一个有意义

2020-07-18 21:03:24 457

原创 树:线索化二叉树

1,线索化二叉树基本介绍线索化二叉树是对普通二叉树的扩展,对于普通二叉树而言,一个节点会包含一个数据域以及指向左右子节点的位置索引;但是对于叶子节点来讲,左右子节点的位置索引并没有被利用到,线索二叉树充分利用该部分节点,普通二叉树如下:在n个节点的二叉树中总共含有n - 1(类似5指向2表示一个位置指向)个位置指向,即2n(每一个节点有左右两个指针域)个指针域,这样对于一个二叉树来讲,共有2n - (n - 1) = n + 1个空指针域。利用二叉树的空指针域,根据前/中/后序不同遍历方式存储前驱节

2020-07-18 20:50:53 459

原创 树:顺序存储二叉树

1,线索化二叉树基本介绍顺序存储二叉树是堆排序的基本思想从数据存储来看,数组存储方式和树的存储方式可以相互转换,即数组可以转换为树,树也可以转换为数组,如下图所示顺序存储二叉树只考虑完全二叉树,并且元素间存在函数对应关系第n个元素的左子节点为:index = 2 * n + 1第n个元素的右子节点为:index = 2 * n + 2第n个元素的父节点为:index = (n - 1)/ 2其中n表示在完全二叉树中的第几个元素,同时也表示数组中的索引下标,从0开始2,代码实现p

2020-07-18 20:41:52 483

原创 树:二叉排序树

1,二叉树基本概念树分为很多种,其中每一个节点最多有两个节点的树形式称之为二叉树二叉树的子节点分为左节点和父节点;对于一个父节点来说,可以单独存在左子节点或者右子节点,也可以同时存在左右子节点如果二叉树的所有叶子节点都在最后一层,并且节点总数 = 2 ^ n - 1,n为最大层数,则该二叉树可以称之为满二叉树如果二叉树的所有叶子节点都在最后一层或者倒数第二层,且最后一层的叶子节点在左边连续,倒数第二层的叶子节点在右边连续,则称之为完全二叉树2,二叉树遍历2.1,前序遍历先输出当前节

2020-07-18 20:40:10 311

原创 哈希表(散列)

1,哈希表基本介绍散列表(HashTable,也叫哈希表),是根据关键码值(Key Value)而进行访问的数据结构。也就是说,通过关键码值映射到表中的一个位置来访问记录,以加快查找的速度。这个映射函数叫散列函数,存放记录的数组叫做散列表基本数据结构为 数组 + 链表;通过键值获取到数组索引位置,存储到数组中,数组中该索引位置如果已经存在数据,则在该索引位置上构造链表。2,哈希表示意图3,哈希表代码实现package com.self.datastructure.hash;import

2020-07-18 20:28:24 977

原创 查找算法:斐波拉契查找

1,斐波拉契查找基本介绍黄金分割点:是把一条线段分为两部分,使得一部分与全程之比等于另一部分跟这部分之比,比例近似于0.618,称为黄金分割点斐波那契数列{1, 1, 2, 3, 5, 8 ... n, m, m + n}发现两个相邻数的比例,无限接近于0.618斐波那契查找,依旧基于数组是有序数组,并使数组长度与斐波那契数组元素相匹配,之后类似于二分查找方式,以斐波那契数组的数组特性f[k] = f[k - 1] + f[k - 2],对目标数组取中值middle = low+ f[k - 1]

2020-07-18 20:25:17 653 2

原创 数据查找算法:插值查找

1,插值查找基本介绍插值查找的前提条件是目标数组为有序数组插值查找类似于二分查找,不同的是插值查找每次从自适应middle索引开始查找插值查找其实就是对二分查找middle索引求值的优化,求值公式为:int middle = left + (right - left) * (target - arr[left]) / (arr[right] - arr[left])二分查找到插值查找的公式演进如下:举例说明:如果存在一个长度为20, 值为1-20的顺序一维数组,需要查找到1所在的索引

2020-07-18 20:21:38 292

原创 数组查找算法:线性查找、二分查找

1,线性查找1.1,线性查找基本介绍线性查找就是基本的循环查找,遍历每一个元素进行比对,返回匹配结果1.2,线性查找代码实现package com.self.datastructure.search;/** * 线性查找 * * @author PJ_ZHANG * @create 2020-03-13 15:18 **/public class SeqSearch { public static void main(String[] args) { i

2020-07-18 20:19:05 245

原创 排序算法:堆排序

堆排序基本思想是顺序存储二叉树1,堆排序基本介绍堆排序是利用堆这种数据结构设计的一种排序算法,类似与选择排序,它的最慢,最好,平均时间复杂度都是O(nlogn),是不稳定排序堆是具有以下性质的完全二叉树:每个节点的值都大于或者等于它的左右子节点的值,称为大顶堆;每个节点的值都小于或者等于左右的值,称为小顶堆;注意此处没有要求左右节点的顺序关系一般升序使用大顶堆,降序使用小顶堆2,堆排序基本思想首先根据大顶堆的基本格式,将无序数组转换为符合大顶堆规则的数组此处转换先根据算法获取到最.

2020-07-18 20:10:12 122

原创 排序算法:基数排序

1,基数排序基本介绍基数排序(Radix Sort)属于分配式排序,又称桶子法或者Bin Sort,它是通过键值的各个位的值,将要排序的数组分配到对应桶中,达到排序的左右基数排序属于稳定性排序,同时也是效率较高的稳定性排序,基数排序是对桶排序的扩展基数排序基本思想:将所有待比较的数值统一为同样的数位长度(长度不足前位补零);然后,从低位开始,依次进行一次排序。按照基本排序规则,等所有位数全部比较完成后,数据就是一个有序数列首先初始化一个二维数组,第一维表示桶的个数,从0-9共有10个桶,第二维表

2020-07-18 20:03:10 206

原创 排序算法:归并排序

1,归并排序介绍归并排序就是利用归并的思想实现的排序方式,采用了经典的分治策略;分治法就是先将问题分成一些小的问题然后递归求解,治阶段就是将分阶段得到的各答案补在一起,即分而治之;归并排序处理次数 = 元素个数 - 1基本思想:归并排序为分和治两个部分,其中分部分是对数组元素完全拆分,拆无可拆时开始治;治就是对已经拆散的数据按顺序依次重组起来;此外,归并排序需要一个额外空间进行有序数据重组首先拆,归并排序拆的目的是将数组中的每一 元素都拆分出来拆完之后治,治是对拆开的每一组数据依次排序,并最终

2020-07-18 19:59:11 89

原创 排序算法:快速排序

1,快速排序介绍快速排序是对冒泡排序的一种改进,通过一趟排序将要排序的数据分为独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小;然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,通过多次递归,达到整个数组为有序数组。基本思想:先从数组中随机取一个参考值分别从数组两边(left, right)开始取数据进行比较如果left取到的数据大于基准数据, right取到的数据小于基准数据, 则进行交换交换完成后, 对两侧数据分别与参考值比较, 如果与参考值相等,

2020-07-18 19:54:10 197

原创 排序算法:希尔排序

1,希尔排序基本介绍希尔排序也是一种插入排序,是简单拆入排序经过改进之后的一个更高效的版本,也称为缩小增量排序基本思想:对数组元素进行两两分组, 分为 (N / 2) 组, 且一组的两个数据间步长为 (N / 2)对各组数据进行插入排序, 使各组数据有序对上一步有序的数据, 继续分为 (N / 2 / 2) 组, 每组数据步长为 (N / 2 / 2)继续对该组数进行插入排序, 使各组数据有序以此类推, 直到 (N / 2 / … / 2 = 1) 时, 不能继续分组, 最后进行插入排序,

2020-07-18 19:51:16 121

原创 排序算法:插入排序

1,插入排序基本介绍插入排序属于内部排序法,是对欲排序的元素以插入的方式找到合适的位置,以达到排序的目的基本思想:将一个数组在物理上划分为有序数组部分和无序数组部分;开始时有序数组部分只包括第一个元素,从第二个元素开始,依次与前一个元素进行比较并确定其位置第二个元素排序完成后,此时有序数组部分有两个元素(第一,二个元素),无序数组部分是其他元素;继续从第三个元素开始,依次类推,直到所有元素比较完毕,注意元素插入到有序数据部分时,有序数组内部位于该元素后续位置的元素需要统一后移;插入排

2020-07-18 19:48:35 94

原创 排序算法:选择排序

1,选择排序基本介绍选择排序也属于内部排序,是从欲排序的数据中,按指定的规则选出某一元素,再依规定交换位置已达到排序的目的选择排序的基本思想是:从第一个数开始,依次与后面的数进行比较,选出最小的数并进行位置交换,之后进行第二个和后续所有数据的比较和交换,以此类推。通过length - 1次后,获取到一个从小到大排列的有序数组选择排序的时间复杂度为O(n^2)。大数据量下,相对于冒泡排序性能会好很多,主要是因为选择排序比冒泡排序内部交换更少2,选择排序示例3,选择排序代码演示package

2020-07-18 19:44:04 105

原创 排序算法:冒泡排序

1,冒泡排序基本介绍冒泡排序是对数组的第一个元素开始,从前往后(从最小下标开始)依次比较相邻两个元素的值,若发现逆序则进行交换,使得较大的元素逐渐往后移动优化:在排序过程中,可以设置标志位,如果存在某一趟比较没有发生元素的位置互换,则说明数组已经有序,直接退出,无需再进行后续比较冒泡排序的时间复杂度为O(n^2)2,冒泡排序示例3,冒泡排序代码演示package com.self.datastructure.sort;import java.util.Arrays;/** * 排

2020-07-18 19:40:33 232

原创 排序算法:时间复杂度和空间复杂度

1,常见的排序分类排序算法分为内部排序和外部排序两种,内部排序是完全在内存中完成,外部排序需要使用外部介质,如硬盘,中间件等,此次排序算法只考虑内部排序内部排序算法可分为:插入排序(直接插入排序,希尔排序),选择排序(简单选择排序,堆排序),交换排序(冒泡排序,快速排序),归并排序,基数排序等2,时间复杂度时间频度:一个算法花费的时间与算法中语句的执行次数成正比例,哪个算法中语句的执行次数多,它花费的时间就多。一个算法中语句的执行次数称为语句频度或者时间频度,记为T(n)。在数量及运算下,时间

2020-07-18 14:24:19 1412

原创 递归:回溯,迷宫,八皇后问题

1,递归的基本原则执行一个方法时,就创建一个新的受保护的独立空间(JVM栈)方法的局部变量是独立的,不会相互影响方法中使用的是引用类型变量,则会基于地址共享发生改变递归必须向退出递归的条件逼近,否则就是无限递归,最终栈溢出StackOverflowError当一个方法执行完毕,或者遇到return,就会返回,遵守谁调用,就将结果返回给谁,同时当结果返回时,该方法也执行完毕2,迷宫问题迷宫问题注意,当前路径不是最短路径package com.self.datastructure.rec

2020-07-18 14:14:20 123

原创 栈:栈及计算器模拟

1,栈基本介绍栈是一种先入后出的有序列表栈限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端,为变化的一端,称为栈顶,另一端为固定的一端,称为栈底出栈(pop)入栈(push)原理图如下:2,栈模拟代码演示2.1,数组模拟package com.self.datastructure.stack;import lombok.Data;/** * 通过数组模拟栈数据结构 * @author LiYanBin * @create 2020-0

2020-07-18 14:07:38 268

原创 链表:单向链表,双向链表,单向环形链表

1,单向链表1.1,单项链表基本介绍链表是以节点的方式存储链表的每个节点都包括data域和next域,指向下一个节点链表的各个节点不一定都是连续存储的链表分为带头结点的链表和不带头结点的链表1.2,单向链表示意图1.3,单向链表代码实现package com.self.datastructure.linked;import lombok.Data;/** * @author LiYanBin * @create 2020-01-08 14:06 **/public cl

2020-07-18 13:52:43 210

原创 队列:数组模拟实现

1,队列基本介绍队列是一个有序列表,可以用数组或者链表来实现队列遵循先入先出(FIFO)原则2,数组模拟队列队列本身是有序列表,若使用数组的结构存储队列,则队列的声明如上图因为队列的输入和输出是分别从两端处理,所以需要两个对应的索引数据write和read,而write和read 随着数据的输入和输出移动在添加数据时,需要考虑的问题数组是否已经初始化,如果没有初始化,初始化为默认长度,比如10判断写索引 + 写数据 > 读索引,成立则数组越界,此处通过总数判断写索引到索引末

2020-07-18 13:41:17 116

原创 数组:稀疏数组

1,实际问题分析在编写五子棋程序时,需要进行存盘和读盘操作,对棋盘现状进行保存,因为该二维数组的很多值是默认值0,所以直接通过棋盘的二维数组记录可能会记录很多没有意义的数据,此时可以使用稀疏数组进行存储。如图:2,基本介绍当一个数组中大部分元素为0,或者为某一固定值,可以使用稀疏数组保存该数组稀疏数组首先会记录该二维数组一共有几行,几列,有多少个值之后把具有不同值的元素的行列及值记录在一个小规模的数组中,从而缩小数组的规模如上图:稀疏数组第一个元素([0])表示当前二组数

2020-07-18 13:37:46 160 1

Java数据结构学习笔记

Java数据结构学习笔记

2020-12-18

Java设计模式学习笔记

Java设计模式学习笔记

2020-12-18

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除