最小代价生成树Prim/Kruskal(c/c++)
常用的求最小代價生成樹的方法有兩種:Prim算法和Kruskal算法,這兩種算法都是貪心算法的應用,
Prim算法
在一個無向帶權圖中求得最小生成樹得思路是:從a頂點出發,將a放入u集合(表示已選),找與u集合中所有點連接的權值最小的邊(此時只有a結點),假設該邊連接a和b結點,b結點被選定放入u集合,查找與u集合中所有點連接的權值最小的邊(此時有a,b結點),通過改變找到c結點,c被選定放入u集合中…當所有結點都被選中時,最小生成樹建成了。故Prim可看做為‘加點’的算法。
輔助結構
typedef struct {int adjvex;//相連接的頂點int lowcost;//表示權值 }st; st closeEdge[maxSize]; closeEdge[i].adjvex=k;//k為在集合中的頂點 closeEdge[i[.lowcost=0;i頂點與在集合中的k頂點相鄰接。i頂點的lowcost為0,表示將i頂點被選中加入u集合
代碼如下
用鄰接矩陣存儲圖,將邊上的權值存入矩陣中,圖中不連接的邊在矩陣中為INT_MAX,自身之間的連接也存為INT_MAX
void miniSpanTree(mGraph& G, int u) {//從頂點u出發構造G的最小代價生成樹int i, j, min;for (i = 0; i < G.vexnum; i++)if (i != u)closeEdge[i]= { u, G.arc[i][u]};//初始化與u相連所有頂點間的權值closeEdge[u].lowcost = 0;//將u加入到已選集合中for (j = 1; j < G.vexnum; j++)//僅起到循環G.vexnum-1次的作用{int minValue =INT_MAX;for (i = 0; i < G.vexnum; i++)if (closeEdge[i].lowcost != 0){if (minValue > closeEdge[i].lowcost){minValue = closeEdge[i].lowcost;min = i;}}std::cout << "選定結點: "<<G.vex[min] << " 權值: " << closeEdge[min].lowcost << '\n';closeEdge[min].lowcost = 0;//將min頂點加入已選集合中for (i = 0; i < G.vexnum; i++){if (closeEdge[i].lowcost != 0){if (closeEdge[i].lowcost>G.arc[min][i])closeEdge[i] = { min, G.arc[min][i] };//i與集合中的min相連,因為它們的權值更小}}} }完整示例
輸入圖如下:6個頂點,10條邊
對該圖用prim算法進行最小代價生成樹構造代碼如下:
輸出結果如下:
Kruskal算法
Kruskal算法可看作為‘加邊’來得到最小生成樹。它的思路為:
1,找到所有邊中代價(權值)最小的邊,加入u集合中
2,判定該邊所關聯的兩個頂點是否在同一個分量中(可以用DFS在集合u中來判斷,當一次DFS可以成功查找到,那么兩個頂點在同一個分量中)如果兩個頂點已經在同一個分量中,那么該邊被舍棄,否則該邊被加入到所選集合u中
3,再找代價最小的邊,再判定…
對于下圖:
先找到a-c邊,然后是d-f邊,再是b-e邊,接下來是c-f邊,如果當找到a-d邊時,因為在集合u中a頂點與d頂點已經在同一個連通分量中了,舍棄a-d邊,重新查找…
總結
以上是生活随笔為你收集整理的最小代价生成树Prim/Kruskal(c/c++)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: DFS深度优先搜索算法/BFS广度优先搜
- 下一篇: AOV网拓扑排序(c/c++)