第十六章 常用算法
1.二分查找算法(非递归)
package binarysearchnorecursion;
public class Test {
public static void main(String[] args) {
int[]arr= {1,2,3,4,5};
System.out.println(binarySearch(arr, 5));
}
public static int binarySearch(int[]arr,int target) {
int left=0;
int right=arr.length-1;
while(left<=right) {
int mid=(left+right)/2;
if(arr[mid]==target) {
return mid;
}else if(arr[mid]>target) {
right=mid-1;
}else {
left=mid+1;
}
}
return -1;
}
}
2.分治算法
package binarysearchnorecursion;
public class Test {
public static void main(String[] args) {
hanoiTower(3, 'a', 'b', 'c');
}
public static void hanoiTower(int num,char a,char b,char c) {
//如果只有一个盘
if(num==1) {
System.out.println("第一个盘从"+a+"->"+c);
}else {
//如果我们有n>=2情况,我们总是可以将下面看成两个盘1最下面的一个盘 2.上面的所有盘
//1.先把 最上面的所有盘A-B 移动过程中会使用到c
hanoiTower(num-1, a, c, b);
//2.把最下面的盘A->c
System.out.println("第"+num+"个盘子从"+a+"->"+c);
//3.把B所有盘从B->C 移动过程中使用到a
hanoiTower(num-1, b, a, c);
}
}
}
3.动态规划算法
public class Test {
public static void main(String[] args) {
int[]w= {1,4,3};//物品重量
int[]val= {1500,3000,2000};//物品价值
int m=4;//背包一共有多沉
int n=val.length;//一共多少个物品
int[][]v=new int[n+1][m+1];//创建一个二维数组表示物品的价值
int[][]path=new int[n+1][m+1];//表示物品重量
for(int i=0;i<v.length;i++) {//把第一行设置为0
v[i][0]=0;
}
for(int i=0;i<v[0].length;i++) {//把第一列设置为0
v[0][i]=0;
}
for(int i=1;i<v.length;i++) {//横向遍历
for(int j=1;j<v[0].length;j++) {//纵向遍历
if(j<w[i-1]) {//当背包容量小于物品重量时
v[i][j]=v[i-1][j];//将此时的值设为上一个物品的同容量的价值
}else {//背包容量大于等于当前遍历到的物品重量
if(v[i-1][j]<val[i-1]+v[i-1][j-w[i-1]]) {//判断上一个阶段的价值和当前物品+上减去当前物品重量剩余重量能拿的最大价值的物品
v[i][j]=val[i-1]+v[i-1][j-w[i-1]];//大于直接赋值
path[i][j]=1;//表示装了新物品
}else {
v[i][j]=v[i-1][j];//小于直接用上一个
}
}
}
}
for(int i=0;i<v.length;i++) {//遍历背包
for(int j=0;j<v[0].length;j++) {
System.out.print(v[i][j]+" ");
}
System.out.println();
}
int i=path.length-1;//因为之前为了添加0增加过1
int j=path[0].length-1;
while(i>0&&j>0) {
if(path[i][j]==1) {
System.out.println("第"+i+"个商品放入背包");
j-=w[i-1];//背包还剩余容量能放入的最大价值
}
i--;//上一个商品
}
}
}
4.暴力匹配(字符串匹配问题)
public class Test{
public static void main(String[] args) {
String str2="abc你好呀!嘻嘻嘻";
String str1="埃及地啊你噶,abc你好呀!嘻嘻嘻";
int i=violenceMatch(str1, str2);
System.out.println();
}
public static int violenceMatch(String str1,String str2) {
char[]a1=str1.toCharArray();//把`字符串变成字符数组
char[]a2=str2.toCharArray();
int s1Len=a1.length;//求出长度
int s2Len=a2.length;
int i=0;
int j=0;
while(i<s1Len&&j<s2Len) {
if(a1[i]==a2[j]) {
i++;
j++;
}else {
i=i-(j-1);//因为i要向前移动一个不能全部减掉
j=0;
}
}
if(j==s2Len) {//匹配完成,返回str1起始位置
return i-j;
}else {
return -1;//没找到
}
}
}
5.KMP算法介绍 (字符串匹配问题)
import java.util.Arrays;
public class Test{
public static void main(String[] args) {
String str="AAAAB";//要匹配的字符串
int []arr=kmpNext(str);
System.out.println(Arrays.toString(arr));
}
public static int[] kmpNext(String dest) {
int []next=new int[dest.length()];//用next装前缀和后缀长度
next[0]=0;//1个数的时候匹配值肯定为0
for(int i=1,j=0;i<dest.length();i++) {//开始遍历
while(j>0&&dest.charAt(i)!=dest.charAt(j)) {//kmp算法核心 j移到0的位置或者i和j的数相等
j=next[j-1];//在j在的位置向前移动一个位置
}
if(dest.charAt(i)==dest.charAt(j)) {
j++;
}
next[i]=j;//前缀和后缀最大相同长度
}
return next;
}
}
例子
public class Test {
// 计算部分匹配表(前缀表)
private static int[] computeLPSArray(String pattern) {
int m = pattern.length();
int[] lps = new int[m];
int length = 0;
int i = 1;
lps[0] = 0;
while (i < m) {
if (pattern.charAt(i) == pattern.charAt(length)) {
length++;
lps[i] = length;
i++;
} else {
if (length != 0) {
length = lps[length - 1];
} else {
lps[i] = 0;
i++;
}
}
}
return lps;
}
// 使用 KMP 算法进行字符串匹配
public static void KMPSearch(String text, String pattern) {
int n = text.length();//求出文本字符串长度
int m = pattern.length();//要匹配的字符串长度
int[] lps = computeLPSArray(pattern);//将匹配字符串的部分匹配值计算出来
int i = 0;//便利文本字符串
int j = 0;//遍历匹配字符串
while (i < n) {//文本字符串还有值
if (pattern.charAt(j) == text.charAt(i)) {//如果相等两个字符串都向前推进
j++;
i++;
}
if (j == m) {//如果j=m代表匹配成功了,结束匹配
System.out.println("在索引 " + (i - j) + " 处找到匹配");//i-j即开始匹配的位置
} else if (i < n && pattern.charAt(j) != text.charAt(i)) {//如果i小于n并且遇到了不匹配的字符
if (j != 0) {//j不等于0的话
j = lps[j - 1];//让j等于j-1个前面已经匹配上的值
} else {//j=0,i++表示没有部分匹配值
i++;
}
}
}
}
public static void main(String[] args) {
String text = "ABCABCD";
String pattern = "ABCD";
KMPSearch(text, pattern);
}
}
6.贪心算法
介绍:
-
贪心算法是指在对问题进行求解时,在每一步选择中都采取最好或者最优(即最优利)的选择,从而希望能够导致结构是最好或者最优的算法
-
贪心算法所得到的结果不一定是最优的结果(有时候会是最优解),但是都是相对近似(接近)最优解的结果
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
public class Test{
public static void main(String[] args) {
//创建广播电台,放入到Map broadcasts
HashMap<String,HashSet<String>> broadcasts=new HashMap<String,HashSet<String>>();
//将各个电台放入到broadcasts
HashSet<String> hashSet1=new HashSet<>();//创建广播用来存放可以广播的地区
hashSet1.add("北京");
hashSet1.add("上海");
hashSet1.add("天津");
HashSet<String> hashSet2=new HashSet<>();
hashSet2.add("广州");
hashSet2.add("北京");
hashSet2.add("深圳");
HashSet<String> hashSet3=new HashSet<>();
hashSet3.add("成都");
hashSet3.add("上海");
hashSet3.add("杭州");
HashSet<String> hashSet4=new HashSet<>();
hashSet4.add("上海");
hashSet4.add("天津");
HashSet<String> hashSet5=new HashSet<>();
hashSet5.add("杭州");
hashSet5.add("大连");
broadcasts.put("K1", hashSet1);//将广播和序号联系上
broadcasts.put("K2", hashSet2);
broadcasts.put("K3", hashSet3);
broadcasts.put("K4", hashSet4);
broadcasts.put("K5", hashSet5);
//allAreas 存放所有的地区
HashSet<String> allAreas=new HashSet<String>();
allAreas.add("北京");
allAreas.add("上海");
allAreas.add("天津");
allAreas.add("广州");
allAreas.add("深圳");
allAreas.add("成都");
allAreas.add("杭州");
allAreas.add("大连");
//创建ArrayList ,存放选择的电台集合 selects
ArrayList<String> selects=new ArrayList<>();
//定义一个临时的集合,在遍历过程中,存放遍历过程中的电台覆盖的地区和当前还没有覆盖的地区的交集
HashSet<String> tempSet=new HashSet<String>();
String maxKey=null;
//定义给maxKey,保存在一次遍历过程中,能够覆盖最大未覆盖的地区对应的电台的key
//如果maxKey不为null,则会加入到selects
while(allAreas.size()!=0) {//当没遍历完所有地区时一直遍历
maxKey=null;
for(String key:broadcasts.keySet()) {//遍历广播
tempSet.clear();
HashSet<String> areas=broadcasts.get(key);//得到这个广播可以覆盖的地区
tempSet.addAll(areas);//临时可以覆盖的地区
tempSet.retainAll(allAreas);//保留tempset里面的地区在allareas存在的地区
if(tempSet.size()>0&&
(maxKey==null||tempSet.size()>broadcasts.get(maxKey).size()))//当tempset>0时并且maxkey=null或者当前遍历到的广播比之前覆盖最多的还多
{
maxKey=key;//将当前电视台放入
}
}
if(maxKey!=null) {//如果不为空,则添加到select
selects.add(maxKey);
allAreas.removeAll(broadcasts.get(maxKey));//并移除在area中所有maxkey的地区
}
}
System.out.println("得到的结果是"+selects);
}
}
7.普里姆算法 Prim
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
public class Test{
public static void main(String[] args) {
char[]data= {'A','B','C','D','E','F','G'};//创建7个结点
int verxs=data.length;//一共有几个结点
int[][]weight=new int[][] {//10000表示不是相邻的结点,正常的表示相距的距离
{10000,5,7,10000,10000,10000,2},
{5,10000,10000,9,10000,10000,3},
{7,10000,10000,10000,10000,8,2},
{10000,5,7,10000,10000,10000,2},
{10000,5,7,10000,10000,10000,2},
{10000,5,7,10000,10000,10000,2},
{10000,5,7,10000,10000,10000,2}
};
MGraph graph=new MGraph(verxs);//构建一个图
MinTree minTree=new MinTree();
minTree.createGraph(graph, verxs, data, weight);
minTree.showGraph(graph);
}
}
class MinTree{
public void createGraph(MGraph graph,int verxs,char[]data,int[][]weighit) {
int i,j;
for(i=0;i<verxs;i++) {//以结点的个数为遍历条件
graph.data[i]=data[i];//放入数据
for(j=0;j<verxs;j++) {//内循环放入二维数组图
graph.weight[i][j]=weighit[i][j];
}
}
}
public void showGraph(MGraph graph) {
for(int[]link:graph.weight) {
System.out.println(Arrays.toString(link));
}
}
}
class MGraph{
int verxs;//表示图的节点个数
char[]data;//存放节点数据
int[][]weight;//存放边
public MGraph(int verxs)
{
this.verxs=verxs;
data=new char[verxs];
weight=new int[verxs][verxs];
}
}
package binarysearchnorecursion;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
public class Test{
public static void main(String[] args) {
char[]data= {'A','B','C','D','E','F','G'};
int verxs=data.length;
int[][]weight=new int[][] {
{10000,5,7,10000,10000,10000,2},//A
{5,10000,10000,9,10000,10000,3},//B
{7,10000,10000,10000,8,10000,10000},//C
{10000,9,10000,10000,10000,4,10000},//D
{10000,10000,8,10000,10000,5,4},//E
{10000,10000,10000,4,5,10000,6},//F
{2,3,10000,10000,4,6,10000}//G
};
MGraph graph=new MGraph(verxs);
MinTree minTree=new MinTree();
minTree.createGraph(graph, verxs, data, weight);
minTree.showGraph(graph);
minTree.prime(graph, 0);
}
}
class MinTree{
public void createGraph(MGraph graph,int verxs,char[]data,int[][]weighit) {
int i,j;
for(i=0;i<verxs;i++) {
graph.data[i]=data[i];
for(j=0;j<verxs;j++) {
graph.weight[i][j]=weighit[i][j];
}
}
}
public void showGraph(MGraph graph) {
for(int[]link:graph.weight) {
System.out.println(Arrays.toString(link));
}
}
public void prime(MGraph Graph,int v) {
int visited[]=new int[Graph.verxs];
visited[v]=1;
int h1=-1;
int h2=-2;
int minWeight=10000;
for(int k=1;k<Graph.verxs;k++) {
for(int i=0;i<Graph.verxs;i++) {
for(int j=0;j<Graph.verxs;j++) {
if(visited[i]==1&&visited[j]==0&&Graph.weight[i][j]<minWeight)
{
minWeight=Graph.weight[i][j];
h1=i;
h2=j;
}
}
}
System.out.println("边"+Graph.data[h1]+"边"+Graph.data[h2]);
visited[h2]=1;
minWeight=10000;
}
}
}
class MGraph{
int verxs;//表示图的节点个数
char[]data;//存放节点数据
int[][]weight;//存放边
public MGraph(int verxs)
{
this.verxs=verxs;
data=new char[verxs];
weight=new int[verxs][verxs];
}
}
8.克鲁斯卡尔算法 Kruskal
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
public class Test{
private static final int INF = Integer.MAX_VALUE;//表示两个节点之间不是通路
public static void main(String[] args) {
char[]vertexs= {'A','B','C','D','E','F','G'};//七个站点
int matrix[][]= {//打印七个站点之间的距离
{0,12,INF,INF,INF,16,14},
{12,0,10,INF,INF,7,INF},
{INF,10,0,3,5,6,INF},
{INF,INF,3,0,4,INF,INF},
{INF,INF,5,4,0,2,8},
{16,7,6,INF,2,0,9},
{14,INF,INF,INF,8,9,0}};
KruskalCase k=new KruskalCase(matrix, vertexs);//将矩阵和站点传进去
k.print();
}
}
class KruskalCase{
private static final int INF=Integer.MAX_VALUE;
private int [][]matrix;
private char[]vertexs;
private int edgeNum;
public KruskalCase(int[][]matrix,char[]vertexs) {
int len=vertexs.length;//获得站点个数
this.matrix=new int[len][len];//创建和站点个数一样的二维数组
this.vertexs=new char[len];//创建站点
for(int i=0;i<len;i++) {//循环便利使得vertexs里面是站点
this.vertexs[i]=vertexs[i];
}
for(int i=0;i<len;i++) {//遍历二维数组
for(int j=0;j<len;j++) {
this.matrix[i][j]=matrix[i][j];
}
}
for(int i=0;i<len;i++) {//边的个数
for(int j=0;j<len;j++) {
if(this.matrix[i][j]!=INF) {
edgeNum++;
}
}
}
}
public void print() {//打印二维数组
System.out.println("邻接矩阵为:");
for(int i=0;i<vertexs.length;i++) {
for(int j=0;j<vertexs.length;j++) {
System.out.print(matrix[i][j]+" ");
}
System.out.println();
}
}
}
import java.util.Arrays;
// 表示图的边
class Edge {
char start;
char end;
int weight;
public Edge(char start, char end, int weight) {
this.start = start;
this.end = end;
this.weight = weight;
}
@Override
public String toString() {
return "开始:" + start + "结束" + end ;
}
}
// 实现Kruskal算法
class KruskalCase {
private static final int INF = Integer.MAX_VALUE;
private int[][] matrix;
private char[] vertices;
private int edgeCount;
public KruskalCase(int[][] matrix, char[] vertices) {
int len = vertices.length;
this.matrix = new int[len][len];
this.vertices = new char[len];
// 复制顶点数组
System.arraycopy(vertices, 0, this.vertices, 0, len);
// 复制邻接矩阵
for (int i = 0; i < len; i++) {
System.arraycopy(matrix[i], 0, this.matrix[i], 0, len);
}
// 计算边的数量
for (int i = 0; i < len; i++) {
for (int j = i + 1; j < len; j++) {
if (this.matrix[i][j] != INF) {
edgeCount++;
}
}
}
}
// 打印邻接矩阵
public void printMatrix() {
System.out.println("邻接矩阵为:");
for (int i = 0; i < vertices.length; i++) {
for (int j = 0; j < vertices.length; j++) {
System.out.printf("%10d", matrix[i][j]);
}
System.out.println();
}
}
// 对边进行排序
public void sortEdges(Edge[] edges) {
Arrays.sort(edges, (e1, e2)
-> e1.weight - e2.weight);
}
// 获取顶点的位置
private int getVertexPosition(char ch) {
for (int i = 0; i < vertices.length; i++) {//遍历全部顶点
if (vertices[i] == ch) {//得到接受进来的顶点对应的索引
return i;
}
}
return -1;
}
// 获取所有边
public Edge[] getEdges() {//打印所有边
int index = 0;
Edge[] edges = new Edge[edgeCount];
for (int i = 0; i < vertices.length; i++) {
for (int j = i + 1; j < vertices.length; j++) {
if (matrix[i][j] != INF) {
edges[index++] = new Edge(vertices[i], vertices[j], matrix[i][j]);
}
}
}
return edges;
}
// 查找顶点所在的集合
private int find(int[] parent, int i) {
if (parent[i] == i) {
return i;
}
return find(parent, parent[i]);
}
// 合并两个集合
private void union(int[] parent, int x, int y) {
int xroot = find(parent, x);//
int yroot = find(parent, y);
parent[xroot] = yroot;//把前面结点索引变成后面索引
}
// 实现Kruskal算法
public Edge[] kruskalMST() {
Edge[] result = new Edge[vertices.length - 1];//vertices.length个点,-1个边
Edge[] edges = getEdges();//得到所有边
sortEdges(edges);//给所有边按weight从小到大排序
int[] parent = new int[vertices.length];
for (int i = 0; i < vertices.length; i++) {
parent[i] = i;
}
int e = 0;//表示最小生成树的边
int i = 0;
while (e < vertices.length - 1 && i < edges.length) {//当还存在边并且没有遍历到顶点-1条边
Edge next_edge = edges[i];//获得第一条边
int x = find(parent, getVertexPosition(next_edge.start));//求出该点对应的最终尾节点
int y = find(parent, getVertexPosition(next_edge.end));//如上
if (x != y) {//如果相同证明这条边构成了回路不执行
result[e++] = next_edge;
union(parent, x, y);
}
i++;
}
return result;
}
}
// 测试类
public class Test {
public static void main(String[] args) {
char[] vertices = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
int[][] matrix = {
{0, 12, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 16, 14},
{12, 0, 10, Integer.MAX_VALUE, Integer.MAX_VALUE, 7, Integer.MAX_VALUE},
{Integer.MAX_VALUE, 10, 0, 3, 5, 6, Integer.MAX_VALUE},
{Integer.MAX_VALUE, Integer.MAX_VALUE, 3, 0, 4, Integer.MAX_VALUE, Integer.MAX_VALUE},
{Integer.MAX_VALUE, Integer.MAX_VALUE, 5, 4, 0, 2, 8},
{16, 7, 6, Integer.MAX_VALUE, 2, 0, 9},
{14, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, 8, 9, 0}
};
KruskalCase kruskal = new KruskalCase(matrix, vertices);
kruskal.printMatrix();
System.out.println("=");
Edge[] edges = kruskal.getEdges();
System.out.println("所有边: " + Arrays.toString(edges));
System.out.println("=");
kruskal.sortEdges(edges);
System.out.println("所有边: " + Arrays.toString(edges));
System.out.println("=");
Edge[] mst = kruskal.kruskalMST();
System.out.println("最小生成树的边: " + Arrays.toString(mst));
}
}
9.迪杰斯特拉算法
import java.util.Arrays;
import javax.xml.transform.Templates;
public class Test {
public static void main(String[] args) {
char[]vertex= {'A','B','C','D','E','F','G'};
int[][] matrix=new int[vertex.length][vertex.length];
final int N=65535;
matrix[0]=new int[] {N,5,7,N,N,N,2};
matrix[1]=new int[] {5,N,N,9,N,N,3};
matrix[2]=new int[] {7,N,N,N,8,N,N};
matrix[3]=new int[] {N,9,N,N,N,4,N};
matrix[4]=new int[] {N,N,8,N,N,5,4};
matrix[5]=new int[] {N,N,N,4,5,N,6};
matrix[6]=new int[] {2,3,N,N,4,6,N};
//创建Graph对象
Graph garph=new Graph(vertex,matrix);
garph.showGraph();
System.out.println();
garph.dsj(6);
garph.showDisjsta();
}
}
class Graph{
private char[]vertex;//顶点数组
private int[][]matrix;//邻接矩阵
private VisitedVertex vv;
public Graph(char[]vertex,int[][]matrix) {
this.matrix=matrix;
this.vertex=vertex;
}
public void showDisjsta() {
vv.show();
}
//显示图
public void showGraph() {
for(int[]link:matrix) {
System.out.println(Arrays.toString(link));
}
}
public void dsj(int index) {
vv=new VisitedVertex(vertex.length, index);
update(index);//更新index顶点到周围定带你的距离和前驱节点
for(int j=1;j<vertex.length;j++) {//遍历完所有节点,优先获得距离出发节点近的
index=vv.updateArr();//选择并返回新的结点第一次循环得到距离出发顶点最近的索引
update(index);//更新index下标顶点到周围顶点的距离和周围顶点的前驱节点
}
}
// 更新index下标顶点到周围顶点的距离和周围顶点的前驱节点
public void update(int index) {
int len=0;
//根据遍历我们的邻接矩阵matrix[index]行
for(int j=0;j<matrix[index].length;j++) {//遍历所有顶点
//len 出发顶点到index顶点的距离+从index顶点到j顶点的距离之和
len=vv.getDis(index)+matrix[index][j];
//如果j顶点没有被访问过,并且len小于出发顶点到j顶点的距离,就需要更新
if(!vv.in(j)&&len<vv.getDis(j)) {//j顶点没有被访问过并且len<出发顶点到j顶点的距离
vv.updatePre(j, index);
vv.updateDis(j, len);
}
}
}
}
class VisitedVertex{
//记录各个顶点是否访问过,1表示访问过,0表示未访问,会动态更新
public int[]already_arr;
//每个下标对应的值为前一个顶点的下标,会动态更新
public int[]pre_visited;
//记录从出发顶点到其他所有顶点的距离,比如G为出发顶点,就会记录G到其他顶点的距离
//会动态更新,求的最短距离就会存放到dis
public int[]dis;
public VisitedVertex(int length,int index) {
this.already_arr=new int[length];
this.pre_visited=new int[length];
this.dis=new int[length];
//初始化 dis数组
Arrays.fill(dis, 65535);
this.already_arr[index]=1;//设置出发顶点被访问过
dis[index]=0;//设置出发顶点的访问距离为0
}
/*判断index顶点是否被访问过*/
public boolean in(int index) {
return already_arr[index]==1;
}
// 更新出发顶点到index的距离
public void updateDis(int index,int len) {
dis[index]=len;
}
// 更新顶点的前驱为index结点
public void updatePre(int pre,int index) {
pre_visited[pre]=index;
}
// 返回出发顶点到index顶点的距离
public int getDis(int index) {
return dis[index];
}
public int updateArr() {
int min=65535,index=0;
for(int i=0;i<already_arr.length;i++) {//遍历得到g周围最近的结点的索引并把该结点标志为访问过
if(already_arr[i]==0&&dis[i]<min) {//节点没被访问过并且到g可以连接的到
min=dis[i];//让min等于该节点到出发顶点的距离
index=i;//
}
}
already_arr[index]=1;
return index;
}
//显示最后的结果
//即将三个数组情况输出
public void show() {
System.out.println("==================");
//输出already_arr
for(int i:already_arr) {
System.out.print(i+" ");
}System.out.println();
for(int i:pre_visited) {
System.out.print(i+" ");
}System.out.println();
for(int i:dis) {
System.out.print(i+" ");
}
System.out.println();
char[]vertex= {'A','B','C','D','E','F','G'};
int count=0;
for(int i:dis) {
if(i!=65535) {
System.out.print(vertex[count]+"("+i+")");
}else {
System.out.println("N ");
}count++;
}
System.out.println();
}
}
10.弗洛伊德算法(Floyd)
package binarysearchnorecursion;
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
char[]vertex= {'A','B','C','D','E','F','G'};
int[][]matrix=new int[vertex.length][vertex.length];
final int N=65535;
matrix[0]=new int[] {0,5,7,N,N,N,2};
matrix[1]=new int[] {5,0,N,9,N,N,3};
matrix[2]=new int[] {7,N,0,N,8,N,N};
matrix[3]=new int[] {N,9,N,0,N,4,N};
matrix[4]=new int[] {N,N,8,N,0,5,4};
matrix[5]=new int[] {N,N,N,4,5,0,6};
matrix[6]=new int[] {2,3,N,N,4,6,0};
Graph graph=new Graph(vertex.length,matrix,vertex);
graph.show();
}
}
class Graph{
private int[][] dis;//保存各个顶点到各个顶点的距离 最后结果也保留在这里
private char []vertex;//保存顶点数组
private int[][]pre;//保存目标顶点的前驱顶点
public Graph(int length,int[][]matrix,char[]vertex) {
this.dis=matrix;
this.vertex=vertex;
this.pre=new int[length][length];
//对pre数组进行初始化
for(int i=0;i<length;i++) {
Arrays.fill(pre[i], i);
}
}
public void show() {
char[]vertex= {'A','B','C','D','E','F','G'};
for(int k=0;k<dis.length;k++) {
for(int i=0;i<dis.length;i++) {
System.out.print(vertex[pre[k][i]]+" ");
}System.out.println();
for(int i=0;i<dis.length;i++) {
System.out.print("("+vertex[k]+")"+"到"+vertex[i]+"的距离是"+dis[k][i]+" ");
}System.out.println();
System.out.println();
}
}
public void floyd() {
int len=0;
for(int k=0;k<dis.length;k++) {//k为中间顶点
for(int i=0;k<dis.length;i++) {
for(int j=0;k<dis.length;j++) {
len=dis[i][k]+dis[k][j];
if(len<dis[i][j]) {
dis[i][j]=len;//更新距离
pre[i][j]=pre[k][j];//更新前驱节点
}
}
}
}
}
}