日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

利用克鲁斯卡尔算法求最小生成树

發布時間:2023/12/19 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 利用克鲁斯卡尔算法求最小生成树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

思路:最小生成樹即為無向連通圖G的一個子圖如果是一顆包含G的所有頂點且權最小的樹則稱為最小生成樹。克魯斯卡爾算法的基本思想是以邊為主導地位,始終選擇當前可用的(所選的邊不能構成回路)最小權值邊。所以第一步是將所有邊按照權值從小到大的順序排序,接下來從小到大依次考察每一條邊。具體實現過程如下:

<1>設一個有n個頂點的連通網絡為G(V,E),最初先構造一個只有n個頂點,沒有邊的非連通圖T={V,空},圖中每個頂點自成一格連通分量。

<2>在E中選擇一條具有最小權植的邊時,若該邊的兩個頂點落在不同的連通分量上,則將此邊加入到T中;否則,即這條邊的兩個頂點落到同一連通分量上,則將此邊舍去(此后永不選用這條邊),重新選擇一條權植最小的邊。

<3>如此重復下去,直到所有頂點在同一連通分量上為止。

在上面的算法思路中,最為復雜的部分是連通分量的查詢和合并,并查集這個數據結構可以方便快速的解決這個問題。基本的處理思想是:初始時把每個對象看作是一個單元素集合;然后依次按順序讀入聯通邊,將連通邊中的兩個元素合并。在此過程中將重復使用一個搜索(Find)運算,確定一個集合在那個集合中。當讀入一個連通邊(u,v)時,先判斷u和v是否在同一個集合中,如果是則不用合并;如果不是,則用一個合并運算把u、v所在集合合并,使得這兩個集合中的任意兩個元素都連通。因此并查集在處理時,主要用到搜索和合并兩個運算。為了方便并查集的描述與實現,通常把先后加入到一個集合中的元素表示成一個樹結構,并用根結點的序號(在這里根節點的序號就是數組的下標值)來表示這個集合。因此定義一個parent[n]的數組,parent[i]中存放的就是結點i+1所在的樹中結點i+1的父親節點的序號。

#include<stdio.h> #include<stdlib.h> #define MAXVEX 20 #define INF 32767 typedef struct {int arcs[MAXVEX][MAXVEX];char vex[MAXVEX];int vexnum;int arcnum; }AdjMatrix; //圖 typedef struct {int start;int end;int weight;int isUsed; } Brim; //邊 int LocateVex(AdjMatrix* G, char v); void Create(AdjMatrix *G); int Find(int *parent, int f); void Kruskal(AdjMatrix *G) int main() {AdjMatrix* G = (AdjMatrix*)malloc(sizeof(AdjMatrix));Create(G);Kruskal(G);return 0; }int Find(int *parent, int f) {//從下標f開始尋找parent數組中元素為0的下標int x;for(x = f;parent[x] > 0; x=parent[x]);return x; } void Create(AdjMatrix *G) {int i, j, k;char vex1, vex2;int weight;scanf("%d%d", &G->vexnum, &G->arcnum);getchar();for (i = 0; i < G->vexnum; i++){for (j = 0; j < G->vexnum; j++){G->arcs[i][j] = INF;}}for (i = 0; i < G->vexnum; i++){scanf("%c", &G->vex[i]); //輸入各個頂點 }getchar();for (i = 0; i < G->arcnum; i++){scanf("(%c,%c,%d)", &vex1, &vex2, &weight); //輸入邊的信息 j = LocateVex(G, vex1);k = LocateVex(G, vex2);G->arcs[j][k] = weight;G->arcs[k][j] = weight;} }void Kruskal(AdjMatrix *G) { Brim brim[MAXVEX];int i, j;int k = 0;int n, m;for (i = 0; i < G->vexnum- 1; i++) { //生成樹最多只有n-1條邊 for (j = i + 1; j < G->vexnum; j++) {if (G->arcs[i][j] != INF) {brim[k].start = i;brim[k].end = j;brim[k].weight = G->arcs[i][j];brim[k].isUsed = 0;k++;}}}for (i = 0; i < k - 1; i++){for (j = i + 1; j < k; j++){if (brim[i].weight > brim[j].weight){Brim tmp = brim[i];brim[i] = brim[j];brim[j] = tmp;}}}int parent[MAXVEX] = { 0 };for (int i = 0; i < G->arcnum; i++){n = Find(parent, brim[i].start); //找到根節點 m = Find(parent, brim[i].end); //找到根節點 if (n != m)//m=n說明有環{parent[n] = m; //將根節點n所在的樹作為m的子樹 合并 brim[i].isUsed = 1;}printf("(%c,%c,%d,%d)", G->vex[brim[i].start], G->vex[brim[i].end], brim[i].weight, brim[i].isUsed);}}

總結

以上是生活随笔為你收集整理的利用克鲁斯卡尔算法求最小生成树的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。