Prim算法,普里姆算法,在無向圖中搜索最小生成樹。
算法實現的主要步驟:
(1) 初始化
所有點都初始化爲沒有被訪問,初始化根結點到各結點的距離,存放在lowcost[]數組中;
(2)尋找最小值
從根結點開始,其依據:一端連接,另一端未連接,尋找最小值
找到最小值後,更新lowcost[],未選結點到已選結點(可能已經選中了多個結點)中的最小值
(3)重複第(2)步,直到所有點都被選中,則算法結束。
本文依據下圖對算法實現:
具體代碼如下,已經**在vs2010測試通過**。
#include <iostream>
using namespace std;
#define UndirectedGraphNode 6
#define INFINITE 1000
void Prim(int undirectedGraph[][UndirectedGraphNode], bool visited[], int lowcost[], int path[])
{
//初始化
memset(visited, 0, sizeof(bool) * UndirectedGraphNode);//所有點都沒有被訪問
for(int i = 1; i < UndirectedGraphNode; i++)
lowcost[i] = undirectedGraph[0][i];//根結點到各結點的距離
//根結點被訪問
int k = 0;//記錄加入路徑中的結點的順序
visited[0] = true;
path[k] = 0;//記錄加入路徑中的結點的下標
int min;
int minIndex;
//一端連接,另一端未連接,尋找最小值
for(int j = 1; j < UndirectedGraphNode; j++)//外層循環,每次循環確定一個點
{
min = INFINITE;//每次循環要重新賦值
//尋找最小值
for(int i = 1; i < UndirectedGraphNode; i++)
{
//存在多個條件的判斷,應將最可能爲假的條件放在前面,減少判斷次數
if(false == visited[i] && lowcost[i] < min)
{
min = lowcost[i];
minIndex = i;
}
}
path[++k] = minIndex;//對應結點加入路徑中,區分 ++k 與 k++
visited[minIndex] = true;//該點已經被訪問
//更新lowcost[]
//lowcost[],未選結點到已選結點中的最小值
for(int i = 1; i < UndirectedGraphNode; i++)
{
if(false == visited[i] && lowcost[i] > undirectedGraph[minIndex][i])
lowcost[i] = undirectedGraph[minIndex][i];
}
}
}
void PrimRun()
{
//點與點之間存在邊,權重爲非零值,非無窮大值
//點與點之間不存在邊,權重爲無窮大值
int undirectedGraph[][UndirectedGraphNode] =
{
{INFINITE, 12, INFINITE, INFINITE, 9, 9},
{12, INFINITE, 6, INFINITE, INFINITE, 15},
{INFINITE, 6, INFINITE, 3, INFINITE, 17},
{INFINITE, INFINITE, 3, INFINITE, 4, 20},
{9, INFINITE, INFINITE, 4, INFINITE, 9},
{9, 15, 17, 20, 9, INFINITE},
};
bool visited[UndirectedGraphNode];
int path[UndirectedGraphNode];
int lowcost[UndirectedGraphNode];
Prim(undirectedGraph, visited, lowcost, path);
for(int i = 0; i < UndirectedGraphNode; i++)
cout<<"v"<<path[i] + 1<<" ";//v1表示第一個結點
cout<<endl;
}
int _tmain(int argc, _TCHAR* argv[])
{
PrimRun();//調用
return 0;
}
算法運行結果如圖所示: