图相关(二)图的邻接矩阵表示(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;;
    }

测试结果:

 

猜你喜欢

转载自blog.csdn.net/u014450222/article/details/83627104
今日推荐