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

Kruskal的最小生成树算法

谭富
2023-03-14
本文向大家介绍Kruskal的最小生成树算法,包括了Kruskal的最小生成树算法的使用技巧和注意事项,需要的朋友参考一下

有一个连通图G(V,E)并给出了每个边的权重或成本。Kruskal的算法将使用图形和成本找到最小生成树。

这是合并树方法。最初,有不同的树,此算法将采用成本最小的那些边合并它们,并形成一棵树。

在此问题中,所有边均根据其成本列出并排序。从列表中,取出成本最低的边并添加到树中,然后每一次检查是否形成边,如果形成一个循环,则从列表中丢弃边并移至下一条边。

该算法的时间复杂度为O(E log E)或O(E log V),其中E是许多边,V是许多顶点。

输入输出

Input:
Adjacency matrixOutput:
Edge: B--A And Cost: 1
Edge: E--B And Cost: 2
Edge: F--E And Cost: 2
Edge: C--A And Cost: 3
Edge: G--F And Cost: 3
Edge: D--A And Cost: 4
Total Cost: 15

算法

kruskal(g: Graph, t: Tree)

输入-给定图g和空树t

输出-具有选定边的树t

Begin
   create set for each vertices in graph g
   for each set of vertex u do
      add u in the vertexSet[u]
   done

   sort the edge list.
   count := 0
   while count <= V – 1 do    //as tree must have V – 1 edges
      ed := edgeList[count]   //take an edge from edge list
      if the starting vertex and ending vertex of ed are in same set then
         merge vertexSet[start] and vertexSet[end]
         add the ed into tree t
      count := count +1
   done
End

示例

#include<iostream>
#define V 7
#define INF 999
using namespace std;

//图的成本矩阵
int costMat[V][V] = {
   {0, 1, 3, 4, INF, 5, INF},
   {1, 0, INF, 7, 2, INF, INF},
   {3, INF, 0, INF, 8, INF, INF},
   {4, 7, INF, 0, INF, INF, INF},
   {INF, 2, 8, INF, 0, 2, 4},
   {5, INF, INF, INF, 2, 0, 3},
   {INF, INF, INF, INF, 4, 3, 0}
};

typedef struct {
   int u, v, cost;
}edge;

void swapping(edge &e1, edge &e2) {
   edge temp;
   temp = e1;
   e1 = e2;
   e2 = temp;
}

class Tree {
   int n;
   edge edges[V-1];    //as a tree has vertex-1 edges
   public:
      Tree() {
         n = 0;
      }

      void addEdge(edge e) {
         edges[n] = e;   //add edge e into the tree
         n++;
      }

      void printEdges() {    //print edge, cost and total cost
         int tCost = 0;

         for(int i = 0; i<n; i++) {
            cout << "Edge: " << char(edges[i].u+'A') << "--" <<char(edges[i].v+'A');
            cout << " And Cost: " << edges[i].cost << endl;
            tCost += edges[i].cost;
         }
         cout << "Total Cost: " << tCost << endl;
      }
};

class VSet {
   int n;
   int set[V];    //a set can hold maximum V vertices
   public:
      VSet() {
         n = -1;
      }

      void addVertex(int vert) {
         set[++n] = vert;    //add vertex to the set
      }

      int deleteVertex() {
         return set[n--];
      }

      friend int findVertex(VSet *vertSetArr, int vert);
      friend void merge(VSet &set1, VSet &set2);
};

void merge(VSet &set1, VSet &set2) {
   //将两个顶点集合并在一起
   while(set2.n >= 0)
      set1.addVertex(set2.deleteVertex());
      //addToSet(vSet1,delFromSet(vSet2)); 
}

int findVertex(VSet *vertSetArr, int vert) {
   //在不同的顶点集中找到顶点
   for(int i = 0; i<V; i++)
      for(int j = 0; j<=vertSetArr[i].n; j++)
         if(vert == vertSetArr[i].set[j])
            return i;   //node found in i-th vertex set
}

int findEdge(edge *edgeList) {
   //从Graph的成本矩阵中找到边并存储到edgeList-
   int count = -1, i, j;
   for(i = 0; i<V; i++)
      for(j = 0; j<i; j++)
         if(costMat[i][j] != INF) {
            count++;
            //填充位置“计数”的边缘列表
            edgeList[count].u = i; edgeList[count].v = j;
            edgeList[count].cost = costMat[i][j];
         }
   return count+1;
}

void sortEdge(edge *edgeList, int n) {
   //以成本的升序对图的边缘进行排序
   int flag = 1, i, j;

   for(i = 0; i<(n-1) && flag; i++) {   //modified bubble sort is used
      flag = 0;
      for(j = 0; j<(n-i-1); j++)
         if(edgeList[j].cost > edgeList[j+1].cost) {
            swapping(edgeList[j], edgeList[j+1]);
            flag = 1;
         }
   }
}

void kruskal(Tree &tr) {
   int ecount, maxEdge = V*(V-1)/2;   //max n(n-1)/2 edges can have in a graph
   edge edgeList[maxEdge], ed;
   int uloc, vloc;
   VSet VSetArray[V];
   ecount = findEdge(edgeList);

   for(int i = 0; i < V; i++)
      VSetArray[i].addVertex(i);    //each set contains one element
   sortEdge(edgeList, ecount);      //ecount number of edges in the graph
   int count = 0;

   while(count <= V-1) {
      ed = edgeList[count];
      uloc = findVertex(VSetArray, ed.u);
      vloc = findVertex(VSetArray, ed.v);

      if(uloc != vloc) {    //check whether source abd dest is in same set or not
         merge(VSetArray[uloc], VSetArray[vloc]);
         tr.addEdge(ed);
      }
      count++;
   }
}

int main() {
   Tree tr;
   kruskal(tr);
   tr.printEdges();
}

输出结果

Edge: B--A And Cost: 1
Edge: E--B And Cost: 2
Edge: F--E And Cost: 2
Edge: C--A And Cost: 3
Edge: G--F And Cost: 3
Edge: D--A And Cost: 4
Total Cost: 15
 类似资料:
  • 最小生成树的Kruskal算法 描述:有A、B、C、D四个点,每两个点之间的距离(无方向)是(第一个数字是两点之间距离,后面两个字母代表两个点):(1,’A’,’B’),(5,’A’,’C’),(3,’A’,’D’),(4,’B’,’C’),(2,’B’,’D’),(1,’C’,’D’) 生成边长和最小的树,也就是找出一种连接方法,将各点连接起来,并且各点之间的距离和最小。 思路说明: Krusk

  • 这里有一个图,我需要用Prim和Kruskal的算法找到G的最小生成树。 我用普里姆的算法找到了最小生成树。这是我的尝试。 我很难用Kruskal的算法找到最小生成树。我看过许多与Kruskal的图算法相关的视频,但最终得到的图与Prim的算法相同。 谁能给我演示一下如何用Kruskal的算法找到图的最小生成树吗?

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

  • 本文向大家介绍python最小生成树kruskal与prim算法详解,包括了python最小生成树kruskal与prim算法详解的使用技巧和注意事项,需要的朋友参考一下 kruskal算法基本思路:先对边按权重从小到大排序,先选取权重最小的一条边,如果该边的两个节点均为不同的分量,则加入到最小生成树,否则计算下一条边,直到遍历完所有的边。 prim算法基本思路:所有节点分成两个group,一个为

  • 主要内容:生成树,最小生成树数据结构提供了 3 种存储结构,分别称为线性表、树和图,如图 1 所示。 图 1 3 种存储结构 a) 是线性表,b) 是树,c) 是图。 在图存储结构中,a、b、c 等称为顶点,连接顶点的线称为边。 线性表是最简单的存储结构,很容易分辨。树和图有很多相似之处,它们的区别是:树存储结构中不允许存在环路,而图存储结构中可以存在环路(例如图 1 c) 中,c-b-f-c、b-a-f-b 等都是环路)。

  • 最小生成树 一个有 n 个结点的带权无向图,在满足所有顶点都连接的前提下使得所有的边的权总和最小,即为最小生成树(Minimum Spanning Tree MST)。最小生成树可以用kruskal(克鲁斯卡尔)算法或prim(普里姆)算法求出。 N个顶点,一定有N-1条边 包含所有顶点 所有顶点都可以直接或间接连接到另外的顶点 普里姆算法 普里姆算法在找最小生成树时,将顶点分为两类,一类是在查找