0
点赞
收藏
分享

微信扫一扫

Dijkstra算法基础

精进的医生 2022-03-18 阅读 43

基本原理

Dijkstra算法是根据贪心算法实现的,首先找出当前点到所有能到达的点之间最短的距离,然后松弛一次继续循环。所谓松弛一次,就是在已经访问过的点中遍历一遍,看看有没有更近的,如果有更近的就更新距离。这样每次找最近的可达点+松弛遍历历史节点的操作,一直重复就能找到最短路径。
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径。
它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止。

算法步骤

  1. 指定起始点s。
  2. 找到起始点相邻的点开始记录
  3. 将第二步记录的点作为起始点,如果第二部记录了多个点的话,那么按照与起始点s的距离或者权值,其中权值最小的优先依次作为起始点。
  4. 直到遍历完图中所有的点。

过程图解

在这里插入图片描述

初始配置表

vKnowndvpv
v1000
v200
v300
v400
v500
v600
v700

在v1被声明为已知后的表

vKnowndvpv
v1100
v202v1
v300
v401v1
v500
v600
v700

在v4被声明为已知后的表

vKnowndvpv
v1100
v202v1
v303v4
v411v1
v503v4
v609v4
v705v4

在v2被声明为已知后的表

vKnowndvpv
v1100
v212v1
v303v4
v411v1
v503v4
v609v4
v705v4

在v5然后v3被声明为已知后的表

vKnowndvpv
v1100
v212v1
v313v4
v411v1
v513v4
v608v3
v705v4

在v7被声明为已知后的表

vKnowndvpv
v1100
v212v1
v313v4
v411v1
v513v4
v606v7
v715v4

在v6被声明为已知后的表

vKnowndvpv
v1100
v212v1
v313v4
v411v1
v513v4
v616v7
v715v4

至此我们可以得出从v1出发到所有点的最短路径

伪代码

Dijkstar算法的声明

typeof int Vertex;

struct TableEntry
{
	List Header; /*Adjacency list*/
	int Known;
	DistType Dist;
	Vertex Path;
}
/*Vertices are numbered from 0*/
#define NotAVertex(-1)
typeof struct TableEntry Table[NumVertex];

表初始化例程

void InitTable(Vertex Start, Graph G, Table T)
{
	int i;
	ReadGraph(G,T);
	for(i=0; i<NumVertex; i++)
	{
		T[i].Known = false;
		T[i].Dist = Infinity;
		T[i].Path = NotVertex;	
	}
	T[Start].dist = 0;
}

显示实际最短路径的例程

void PrintPath(Vertex V, Table T)
{
	if(T[V].Path != NotVertex)
	{
		PrintPath(T[V].Path,T);
		prithf("to");
	}
	printf("%v",V) /*%v is pseudocode*/
}

Dijkstra算法

void Dijkstra(Table T)
{
	Vertex V, W;
	for(; ;)
	{
		V = smallest unkonwn diatance vertex;
		if(V = NotVertex)
		{
			break;
		}
		T[V].Known = true;
		for each W adjacent to V
		{	
			if(!T[W].Known)
			{
				if(T[V].Dist + Cvw < T[W].Dist)
				{
					Decrease(T[W].Dist to T[V].Dist + Cvw);
					T[W].Path = V;
				}
			}
		}
	}
	
}

例题

class Solution {
public:
    struct Edge
    {
        int u,v,d;
        Edge(int from,int to,int dis)
            :      u(from),
                   v(to),
                   d(dis)
        {
        }
    };
    struct heapNode
    {
        int u,d;
        bool operator < (const heapNode& rhs) const
        {
            return d > rhs.d;
        }
    };
    int networkDelayTime(vector<vector<int>>& times, int N, int K) 
    {
        priority_queue<heapNode> que;
        vector<Edge> edges;
        vector<vector<int>> g(N,vector<int>());
        vector<int> d(N,INT_MAX);
        d[K-1] = 0;
        vector<int> visited(N,0);
        for(int i = 0; i < times.size();++i)//建图
        {
            edges.push_back(Edge{times[i][0]-1,times[i][1]-1,times[i][2]});
            g[times[i][0]-1].push_back(edges.size()-1);
        }
        que.push(heapNode{K-1,0});//先把源节点加进去
        while(!que.empty())
        {
            heapNode node = que.top();
            que.pop();
            if(visited[node.u])
                continue;
            visited[node.u] = 1;//标记
            for(int i = 0; i < g[node.u].size(); ++i)
            {
                Edge &edge = edges[g[node.u][i]];
                if(d[edge.v] > d[edge.u] + edge.d)//更新权值
                {
                    d[edge.v] = d[edge.u] + edge.d;
                    que.push(heapNode{edge.v,d[edge.v]});
                }
            }
        }
        int result = -1;
        for(int i = 0; i < d.size(); ++i)
        {
            if(d[i] > result)
                result = d[i];
        }
        return result == INT_MAX ? -1 : result;//判断是否是连通图
    }
};

举报

相关推荐

0 条评论