java克鲁斯卡尔算法,JS实现最小生成树之克鲁斯卡尔(Kruskal)算法

克鲁斯卡尔算法打印最小生成树:

构造出所有边的集合 edges,从小到大,依次选出筛选边打印,遇到闭环(形成回路)时跳过。

267c8a75080faa16a02ace49d4566a06.png

JS代码:

1 //定义邻接矩阵

2 let Arr2 =[3 [0, 10, 65535, 65535, 65535, 11, 65535, 65535, 65535],4 [10, 0, 18, 65535, 65535, 65535, 16, 65535, 12],5 [65535, 18, 0, 22, 65535, 65535, 65535, 65535, 8],6 [65535, 65535, 22, 0, 20, 65535, 65535, 16, 21],7 [65535, 65535, 65535, 20, 0, 26, 65535, 7, 65535],8 [11, 65535, 65535, 65535, 26, 0, 17, 65535, 65535],9 [65535, 16, 65535, 65535, 65535, 17, 0, 19, 65535],10 [65535, 65535, 65535, 16, 7, 65535, 19, 0, 65535],11 [65535, 12, 8, 21, 65535, 65535, 65535, 65535, 0],12 ]13

14 let numVertexes = 9, //定义顶点数

15 numEdges = 15; //定义边数

16

17 //定义图结构

18 functionMGraph() {19 this.vexs = []; //顶点表

20 this.arc = []; //邻接矩阵,可看作边表

21 this.numVertexes = null; //图中当前的顶点数

22 this.numEdges = null; //图中当前的边数

23 }24 let G = new MGraph(); //创建图使用

25

26 //创建图

27 functioncreateMGraph() {28 G.numVertexes = numVertexes; //设置顶点数

29 G.numEdges = numEdges; //设置边数

30

31 //录入顶点信息

32 for (let i = 0; i < G.numVertexes; i++) {33 G.vexs[i] = 'V' + i; //scanf('%s'); //ascii码转字符 //String.fromCharCode(i + 65);

34 }35 console.log(G.vexs) //打印顶点

36

37 //邻接矩阵初始化

38 for (let i = 0; i < G.numVertexes; i++) {39 G.arc[i] =[];40 for (j = 0; j < G.numVertexes; j++) {41 G.arc[i][j] = Arr2[i][j]; //INFINITY;

42 }43 }44 console.log(G.arc); //打印邻接矩阵

45 }46

47 functionEdge() {48 this.begin = 0;49 this.end = 0;50 this.weight = 0;51 }52

53 functionKruskal() {54 let n, m;55 let parent = []; //定义一数组用来判断边与边是否形成环路

56 let edges = []; //定义边集数组

57

58 for (let i = 0; i < G.numVertexes; i++) {59 for (let j = i; j < G.numVertexes; j++) { //因为是无向图所以相同的边录入一次即可,若是有向图改为0

60 if (G.arc[i][j] != 0 && G.arc[i][j] != 65535) {61 let edge = newEdge();62 edge.begin =i;63 edge.end =j;64 edge.weight =G.arc[i][j];65 edges.push(edge);66 }67 }68 }69

70 edges.sort((v1, v2) =>{71 return v1.weight -v2.weight72 });73

74 console.log('**********打印所有边*********');75 console.log(edges);76

77 for (let i = 0; i < G.numVertexes; i++) {78 parent[i] = 0;79 }80

81 for (let i = 0; i < edges.length; i++) {82 n =Find(parent, edges[i].begin)83 m =Find(parent, edges[i].end)84 if (n != m) { //假如n与m不等,说明此边没有与现有生成树形成环路

85 parent[n] =m;86 console.log("(%s,%s) %d", G.vexs[edges[i].begin], G.vexs[edges[i].end], edges[i].weight);87 }88 }89 }90

91

92 function Find(parent, f) { //查找连线顶点的尾部下标

93 while (parent[f] > 0) {94 f =parent[f]95 }96 returnf;97 }98

99 createMGraph();100 console.log('*********打印最小生成树**********')101 Kruskal();

打印结果:

f7d2eb1a92b381a2a777edad6ca5783a.png

代码部分过程解析:

52a9357f82dd2f13e2d7d8f60a46037b.png

当i=7时,第82行,调用Find函数,会传入参数edges[7].begin=5。此时第94行,parent[5]=8>0,所以f=8,再循环得parent[8]=6。因parent[6]=0 所以Find返回后第82行得到n=6。而此时第83行,传入参数edges[7].end=6得到m=6。此时n=m,不再打印,继续下一循环。这就告诉我们,因为(V5,V6)使得边集合A形成了环路。因此不能将它纳入到最小生成树中。

当i=8时,与上面相同,由于边(V1,V2)使得边集合A形成了环路,因此不将它纳入最小生成树。

克鲁斯卡尔算法主要针对边展开,时间复杂度为 O(elog e),e为图的边数,普利姆算法的时间复杂度为O(n²),n为最小生成树的边数。所以,边数少(稀疏图)用克鲁斯卡尔算法,边数多(稠密图)用普利姆算法。

参考文献: 程杰《大话数据结构》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值