自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(35)
  • 问答 (1)
  • 收藏
  • 关注

原创 学习笔记-马踏棋盘算法

马踏棋盘或骑士周游问题马踏棋盘算法也被称为骑士周游问题将马随机放在国际象棋的 8×8 棋盘 Board[0~7][0~7]的某个方格中,马按走棋规则(马走日字)进行移动。要求每个方格只进入一次,走遍棋盘上全部 64 个方格思路会使用到深度优先思想和类似迷宫问题的寻路策略问题,和八皇后问题也有相似。用一个二维数组建立整张棋盘。用另外一个二维数组保存棋盘的每一个位置是否走过马在棋盘上有一个初始位置,将这个位置设为已走过,并将步数设为1.获得在这个位置上,马下一步能走的位置集合。遍历集合里

2021-04-18 00:47:51 480

原创 学习笔记-弗洛伊德算法

弗洛伊德算法解决最短路径问题弗洛伊德算法和迪杰斯特拉算法都可以求解最短路径的问题,但区别是迪杰斯特拉会求出某个顶点到其他顶点的最短路径,而弗洛伊德算法会求出各个顶点到各个顶点的最短路径,最终结果采用一个二维表表示,而迪杰斯特拉算法只需要用一维表表示。最短路径问题弗洛伊德算法的核心思路将所有的顶点看作起始点-中间点-终点。如果起始点到中间的的路程加上中间点到终点的路程小于起始点到终点的直接路程,就更新此路程,并记录中间点。如BAC,如果BA+AC<BC,就更新BC的路程为BA+AC,更新BC

2021-04-16 22:45:30 322

原创 学习笔记-迪杰斯特拉算法求最短路径

求最短路径问题迪杰斯特拉算法迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个结点到其他结点的最短路径。它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。设置出发顶点为 v,顶点集合 V{v1,v2,vi…},v 到 V 中各顶点的距离构成距离集合 Dis,Dis{d1,d2,di…},Dis集合记录着 v 到图中各顶点的距离(到自身可以看作 0,v 到 vi 距离对应为 di)从 Dis 中选择值最小的 di 并移出 Dis 集合,同时移出 V

2021-04-14 19:07:52 1682

原创 学习笔记-普利姆算法和克鲁斯卡尔算法

普利姆算法修路问题修路问题实际上就是求最小生成树。最小生成树(Minimum Cost Spanning Tree),简称 MST。给定一个带权的无向连通图,如何选取一棵生成树,使树上所有边上权的总和为最小,这叫最小生成树。特点为:N 个顶点,一定有 N-1 条边包含全部顶点N-1 条边都在图中如图普利姆(Prim)算法求最小生成树,也就是在包含 n 个顶点的连通图中,找出只有(n-1)条边包含所有 n 个顶点的连通子图,也就是所谓的极小连通子图。他的思路,以修路问题为例:由于要

2021-04-10 23:59:35 1386

原创 学习笔记-贪心算法

贪心算法贪婪算法(贪心算法)是指在对问题进行求解时,在每一步选择中都采取最好或者最优(即最有利)的选择,从而希望能够导致结果是最好或者最优的算法。贪婪算法所得到的结果不一定是最优的结果(有时候会是最优解),但是都是相对近似(接近)最优解的结果。集合覆盖问题用贪心算法解决这个广播站问题的思路对于这个问题,总体思路是用一个hashset存放未覆盖的所有地区(第一次时就是所有的地区)对所有广播台进行循环,每次选择出一个key,它所对应的地区与未被覆盖的所有地区的交集是最大的,也就是它是这一次的最优选

2021-04-08 19:06:36 120

原创 学习笔记-KMP算法和暴力匹配算法

有两个字符串,原字符串和子字符串,在原字符串里寻找子字符串出现的位置,如果有,返回对应下标,如果没有,返回-1。解决这个问题可以用到两个方法,暴力匹配和KMP算法。暴力匹配法思路是:用两个下标,i指向原字符串,j指向子字符串。比较str1[i]和str2[j]相不相等,如果相等,就进入比较状态,比较后续的字符相不相等,把两个下标后移一位,比较两字符串的下一个字符相不相等,如果一直相等,当j移动到尾时,说明整个字符串都相等,这时就可以退出,输出位置。如果遇到了str1[i]和str2[j]不相等的情况,应

2021-04-06 00:06:01 301

原创 学习笔记-动态规划解决01背包问题

01背包问题解决思路可以通过画一张表来解决。如右图横轴表示限定最大重量,纵轴表示放入的物品,当指向吉他那一行时表示可以放入吉他,当指向音响那一行时表示能放入吉他和音响,当指向电脑那一行时表示能放入吉他、音响和电脑。表中的数字就表示那个条件下背包的最大价值。最后一个格子就代表最终解。填表的方式是,首先第一行第一列分别代表背包只有0磅和没有物品,全部填0。然后从G行1磅列开始,如果g的重量大于列限定的重量,显然装不进去,就填入该列上一行的数据,如果g的重量小于等于列限定的重量,说明能放进去,这时如

2021-04-05 17:31:44 251

原创 学习笔记-汉诺塔 分治算法

用分治算法解决汉诺塔分治法是一种很重要的算法。字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。这个技巧是很多高效算法的基础,如排序算法(快速排序,归并排序),傅立叶变换(快速傅立叶变换)……分治算法可以求解的一些经典问题 二分搜索 大整数乘法 棋盘覆盖 合并排序 快速排序 线性时间选择 最接近点对问题 循环赛日程表 汉诺塔分治法在每一

2021-04-04 21:24:05 158

原创 学习笔记-无向图的创建、深度优先遍历、广度优先遍历

图为什么要有图?线性表局限于一个直接前驱和一个直接后继的关系,树也只能有一个直接前驱也就是父节点当我们需要表示一种多对多的关系就需要用到图。图是一种数据结构,其中结点可以具有零个或多个相邻元素。两个结点之间的连接称为边。 结点也可以称为顶点。如图:图的常用概念:图的表示方式图有两种表示方式:邻接矩阵和邻接表。邻接矩阵邻接表创建图采用邻接矩阵的方法思路:用邻接矩阵创建图时,需要以下属性,一个list,用来存放图的所有顶点,顶点用字符串表示;一个二维数组int[][

2021-04-04 19:26:20 3342

原创 学习笔记-平衡二叉树

平衡二叉树对于数列{1,2,3,4,5,6},创建一颗普通的二叉排序树,会有一些问题:左子树全部为空,更像是链表而不是树插入同样很快,但查询的效率降低了。为了解决这个问题,提出了平衡二叉树,实际上是对二叉排序树的优化,可以提高查询的效率。平衡二叉树的特点是每棵左子树和右子树的高度相差不超过1。平衡二叉树的实现实际上,平衡二叉树是通过对二叉排序树旋转来完成的。而旋转的实际意义是更改二叉排序树的根节点,通过二叉排序树的创立规则,数组的第一个数就作为根节点,但这样有时会导致左右子树不平衡,这时

2021-04-01 00:31:39 157

原创 学习笔记-二叉排序树

二叉排序树对于二叉排序树的任何一个非叶子节点,要求左子节点的值比当前节点的值小,右子节点的值比当前节点的值大。如果有相同的值,可以将该节点放在左子节点或右子节点。二叉排序树的创建和遍历思路:比较节点的值,小于就放在左子节点,大于就放在右子节点,如果子节点不为空,就递归添加。 //添加节点 public void add(Node node){ if(node==null){ return; } if(node.

2021-03-30 22:59:52 371

原创 学习笔记-赫夫曼编码

赫夫曼编码赫夫曼编码也翻译为 哈夫曼编码(Huffman Coding),又称霍夫曼编码,是一种编码方式, 属于一种程序算法。赫夫曼编码是赫哈夫曼树在电讯通信中的经典的应用之一。赫夫曼编码广泛地用于数据文件压缩。其压缩率通常在 20%~90%之间。赫夫曼码是可变字长编码(VLC)的一种。Huffman 于 1952 年提出一种编码方法,称之为最佳编码。定长编码:把直接字符翻译成对应的Ascli编码。然后再把Ascli编码直接翻译成2进制。变长编码:比如统计各字符出现的次数,根据次数进行编码

2021-03-27 10:42:41 286

原创 学习笔记-创建赫夫曼树

赫夫曼树给定 n 个权值作为 n 个叶子结点,构造一棵二叉树,若该树的带权路径长度(wpl)达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree), 还有的书翻译为霍夫曼树。赫夫曼树是带权路径长度最短的树,权值较大的结点离根较近。一些概念:路径和路径长度:在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为 1,则从根结点到第 L层结点的路径长度为 L-1。结点的权及带权路径长度:若将树中结点赋给一个

2021-03-20 17:41:10 1407

原创 学习笔记-堆排序

堆排序堆排序运用到了树的思想。它仍然使用数组排序,并不创建树,但是排序时将数组看作一个完全二叉树,通过不断地构建大顶堆,将树顶元素与树尾元素交换,以树顶构建新的大顶堆来把整个数组从小到大排序。首先,将数字按从上到下,从左到右的顺序写成一颗完全二叉树,这样的树的特点是,对于父节点i(对应数组中的下标i),它的左子节点的数组下标为2*i+1,右子节点的数组下标为2*i+2。而最下面的非叶子节点的数组下标为arr.length/2-1进行堆排序大致分为两步,第一步是构建大顶堆,第二步是树顶元素与末尾元素交

2021-03-20 16:20:18 70

原创 学习笔记-线索化二叉树

线索化二叉树线索化二叉树的介绍:对于这个普通二叉树来说,节点8,10,14的左右指针是空的,6的右指针是空的,也就是说并没有充分的利用到所有的指针。那么,我们可以对该树线索化,使得空闲的指针被充分利用。中序线索化二叉树对于一个线索二叉树(如上图),我们让空余节点的左指针指向它的前驱结点,右指针指向它的后继节点。这样一来,该节点的左指针有可能指向它的左子树,也可能指向前驱节点,该节点的右指针有可能指向它的右子树,也有可能指向后继节点。所以,为了区分,我们在普通树节点的基础上设置leftType

2021-03-18 22:25:16 187

原创 学习笔记-顺序存储二叉树

顺序存储二叉树的概念简单来说是将数组以二叉树的形式进行前、中、后序遍历。这在堆排序中有所应用代码package tree;/** * 顺序存储二叉树 */public class ArrBinaryTreeDemo { public static void main(String[] args) { int[] arr={1,2,3,4,5,6,7}; ArrBinaryTree arrBinaryTree=new ArrBinaryTree(a

2021-03-18 20:19:41 82

原创 学习笔记-二叉树遍历、查找、删除

二叉树树结构出现的原因:二叉树示意图:常用用语:叶子节点:没有子节点的节点。节点的权:节点值。路径:从根节点找到该节点的一条路。树的高度:也就是最大层数。二叉树概念:每个节点最多只能有两个子节点称为二叉树。二叉树的节点分为左子节点和右子节点。三种遍历方式前序遍历:先输出父节点,然后遍历左子树右子树。即先输出该节点,如果左子节点不为空,递归遍历左子节点,如果右子节点不为空,递归遍历右子节点。中序遍历:先遍历左子树,然后输出父节点,然后遍历右子树。即如果左子节点不为空,递归遍历左

2021-03-17 21:30:36 117

原创 学习笔记-哈希表(散列)

哈希表(散列)解决一个问题:有一个公司,当有新的员工来报道时,要求将该员工的信息加入(id,性别,年龄,住址…),当输入该员工的 id 时,要求查找到该员工的所有信息.要求: 不使用数据库,尽量节省内存,速度越快越好=>哈希表(散列)散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。看第二张图可知,哈希表这种数

2021-03-17 20:02:29 94

原创 学习笔记-二分法查找

二分法查找要求必须是一个有序数组,才可以进行二分法查找。二分法运用到了递归回溯的思想。思路1.确定中间数的坐标 mid=(left+right)/22.如果中间数大于查询的数,说明查询的数在左边,向左递归继续查询,此时left不变,right变为mid-13.如果中间数小于查询的数,说明查询的数在右边,向右递归继续查询,此时right不变,left变为mid+13.如果都不是,那就说明中间数就是要找的数,将下标返回,也就是返回mid注意:结束递归有两种情况,一种是找到了数,直接返回下标,就是3

2021-03-16 19:54:46 164

原创 学习笔记-基数排序

基数排序将一个一维数组从大到小排列。基数排序是桶排序的扩展。它是一种稳定的排序方法,也就是说,排序之前相同大小的数字的位置次序在排序后并没有发生改变。同时,基数排序是一种用空间换时间的排序方法,当数据量过大时,java的堆内存耗尽,方法就不能使用了。思路基数排序的思路是:首先创建10个桶(二维数组),然后依次遍历原数组,取每一个数的个位数,并按个位数的大小放入桶中,比如5就放在下标为5的桶,17就放在下标为7的桶,729就放在下标为9的桶。遍历结束后,在按照顺序从桶中取出数据放回到原数组,也就是遍历桶

2021-03-12 18:24:59 83

原创 学习笔记-归并排序

归并排序将一个一维数组从小到大排序。归并排序采用了一种化繁为简、分而治之的思想。总的来说,是把一个数组先不断拆分,直到拆分到一个一个单独的元素,再把他们逐渐合并起来。这里边用到了递归回溯。合并思路先说合并的思路:合并时,将两个有序数组合并为一个,需要一个临时数组。先比较两数组的第一数字大小,把小的放入临时数组,然后比较小的数的后一位数与之前数的大小,同样把小的放在临时数组里,就这样一直比较,小的入临时数组,大的保留,索引++,然后再比较。直到两数组有一个到底或都到底。结束后,如果两数组有一个还没到

2021-03-11 23:29:00 103

原创 学习笔记-快速排序

快速排序将一个一维数组从小到大排列。思路快速排序利用了递归的思想。需要三个参数,数组本身,数组起始索引也就是0,数组最右索引,也就是数组长度-1。简单来说,快速排序的思想是这样的,先选择一个数作为基准数,把比它小的都移动到左边,把比它大的都移动到右边,然后针对左边这个子数组,再选择一个基准数,比它小的移到左边,比它大的移到右边,重复以上,直到子数组只剩1个数,这时候认为是有序的,返回到第一次,对右边子数组做同样的操作。具体来说。用left记录数组最左边的索引,用right记录数组最右边的索引(同

2021-03-10 22:42:11 49

原创 学习笔记-希尔排序

希尔排序将一个一维数组从小到大排序。希尔排序是插入排序的优化方式,因为普通的插入排序会存在一个问题,那就是当比较小的数字排在后面时,需要后移很多次才能完成。思路由此,希尔排序的思路是:引入一个步长的因素gep。之前的冒泡也好选择也好插入也好,都是之间跟之前或之后的一个数字进行比较,然后再++或–。而希尔排序简单来说就是跟步长之前的数字比较。它有两种形式,第一种是交换式。它的思路是:首先分多次进行排序,第一次的步长为数组长度÷2,第二次步长为数组长度÷2÷2。。。最后一次步长为1,也就是说步长第一次

2021-03-10 20:38:41 240

原创 学习笔记-插入排序

插入排序将一维数组从小到大排列。思路插入排序的思路是:把要排序的列表看成是一个有序表和一个无序表。一开始,有序表的长度是1,无序表是n-1。每次选无序表的第一个数插入到有序表的合适位置。具体来说,假如有一个长度为5的数组。第一次,认为第一个数是有序的,2到5是无序的,那么,选择第二个数,把它保存下来,让他依次与它之前的数作比较,也就是保存它的索引-1,遍历该索引,如果索引大于等于0(防止越界)且它比对应的数小,那就把这个数后移,把索引–。遍历结束后,此时索引+1(因为最开始把索引-1了)就是这个数的

2021-03-08 22:56:37 45

原创 学习笔记-选择排序

选择排序将一个一维数组从小到大排序。思路选择排序的思路是:首先认为数组的第一个数是最小的,保留它然后遍历它后面的数,跟它作比较,选择出最小的数和位置。遍历结束后,让这个最小的数和数组的第一位数交换,这样确定了第一个最小的数。之后重复这个过程,认为第二个数是最小的,遍历它后面的数和它作比较,结束后就会找到第二小的数和它的位置,与数组的第二位交换,这样就确定了两个数字的顺序。也就是说,一共要进行数组的长度-1次大循环,每一次循环确定一个数的位置,如果一共有5个数,那么4次就会全部排完。而每一个小循环都用

2021-03-07 23:11:38 102 1

原创 学习笔记-冒泡排序

冒泡排序把一个一维数组按从大到小或从小到大排列成顺序数组。以下为从小到大排序。思路冒泡排序的思路是,遍历这个数组,判断第n个和第n+1个数的大小,如果第n个数大于第n+1个数,就交换他们的位置,然后重复这个过程。假如数组的长度是5。第一次遍历会将最大的数移动到数组的最后,第二次遍历会将第二大的数移动到数组的倒数第二位,以此类推,长度是5时一共要遍历4次,因为第四次时,确定了第4大的数,最小的数自动就在最前面,也就是一共遍历length-1次。而第一次遍历时,交换位置的最大次数是4次,因为是和后一个数比

2021-03-07 20:35:49 200

原创 学习笔记-算法的时间复杂度

时间复杂度主要用来度量程序的运行速度。度量程序的运行速度有两种方法:事后统计的方法将两个程序实际运行一遍,比较运行的速度, 但是有两个问题:一是要想对设计的算法的运行性能进行评测,需要实际运行该程序,如果程序很大,运行比较慢,效率就很低了;二是所得时间的统计量依赖于计算机的硬件、软件等环境因素, 这种方式,要在同一台计算机的相同状态下运行,才能比较那个算法速度更快。事前估算的方法通过分析某个算法的时间复杂度来判断哪个算法更优。时间频度一个算法花费的时间与算法中语句的执行次数成正比例,哪个算

2021-03-06 22:06:01 159

原创 学习笔记-递归、迷宫、八皇后

递归简单来说,递归就是自己调用自己,每次传入不同的参数,可以解决复杂的问题。递归的调用规则每当程序执行到一个方法时,就开辟一个新的栈。每个栈中的数据(局部变量)是独立的,而引用类型的变量则是共享的。递归的原则执行一个方法时,就创建一个新的受保护的独立空间(栈空间)方法的局部变量是独立的,不会相互影响, 比如 n 变量如果方法中使用的是引用类型变量(比如数组),就会共享该引用类型的数据.递归必须向退出递归的条件逼近,否则就是无限递归,出现StackOverflowError。当一个方法执行

2021-03-06 20:21:06 73

原创 学习笔记-前缀、中缀和后缀表达式运算

前缀表达式前缀表达式是一种没有括号的算术表达式,与中缀表达式不同的是,其将运算符写在前面,操作数写在后面。前缀表达式也称为“波兰表达式”。例如,- 1 + 2 3,它等价于1-(2+3)。求值方法从右至左扫描表达式,若当前字符是数字则一直到数字串的末尾再记录下来,若为运算符,则将右边离得最近的两个“数字串”作相应运算,然后以此作为一个新的“数字串”并记录下来;扫描到表达式最左端时扫描结束,最后运算的值即为表达式的值。例如:对前缀表达式“- 1 + 2 3”求值,扫描到3时,记录下这个数字串,扫描到2

2021-02-19 00:51:38 339

原创 学习笔记-栈

栈栈(stack)是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊有序线性表。允许插入和删除的一端,为变化的一端,称为栈顶(Top),另一端为固定的一端,称为栈底(Bottom)。特点是后入先出。最先放入栈中元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除。栈的应用子程序的调用:在跳往子程序前,会先将下个指令的地址存到堆栈中,直到子程序执行完后再将地址取出,以回到原来的程序中。处理递归调用:和子程序的调用类似,只是除了储存下一

2021-02-18 00:12:05 92

原创 学习笔记-双向链表与环形链表

双向链表在单链表的基础上,每个节点增加了一个pre属性指向前一个节点。因为单链表只有next指针,因此只能单向遍历。而双向链表可以从前或从后遍历。另外也可以自我删除,也就是不用借助被删节点的前一个节点进行删除,直接靠自己就行。增删改查节点增加了pre指向前一个节点//双向链表的节点class StudentNode2{ public int no; public String name; StudentNode2 next; StudentNode2 pre;

2021-02-17 22:52:09 237

原创 学习笔记-单链表操作

求单链表中有效节点的个数/**** @param head 链表的头节点* @return 返回的就是有效节点的个数*/public static int getLength(HeroNode head) { if(head.next == null) { //空链表 return 0; } int length = 0; //定义一个辅助的变量, 这里我们没有统计头节点 HeroNode cur = head.next; while(cur != null) { lengt

2021-02-07 21:57:25 105

原创 学习笔记-单链表

单链表单链表是由多个节点组成的。它是一种有序的链式存储,也就是在各节点的存储位置不一定相连。同时,单链表分为有头节点和没有头节点,具体通过工作的细节自己选择。而节点由数据和next指针组成。其中,next指针的作用是指向下一个节点。在java中,节点可以表示成一个类class,一些成员变量用来存储数据,比如name,sex等等,而next指针同样表示为一个成员变量,类型为该类。指向下一个类变量。单链表的增删改查思路创建单链表首先需要创建节点类,类成员变量包括需要的数据属性和next指针。我这里创

2021-02-07 20:00:48 191

原创 学习笔记-队列

用java数组实现普通队列队列的特点:先进先出进入队列时从队列尾部进入,头部指针不发生变化,尾部指针向后一位出队列时从队列头部出,头部指针向后一位,尾部指针不变四个变量:max 表示队列容量arr 表示队列rear 尾部指针,初始为-1。指向队列最后一个元素,arr[rear]=最后一个元素front 头部指针,初始为-1。指向队列第一个元素的前一个位置,arr[front+1]=第一个元素判断队列是否满:rear=max-1 比如队列容量是4,数组的下标最大就是3,而因为rea

2021-02-07 01:11:20 110

原创 学习笔记-稀疏数组

稀疏数组当二维数组含有很多很多0项时,完全存储就需要消耗比较大的内存,于是我们可以将原数组改为稀疏数组进行存储,这样就节省了内存空间。形式是一个多行3列的二维数组。第一行用来存储原数组的行数、列数和有效数字个数。之后每一行分别存储一个有效数字的行数、列数和值。总行数为有效数字总数+1行。代码实现稀疏数组的创建:遍历原数组获得有效数字的个数num根据num初始化稀疏数组遍历原数组挨个赋值package DataStructure.SparseArray;import java.i

2021-02-06 22:24:35 71

空空如也

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

TA关注的人

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