1. 程式人生 > >圖相關(二)圖的鄰接矩陣表示(C++)及最短路徑演算法

圖相關(二)圖的鄰接矩陣表示(C++)及最短路徑演算法

一.Dijikstra演算法

注意:計算最短路徑時,需要把鄰接矩陣中沒有邊的位置初始化為無窮大;此處以INF表示,INF可以取0x3f3f3f3f不能直接設為INT_MAX(因為做加法時會上溢)。

測試用圖:

其鄰接矩陣表示為:

vector<vector<int>> test_graph(7, vector<int>(7, INF));

	test_graph[0][1] = 20;
	test_graph[0][2] = 50;
	test_graph[0][3] = 30;

	test_graph[1][2] = 25;
	test_graph[1][5] = 70;

	test_graph[2][3] = 40;
	test_graph[2][4] = 25;
	test_graph[2][5] = 50;

	test_graph[3][4] = 55;

	test_graph[4][5] = 10;
	test_graph[4][6] = 70;

	test_graph[5][6] = 50;

 其中INF為:


const int INF = 0x3f3f3f;//不能取得太大(dijikstra中會用到,其餘情況沒邊用0表示即可)

程式碼:

//pre記錄字首
 
const int INF = 0x3f3f3f;//不能取得太大(dijikstra中會用到,其餘情況沒邊用0表示即可)
void dijkstra(graph g, vector<int>& lowcost, vector<int>& pre, int beg) {//第二、三個引數為傳出引數,分別表示從源節點beg,到所有節點的最短路路徑
    size_t N = g.cost.size();
    vector<bool> visited(N, false);
    for (size_t i = 0;i < N;++i) {//初始化lowcost和pre
        lowcost[i] = INF;
        pre[i] = -1;
    }
 
    lowcost[beg] = 0;//出發點到自己的最短路徑是0
 
    for (size_t i = 0;i < N;++i) {
        int newNode = -1;//下一個要被選中的點的編號, 初始化為 - 1
        int MinWeight=INF;//與當前節點相鄰的邊的最小權值
//第一個for,遍歷所有的未被訪問過的節點,選中間點(已選節點之外的離出發點距離最短的點)
        for (size_t j = 0;j < N;++j) {
            if (!visited[j] && lowcost[j] < MinWeight) {
                MinWeight = lowcost[j];
                newNode = j;
            }
        }
        if(-1==newNode)
            break;//圖不連通時,退出
        visited[newNode] = true;//將中間點標記為已訪問狀態
        for (size_t j = 0;j < N;++j) {
            if (!visited[j] && lowcost[newNode] + g.cost[newNode][j] < lowcost[j]){
                lowcost[j] = lowcost[newNode] + g.cost[newNode][j];
                pre[j] = newNode;
            }
        }
    }
}

步驟:

1.初始化時,將出發點到自己的最短路徑置為0,其餘置為無窮

2.對於出發點以外的點(即上面第二個for中所選的點j),考察從出發點直接到它的距離d1=lowcost[j]和先經過一個第一個for所選的中間點(newNode)才到j的距離d2=lowcost[newNode] + g.cost[newNode][j];

3.如果經由中間點然後訪問點j的距離比直接訪問j的距離短,即步驟2中的d2<d1時,更新出發點到j的最短距離為d2,它的上一個節點即那個中間點newNode

 

測試部分:

graph g;
    g.cost = test_graph;
    g.vertex = { "v1","v2","v3","v4","v5","v6","v7" };
    vector<int> lowcost(7, 0);
    vector<int> pre(7, 0);
    dijkstra(g, lowcost, pre, 0);
    cout << "從v1其它節點的最短距離分別是: " << endl;
    for (size_t i = 0;i < g.vertex.size();++i) {
        cout << g.vertex[i] << ";" << lowcost[i] <<"  " ;
    }
    cout << endl;
    cout << endl;
    cout << "每個節點的前驅是: " << endl;
    for (size_t i = 0;i < g.vertex.size();++i) {
        cout << g.vertex[i] << "的前驅是: " << ((pre[i] == -1) ? "null" :g.vertex[pre[i]]) << endl;;
    }

測試結果: