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

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

JS代码:

 //定义邻接矩阵
let Arr2 = [
[0, 10, 65535, 65535, 65535, 11, 65535, 65535, 65535],
[10, 0, 18, 65535, 65535, 65535, 16, 65535, 12],
[65535, 18, 0, 22, 65535, 65535, 65535, 65535, 8],
[65535, 65535, 22, 0, 20, 65535, 65535, 16, 21],
[65535, 65535, 65535, 20, 0, 26, 65535, 7, 65535],
[11, 65535, 65535, 65535, 26, 0, 17, 65535, 65535],
[65535, 16, 65535, 65535, 65535, 17, 0, 19, 65535],
[65535, 65535, 65535, 16, 7, 65535, 19, 0, 65535],
[65535, 12, 8, 21, 65535, 65535, 65535, 65535, 0],
] let numVertexes = 9, //定义顶点数
numEdges = 15; //定义边数 // 定义图结构
function MGraph() {
this.vexs = []; //顶点表
this.arc = []; // 邻接矩阵,可看作边表
this.numVertexes = null; //图中当前的顶点数
this.numEdges = null; //图中当前的边数
}
let G = new MGraph(); //创建图使用 //创建图
function createMGraph() {
G.numVertexes = numVertexes; //设置顶点数
G.numEdges = numEdges; //设置边数 //录入顶点信息
for (let i = 0; i < G.numVertexes; i++) {
G.vexs[i] = 'V' + i; //scanf('%s'); //ascii码转字符 //String.fromCharCode(i + 65);
}
console.log(G.vexs) //打印顶点 //邻接矩阵初始化
for (let i = 0; i < G.numVertexes; i++) {
G.arc[i] = [];
for (j = 0; j < G.numVertexes; j++) {
G.arc[i][j] = Arr2[i][j]; //INFINITY;
}
}
console.log(G.arc); //打印邻接矩阵
} function Edge() {
this.begin = 0;
this.end = 0;
this.weight = 0;
} function Kruskal() {
let n, m;
let parent = []; //定义一数组用来判断边与边是否形成环路
let edges = []; //定义边集数组 for (let i = 0; i < G.numVertexes; i++) {
for (let j = i; j < G.numVertexes; j++) { //因为是无向图所以相同的边录入一次即可,若是有向图改为0
if (G.arc[i][j] != 0 && G.arc[i][j] != 65535) {
let edge = new Edge();
edge.begin = i;
edge.end = j;
edge.weight = G.arc[i][j];
edges.push(edge);
}
}
} edges.sort((v1, v2) => {
return v1.weight - v2.weight
}); console.log('**********打印所有边*********');
console.log(edges); for (let i = 0; i < G.numVertexes; i++) {
parent[i] = 0;
} for (let i = 0; i < edges.length; i++) {
n = Find(parent, edges[i].begin)
m = Find(parent, edges[i].end)
if (n != m) { //假如n与m不等,说明此边没有与现有生成树形成环路
parent[n] = m;
console.log("(%s,%s) %d", G.vexs[edges[i].begin], G.vexs[edges[i].end], edges[i].weight);
}
}
} function Find(parent, f) { //查找连线顶点的尾部下标
while (parent[f] > 0) {
f = parent[f]
}
return f;
} createMGraph();
console.log('*********打印最小生成树**********')
Kruskal();

打印结果:

代码部分过程解析:

 
当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为最小生成树的边数。所以,边数少(稀疏图)用克鲁斯卡尔算法,边数多(稠密图)用普利姆算法。

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

JS实现最小生成树之克鲁斯卡尔(Kruskal)算法的更多相关文章

  1. 图的生成树(森林)(克鲁斯卡尔Kruskal算法和普里姆Prim算法)、以及并查集的使用

    图的连通性问题:无向图的连通分量和生成树,所有顶点均由边连接在一起,但不存在回路的图. 设图 G=(V, E) 是个连通图,当从图任一顶点出发遍历图G 时,将边集 E(G) 分成两个集合 T(G) 和 ...

  2. 洛谷P3366【模板】最小生成树-克鲁斯卡尔Kruskal算法详解附赠习题

    链接 题目描述 如题,给出一个无向图,求出最小生成树,如果该图不连通,则输出orz 输入输出格式 输入格式: 第一行包含两个整数N.M,表示该图共有N个结点和M条无向边.(N<=5000,M&l ...

  3. 最小生成树之克鲁斯卡尔(kruskal)算法

    #include <iostream> #include <string> using namespace std; typedef struct MGraph{ string ...

  4. 图解最小生成树 - 克鲁斯卡尔(Kruskal)算法

    我们在前面讲过的<克里姆算法>是以某个顶点为起点,逐步找各顶点上最小权值的边来构建最小生成树的.同样的思路,我们也可以直接就以边为目标去构建,因为权值为边上,直接找最小权值的边来构建生成树 ...

  5. 克鲁斯卡尔(Kruskal)算法求最小生成树

    /* *Kruskal算法求MST */ #include <iostream> #include <cstdio> #include <cstring> #inc ...

  6. 克鲁斯卡尔(Kruskal)算法

    # include <stdio.h> # define MAX_VERTEXES //最大顶点数 # define MAXEDGE //边集数组最大值 # define INFINITY ...

  7. MST最小生成树及克鲁斯卡尔(Kruskal)算法

    最小生成树MST,英文名如何拼写已忘,应该是min spaning tree吧.假设一个无向连通图有n个节点,那么它的生成树就是包括这n个节点的无环连通图,无环即形成树.最小生成树是对边上权重的考虑, ...

  8. 最小生成树——Kruskal(克鲁斯卡尔)算法

    [0]README 0.1) 本文总结于 数据结构与算法分析, 源代码均为原创, 旨在 理解 Kruskal(克鲁斯卡尔)算法 的idea 并用 源代码加以实现: 0.2)最小生成树的基础知识,参见 ...

  9. 最小生成树---Prim算法和Kruskal算法

    Prim算法 1.概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点(英语:Vertex (gra ...

随机推荐

  1. HTTP调用接口方法

    1.创建接口调用方法类 package cn.com.victorysoft.sjzx.Message; import java.io.BufferedReader; import java.io.I ...

  2. 73. 矩阵置零 leetcode JAVA

    题目: 给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0.请使用原地算法. 示例 1: 输入: [   [1,1,1],   [1,0,1],   [1,1,1] ...

  3. 八.linux系统文件属性知识

    1.文件属性权限是12位,现在只看9位,其中每3个一组,为:属主权限.属组权限.其他权限,其中r可读,w可写,x可执行,如图: 2.文件属性之软硬链接   linux系统中有两种链接,为硬链接(ln) ...

  4. java下载文件注意点

    前台: 不建议使用ajax,可以使用window.location.href 后台: 三个参数--> response path filename--filename如果要防止乱码,可以用Str ...

  5. luoguP5074 Eat the Trees

    https://www.luogu.org/problemnew/show/P5074 插头 $ dp $ 入门题 如果你还不会插头 $ dp $ 请右转 洛谷插头dp题解 虽然是入门题但还是逃不过分 ...

  6. JAVA数组的定义方式

    JAVA中,数组有以下几种定义方式: 1.先定义数组中元素的个数,然后再进行元素赋值 int[] a=new int[2]; a[0]='a'; a[1]='b';a[2]='c'; 2.元素个数与元 ...

  7. tcping测试端口是否畅通

    https://elifulkerson.com/projects/tcping.php 下载tcping.exe 执行exec文件或者放到C:\Window目录下执行 tcping IP 端口

  8. numpy 常用方法2

    Python之Numpy基础   一个栗子 >>> import numpy as np >>> a = np.arange(15).reshape(3, 5) & ...

  9. vscode 本地调试nodejs

    1.首先通过node-inspect插件可以debug   nodejs ,先起nodejs服务,再启用node-inpector服务 安装调试器 npm install -g node-inspec ...

  10. 插入排序 思想 JAVA实现

    已知一个数组 60.28.41.39.6 .18 .14.28.49.31 利用插入排序算法进行排序 插入排序是一个运行时间为O(N²)的排序算法. 算法思想  60.28.41.39.6 .18 . ...