dijkstra Bellman_Ford与Floyd算法的性质比较与实现

dijkstra,Bellman_Ford,Floyd算法的比较:
:Dijkstra算法,图所有边权值都为非负的;
:Bellman_Ford算法,图中所有边权值可以存在负值,但是不能存在原点可达的负权回路,如果存在负权回路,该算法可以给出判断;
:Floyd算法,不允许所有权值为负的回路,可以求出任意两点间的最短距离,而Dijkstra和Bellman_Ford算法只可以求出任意点到达源点的最短距离;
:Dijkstra算法的思想是贪心,Bellman_Ford和Floyd算法的思想是动态规划
:三者:图中都可以出现正权回路

Bellman_Ford算法实现

时间复杂度O(nm)

复制代码
1  #define  INF 10000
2  queue < int > q;
3    bool  inq[ 1000 ]; // 判断是否已经在队列中
4    for ( int  i = 0 ;i < n;i ++ )
5  d[i] = INF;
6  d[ 0 ] = 0 ;
7  memset(inq, false , sizeof (inq));
8  q.push( 0 );
9  inq[ 0 ] = true ;
10    while ( ! q.empty())
11  {
12  int  x = q.front();q.pop();
13  inq[x] = false ;
14  for ( int  i = first[x];i != NULL;i = next[i]) // 寻找所有与x相连的点
15     {
16  if (d[v[i]] > d[x] + w[i]) // 进行松弛操作
17     d[v[i]] = d[x] + w[i];
18  if ( ! inq[v[i]])
19  {
20  inq[v[i]] = true ;
21  q.push(v[i]);
22  }
23  }
24  }
复制代码

Floyed算法

时间复杂度O(n^3);
动态方程:
当k=0时:d[i][j]=w[i][j]
当k>=1时:d[i][j]=min(d[i][j],d[i][k]+d[k][j])

1  for ( int  k = 0 ;k < n;k ++ )
2  for ( int  i = 0 ;i < n;i ++ )
3  for ( int  j = 0 ;j < n;j ++ )
4  if (d[i][k] + d[k][j] < d[i][j])
5  d[i][j] = d[i][k] + d[k][j]

Dijkstra算法伪代码及代码

从单个原点出发到所有节点的最短路径。该算法适用于有向图和无向图
初始化G,s
S=空
Q=V[G];
d=无穷
while(!Q.isempty())
{
在d中选出最小值对应的下标为u
 S=S+u
 Q=Q-u
 对于所有从u出发的边(u,y)更新d[y]=min{d[y],d[u]+map[u,y]};
 }
 利用father数组记录路径
 时间复杂度O(n*n)
 优化dijkstra算法为:dijkstra+优先队列 时间复杂度O(MlogN);

复制代码
1  #include < iostream >
2  #include < queue >
3  using namespace  std;
4  int  G[ 12 ][ 12 ],E[ 12 ][ 12 ],d[ 12 ],mark[ 12 ],N,x,y,z;
5  /*
6  x为起点y为终点 z为距离 
7  G存储图,E存储边,d存储距离,mark判断该点是否已经算过 
8  */  
9  struct  node
10  {
11  int  valu;
12  int  index;
13  friend  bool operator < (node a,node b)
14  {
15  return  a.valu > b.valu;
16 
17  }t,st; // 重载运算符< 
18  int  main()
19  {
20  while (cin >> N)
21  {
22  for ( int  i = 0 ;i < 12 ;i ++ )
23  G[i][ 0 ] = 0 ,d[i] = 1000 ,mark[i] = 0 ; // 初始化 
24  d[ 1 ] = 0 ;
25  while (N -- )
26  {
27  cin >> x >> y >> z;
28  G[x][ ++ G[x][ 0 ]] = y;
29  E[x][ ++ E[x][ 0 ]] = z;
30  }
31  priority_queue < node > q; // 声明优先队列 
32  t.valu = 0 ,t.index = 1 ;
33  q.push(t);
34  while ( ! q.empty())
35  {
36  t = q.top();
37  q.pop();
38  if (mark[t.index]) // 如果已经算过则跳过 
39  continue ;
40  mark[t.index] = 1 ;
41  for ( int  i = 1 ;i <= G[t.index][ 0 ];i ++ )
42  {
43  if (d[t.index] + E[t.index][i] < d[G[t.index][i]]) // 松弛操作 
44  {
45  d[G[t.index][i]] = d[t.index] + E[t.index][i];
46  st.valu = d[G[t.index][i]];
47  st.index = G[t.index][i];
48  q.push(st);
49  }
50 
51  }
52  cout << " 原点为1每一点到原点的最短距离为: " << endl;
53  for ( int  i = 1 ;i < 6 ;i ++ )
54  cout << d[i] << " " ;
55  cout << endl;
56  }
57  }
58  /*
59  9
60  1 2 10
61  1 3 3
62  2 3 1
63  3 2 4
64  2 4 2
65  3 4 8
66  3 5 2
67  4 5 7
68  5 4 9
69  */
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值