Computer >> Máy Tính >  >> Lập trình >> C ++

Thuật toán cây kéo dài tối thiểu của Kruskal-Thuật toán tham lam trong C ++

Cây bao trùm là một đồ thị con được liên kết và vô hướng nối tất cả các đỉnh. Nhiều cây bao trùm có thể tồn tại trong một biểu đồ. Cây bao trùm tối thiểu (MST) trên mỗi đồ thị có cùng trọng số hoặc nhỏ hơn tất cả các cây bao trùm khác. Trọng số được gán cho các cạnh của cây bao trùm và tổng là trọng số được gán cho mỗi cạnh. Vì V là số đỉnh trong đồ thị nên cây khung tối thiểu có các cạnh là (V - 1), trong đó V là số cạnh.

Tìm cây bao trùm tối thiểu bằng thuật toán của Kruskal

  • Tất cả các cạnh phải được sắp xếp theo thứ tự trọng lượng không giảm dần.

  • Chọn cạnh nhỏ nhất. Cạnh này được bao gồm nếu chu trình không được hình thành.

  • Bước 2 sẽ được thực hiện cho đến khi cây khung có các cạnh (V-1).

Trong trường hợp này, chúng tôi được yêu cầu sử dụng một phương pháp tham lam. Tùy chọn tham lam là chọn cạnh có khối lượng ít nhất. Như một minh họa:Cây bao trùm tối thiểu cho biểu đồ này là (9-1) =8 cạnh.

Thuật toán cây kéo dài tối thiểu của Kruskal-Thuật toán tham lam trong C ++

After sorting:

Weight  Src    Dest
21       27    26
22       28    22
22       26    25
24       20    21
24       22    25
26       28    26
27       22    23
27       27    28
28       20    27
28       21    22
29       23    24
30       25    24
31       21    27
34       23    25

Bây giờ chúng ta cần chọn tất cả các cạnh theo cách sắp xếp.

Cạnh 26-27-> được bao gồm vì không có chu trình nào được hình thành

Cạnh 28-22-> được bao gồm vì không có chu trình nào được hình thành

Cạnh 26-25-> được bao gồm vì không có chu trình nào được hình thành.

Cạnh 20-21-> được bao gồm vì không có chu trình nào được hình thành

Cạnh 22-25-> được bao gồm vì không có chu trình nào được hình thành.

Cạnh 28-26-> bị loại bỏ khi chu kỳ được hình thành

Cạnh 22-23-> được bao gồm vì không có chu trình nào được hình thành

Cạnh 27-28-> bị loại bỏ khi chu kỳ được hình thành

Cạnh 20-27-> được bao gồm vì không có chu trình nào được hình thành

Cạnh 21-22-> bị loại bỏ khi chu kỳ được hình thành

Cạnh 23-24-> được bao gồm vì không có chu trình nào được hình thành

Vì số cạnh là (V-1), vì vậy thuật toán kết thúc ở đây.

Ví dụ

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Edge {
   int src, dest, weight;
};
struct Graph {
   int V, E;
   struct Edge* edge;
};
struct Graph* createGraph(int V, int E){
   struct Graph* graph = (struct Graph*)(malloc(sizeof(struct Graph)));
   graph->V = V;
   graph->E = E;
   graph->edge = (struct Edge*)malloc(sizeof( struct Edge)*E);
   return graph;
}
struct subset {
   int parent;
   int rank;
};
int find(struct subset subsets[], int i){
   if (subsets[i].parent != i)
      subsets[i].parent
   = find(subsets, subsets[i].parent);
   return subsets[i].parent;
}
void Union(struct subset subsets[], int x, int y){
   int xroot = find(subsets, x);
   int yroot = find(subsets, y);
   if (subsets[xroot].rank < subsets[yroot].rank)
      subsets[xroot].parent = yroot;
   else if (subsets[xroot].rank > subsets[yroot].rank)
      subsets[yroot].parent = xroot;
   else{
      subsets[yroot].parent = xroot;
      subsets[xroot].rank++;
   }
}
int myComp(const void* a, const void* b){
   struct Edge* a1 = (struct Edge*)a;
   struct Edge* b1 = (struct Edge*)b;
   return a1->weight > b1->weight;
}
void KruskalMST(struct Graph* graph){
   int V = graph->V;
   struct Edge
   result[V];
   int e = 0;
   int i = 0;
   qsort(graph->edge, graph->E, sizeof(graph->edge[0]), myComp);
   struct subset* subsets
   = (struct subset*)malloc(V * sizeof(struct subset));
   for (int v = 0; v < V; ++v) {
      subsets[v].parent = v;
      subsets[v].rank = 0;
   }
   while (e < V - 1 && i < graph->E) {
      struct Edge next_edge = graph->edge[i++];
      int x = find(subsets, next_edge.src);
      int y = find(subsets, next_edge.dest);
      if (x != y) {
         result[e++] = next_edge;
         Union(subsets, x, y);
      }
   }
   printf("Following are the edges in the constructed MST\n");
   int minimumCost = 0;
   for (i = 0; i < e; ++i){
      printf("%d -- %d == %d\n", result[i].src,
      result[i].dest, result[i].weight);
      minimumCost += result[i].weight;
   }
   printf("Minimum Cost Spanning tree : %d",minimumCost);
   return;
}
int main(){
   /* Let us create the following weighted graph
   30
   0--------1
   | \       |
   26| 25\ |15
   | \ |
   22--------23
   24 */
   int V = 24;
   int E = 25;
   struct Graph* graph = createGraph(V, E);
   graph->edge[0].src = 20;
   graph->edge[0].dest = 21;
   graph->edge[0].weight = 30;
   graph->edge[1].src = 20;
   graph->edge[1].dest = 22;
   graph->edge[1].weight = 26;
   graph->edge[2].src = 20;
   graph->edge[2].dest = 23;
   graph->edge[2].weight = 25;
   graph->edge[3].src = 21;
   graph->edge[3].dest = 23;
   graph->edge[3].weight = 35;
   graph->edge[4].src = 22;
   graph->edge[4].dest = 23;
   graph->edge[4].weight = 24;
   KruskalMST(graph);
   return 0;
}

Đầu ra

Following are the edges in the constructed MST
22 -- 23 == 24
20 -- 23 == 25
20 -- 21 == 30
Minimum Cost Spanning tree : 79

Kết luận

Hướng dẫn này đã trình bày cách sử dụng phương pháp Thuật toán-Greedy của cây kéo dài tối thiểu của Kruskal và mã C ++ để giải quyết vấn đề này. Chúng tôi cũng có thể viết mã này bằng java, python và các ngôn ngữ khác. Nó được mô phỏng theo ý tưởng của Kruskal. Chương trình này tìm cây khung ngắn nhất trong một đồ thị nhất định. Chúng tôi hy vọng bạn thấy hướng dẫn này hữu ích.