当前位置: 首页 > 编程笔记 >

Java语言中的Kruskal算法

梁昊天
2023-03-14
本文向大家介绍Java语言中的Kruskal算法,包括了Java语言中的Kruskal算法的使用技巧和注意事项,需要的朋友参考一下

Kruskal算法是一种贪婪算法,其工作原理如下:

1.它在图形中创建一组所有边。

2.虽然上述集合不是空的,并且并非所有顶点都被覆盖,

  • 它从该组中删除最小重量边

  • 它检查此边缘是形成一个循环还是仅连接2棵树。如果形成一个循环,则丢弃该边,否则将其添加到树中。

3.完成上述处理后,我们便有了最小生成树。

为了实现此算法,我们需要2个以上的数据结构。

首先,我们需要一个优先级队列,我们可以使用它来使边缘保持排序,并在每次迭代中获得所需的边缘。

接下来,我们需要一个不相交的集合数据结构。不相交集数据结构(也称为联合查找数据结构或合并查找集)是一种数据结构,该数据结构跟踪被划分为多个不相交(不重叠)子集的元素集。每当我们将新节点添加到树中时,我们都会检查它们是否已连接。如果是,那么我们有一个周期。如果否,我们将使边缘的两个顶点并合。这会将它们添加到相同的子集中。

让我们看一下UnionFind或DisjointSet数据结构&minsu;的实现。

示例

class UnionFind {
   constructor(elements) {
      //断开连接的组件数量
      this.count = elements.length;

      //跟踪连接的组件
      this.parent = {};

      //初始化数据结构,使所有
      //元素有自己的父母
      elements.forEach(e => (this.parent[e] = e));
   }

   union(a, b) {
      let rootA = this.find(a);
      let rootB = this.find(b);

      //根是相同的,因此它们已经连接。
      if (rootA === rootB) return;

      //始终将根较小的元素作为父元素。
      if (rootA < rootB) {
         if (this.parent[b] != b) this.union(this.parent[b], a);
         this.parent[b] = this.parent[a];
      } else {
         if (this.parent[a] != a) this.union(this.parent[a], b);
         this.parent[a] = this.parent[b];
      }
   }

   //返回节点的最终父级
   find(a) {
      while (this.parent[a] !== a) {
         a = this.parent[a];
      }
      return a;
   }

   //检查2个节点的连接
   connected(a, b) {
      return this.find(a) === this.find(b);
   }
}

您可以使用以下方式进行测试:

示例

let uf = new UnionFind(["A", "B", "C", "D", "E"]);
uf.union("A", "B"); uf.union("A", "C");
uf.union("C", "D");

console.log(uf.connected("B", "E"));
console.log(uf.connected("B", "D"));

输出结果

这将给出输出-

false
true

现在让我们看看使用此数据结构的Kruskal算法的实现-

示例

kruskalsMST() {
   //初始化将包含MST的图形
   const MST = new Graph();
   this.nodes.forEach(node => MST.addNode(node));
   if (this.nodes.length === 0) {
      return MST;
   }

   //创建一个优先级队列
   edgeQueue = new PriorityQueue(this.nodes.length * this.nodes.length);

   //将所有边添加到队列中:
   for (let node in this.edges) {
      this.edges[node].forEach(edge => {
         edgeQueue.enqueue([node, edge.node], edge.weight);
      });
   }

   let uf = new UnionFind(this.nodes);

   //循环直到我们探索所有节点或队列为空
   while (!edgeQueue.isEmpty()) {
      //使用解构获取边缘数据
      let nextEdge = edgeQueue.dequeue();
      let nodes = nextEdge.data;
      let weight = nextEdge.priority;

      if (!uf.connected(nodes[0], nodes[1])) {
         MST.addEdge(nodes[0], nodes[1], weight);
         uf.union(nodes[0], nodes[1]);
      }
   }
   return MST;
}

您可以使用以下方式进行测试:

示例

let g = new Graph();
g.addNode("A");
g.addNode("B");
g.addNode("C");
g.addNode("D");
g.addNode("E");
g.addNode("F");
g.addNode("G");

g.addEdge("A", "C", 100);
g.addEdge("A", "B", 3);
g.addEdge("A", "D", 4);
g.addEdge("C", "D", 3);
g.addEdge("D", "E", 8);
g.addEdge("E", "F", 10);
g.addEdge("B", "G", 9);
g.addEdge("E", "G", 50);

g.kruskalsMST().display();

输出结果

这将给出输出-

A->B, D
B->A, G
C->D
D->C, A, E
E->D, F
F->E
G->B
 类似资料:
  • 一、最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树。 例如,对于如上图G4所示的连通网可以有多棵权值总和不相同的生成树。 二、克鲁斯卡尔算法介绍 克鲁斯卡尔(Kruskal)算法,是用来求加权连通图的最小生成树的算法。 基本思想:按照权值从小到大的顺序选择n-1条边,并保证这n-1条边不构成回路。

  • Kruskal用于查找最小成本生成树的算法使用贪婪方法。 此算法将图形视为森林,将每个节点视为单个树。 树仅连接到另一个树,并且仅当它在所有可用选项中具有最低成本且不违反MST属性时。 要了解Kruskal的算法,让我们考虑以下示例 - 步骤1 - 删除所有循环和平行边缘 从给定图中删除所有循环和平行边。 如果是平行边缘,请保留成本最低的一个并删除所有其他边缘。 步骤2 - 按重量增加的顺序排列所

  • 本文向大家介绍Kruskal算法的基本过程相关面试题,主要包含被问及Kruskal算法的基本过程时的应答技巧和注意事项,需要的朋友参考一下 参考回答: Kruskal算法是以边为主导地位,始终选取当前可用的拥有最小权值的边,所选择的边不能构成回路。首先构造一个只有n个顶点没有边的非连通图,给所有的边按值以从小到大的顺序排序,选择一个最小权值边,若该边的两个顶点在不同的连通分量上,加入到有效边中,否

  • 本文向大家介绍Kruskal的最小生成树算法,包括了Kruskal的最小生成树算法的使用技巧和注意事项,需要的朋友参考一下 有一个连通图G(V,E)并给出了每个边的权重或成本。Kruskal的算法将使用图形和成本找到最小生成树。 这是合并树方法。最初,有不同的树,此算法将采用成本最小的那些边合并它们,并形成一棵树。 在此问题中,所有边均根据其成本列出并排序。从列表中,取出成本最低的边并添加到树中,

  • 本文向大家介绍Prim算法和Kruskal算法之间的区别,包括了Prim算法和Kruskal算法之间的区别的使用技巧和注意事项,需要的朋友参考一下 在本文中,我们将了解Prim算法和Kruskal算法之间的差异。 最小生成树(MST)的Kruskal算法 给定一个连通图和无向图时,此类图的生成树就是子图,该子图是连接所有顶点的树。 单个图可以具有多个生成树。 加权图,连接图和无向图的最小生成树(M

  • 问题 用Kruskal算法求无向图 G 的最小生成树。 解法 Kruskal算法是一种贪心算法。初始时将图 G 的边集 E 按照权值,从小到大进行排序,并且生成树。从最小权值的边开始,依次考虑每一条边,对于边 e_i 来说,若将它加入生成树集合 S 中, e_i 不会与 S 中已有的边形成环,那么选取边 e_i 作为生成树中的一条边,将其加入集合 S ;反之若将 e_i 加入 S 中会与已有的边形