二分查找算法
- 非递归
代码实现
1 | public class BinarySearchNoRecur { |
分治算法
汉诺塔问题
汉诺塔问题代码实现
1 | public class HanoiTower { |
动态规划算法
介绍
背包问题
背包问题代码实现
1 | public class knapsackProblem { |
KMP 算法
暴力算法 代码
1 | public class ViolentMatch { |
KMP 算法介绍
KMP 算法代码实现
1 | /** |
贪婪(贪心)算法
案例
代码实现
1 | /** |
普里姆算法
正确的思路,就是尽可能的选择少的路线,并且每条路线最小,保证总里程数最少
普里姆算法介绍
-
普利姆(Prim)算法求最小生成树,也就是在包含n个顶点的连通图中,找出只有(n-1)条边包含所有n个顶点的连通子图,也就是所谓的极小连通子图
-
普利姆的算法如下:
-
设G=(N,E)是连通网,T=(U,D)是最小生成树,V,U是顶点集合,E,D是边的集合
-
若从顶点u开始构造最小生成树,则从集合V中取出顶点u放入集合U中,标记顶点v的visited[u]=1
-
若集合U中顶点ui与集合V-U中的顶点v之间存在边,则寻找这些边中权值最小的边,但不能构成回路,将顶点vj加入集合U中,将边(ui,vj)加入集合D中,标记visited[vj]=1
-
重复步骤②,直到U与V相等,即所有顶点都被标记为访问过,此时D中有n-1条边
-
提示:单独看步骤很难理解,我们通过代码来讲解,比较好理解.
-
代码实现(修路问题)
1 | public class PrimAlgorithm { |
克鲁斯卡尔算法
介绍
- 克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法。
- 基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路
- 具体做法:首先构造一个只含个顶点的森林,然后依权值从小到大从连通网中选择边加入到森林中,并使森林中不产生回路,直至森林变成一棵树为止
图解说明
以城市公交站问题来图解说明克鲁斯卡尔算法的原理和步骤:
克鲁斯卡尔算法分析
根据前面介绍的克鲁斯卡尔算法的基本思想和做法,我们能够了解到,克鲁斯卡尔算法重点需要解决的以下两个问题:
问题一对图的所有边按照权值大小进行排序。
问题二将边添加到最小生成树中时,怎么样判断是否形成了回路。
问题一很好解决,采用排序算法进行排序即可。
问题二,处理方式是:记录顶点在"最小生成树"中的终点,顶点的终点是"在最小生成树中与它连通的最大顶点"。然后每次需要将一条边添加到最小生存树时,判断该边的两个顶点的终点是否重合,重合的话则会构成回路。
如何判断是否构成回路
公交站问题代码:
1 | import java.util.Arrays; |
迪杰斯特拉算法
应用场景:最短路径问题
-
战争时期,胜利乡有7个村庄(A,B,C,D,E,FG),现在有六个邮差,从G点出发,需要分别把邮件分别送到A,B,C,D,E,F六个村庄
-
各个村庄的距离用边线表示(权),比如A-B距离5公里
-
问:如何计算出G村庄到其它各个村庄的最短距离?
-
如果从其它点出发到各个点的最短距离又是多少?
迪杰斯特拉(Dijkstra)算法介绍
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个结点到其他结点的最短路径。它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。
迪杰斯特拉(Dijkstra)算法过程
设置出发顶点为v,顶点集合V{v1,v2,vi.},v到V中各顶点的距离构成距离集合Dis,Dis{d1,d2,di,…},Dis集合记录着v到图中各顶点的距离(到自身可以看作0,v到vi距离心应为di)
- 从Dis中选择值最小的di并移出Dis集合,同时移出V集合中对应的顶点vi,此时的v到vi即为最短路径
- 更新Dis集合,更新规则为:比较v到V集合中顶点的距离值,与v通过vi到V集合中顶点的距离值,保留值较小的一个(同时也应该更新顶点的前驱节点为ⅵ,表明是通过ⅵ到达的)
- 重复执行两步骤,直到最短路径顶点为目标顶点即可结束
代码实现
1 | import java.util.Arrays; |
弗洛伊德算法
弗洛伊德(Floyd)算法介绍
代码实现
1 | import java.util.Arrays; |
马踏棋盘算法
骑士周游问题
代码实现
1 | package com.algorithm.horse; |