【演算法導論】24.1 Bellman-Ford 演算法
本程式碼為演算法導論24.1的C++實現。
#include <iostream>
using namespace std;
#define N 5
#define INFINITE 0x7fffffff
#define WHITE 1
#define GRAY 2
#define BLACK 3
//頂點結點結構
struct Vertex
{
Vertex * next;/*指向下一個頂點*/
int id;/*節點的標誌*/
int weight;/*節點的權值,臨界表表頭到此元素上邊的權值*/
Vertex():next(NULL),id(0){}
};
//圖結構
struct Graph
{
Vertex *Adj[N+1];//N個頂點及鄰接點頭指標
int p[N+1];//指向遍歷樹節點的父結點
int d[N+1];/*節點的最短路徑權值的上界*/
Graph()
{
for(int i = 1; i <= N; i++)
{
Adj[i] = new Vertex;
d[i] = 0;
p[i] = 0;
}
}
~Graph()
{
for(int i = 1; i <= N; i++)
delete Adj[i];
}
};
void Print(Graph *g);
bool Init(Graph *g);
bool InsertEdge(Graph *g , int start,int end,int weight);
bool InitializeSingleSource(Graph *g,int s);
bool Relax(Graph *g,int u,int v,int weight);
bool Relax(Graph *g,int u,int v);
int Weight(const Graph *g,int u,int v);
/*
start邊開始節點,end邊結束節點,weight邊權值
*/
//插入邊
bool InsertEdge(Graph *g , int start,int end,int weight)
{
Vertex* v = new Vertex();
v->id = end;
v->weight = weight;
if(g->Adj[start]->next == NULL)
{/*如果不存在臨界表的頭結點列表中,則插入*/
Vertex* s = new Vertex();
s->id = start;
g->Adj[start] = s;
}
Vertex* tmp = g->Adj[start];
while(tmp->next)
{
tmp = tmp->next;
}
tmp->next =v;
return true;
}
/*初始化臨接表表示的圖,有向圖。
*/
bool Init(Graph *g)
{
InsertEdge(g,1,2,6);
InsertEdge(g,1,4,7);
InsertEdge(g,2,3,5);
InsertEdge(g,2,4,8);
InsertEdge(g,2,5,-4);
InsertEdge(g,3,2,-2);
InsertEdge(g,4,3,-3);
InsertEdge(g,4,5,9);
InsertEdge(g,5,1,2);
InsertEdge(g,5,3,7);
return true;
}
/*取得兩個兩個節點連線的邊的權重*/
int Weight(const Graph *g,int u,int v)
{
Vertex * t = g->Adj[u]->next;
while(t)
{
if(t->id == v)
{
return t->weight;
}
t = t->next;
}
return 0;
}
bool Relax(Graph *g,int u,int v,int weight)
{
if(g->d[v] > (g->d[u] + Weight(g,u,v)))
{
g->d[v] = g->d[u] + Weight(g,u,v);
g->p[v] = u;
}
return true;
}
/*對邊進行鬆弛操作*/
bool Relax(Graph *g,int u,int v)
{
Relax(g,u,v,Weight(g,u,v));
return false;
}
/*
最短路徑估計和前驅化進行初始化
s 源頂點
*/
bool InitializeSingleSource(Graph *g,int s)
{
for(int i=1;i<=N;i++)
{
g->d[i] = INFINITE;
g->p[i] = 0;
}
g->d[s] = 0;
return true;
}
/*單源最短路徑的Bellman-Ford演算法*/
bool BellmanFord(Graph *g,int s)
{
InitializeSingleSource(g,s);
for(int i=1;i<N;i++)
{/*對每個邊進行N-1次鬆弛操作*/
for(int j=1;j<=N;j++)
{
Vertex * t = g->Adj[j]->next;
while(t)
{
Relax(g,j,t->id);
t = t->next;
}
}
}
for(int i=1;i<=N;i++)
{/*如果包含從原點可達的負權迴路,返回FALSE*/
Vertex * t = g->Adj[i]->next;
while(t)
{
if(g->d[t->id] > (g->d[i] + Weight(g,i,t->id)))
{
return false;
}
t = t->next;
}
}
return true;
}
/*
開始頂點 1
頂點 最短路徑
1 0
2 2
3 4
4 7
5 -2
*/
int main(int argc,char * argv[])
{
//構造一個空的圖
Graph *g = new Graph;
Init(g);
BellmanFord(g,1);
for(int i=1;i<=N;i++)
{
std::cout<<i<<"\t"<<g->d[i]<<std::endl;
}
delete g;
getchar();
return 0;
}
相關文章
- 《演算法導論》演算法
- 演算法導論-堆排序演算法排序
- 演算法導論-快速排序演算法排序
- 學演算法要讀《演算法導論》嗎?演算法
- 演算法導論第三十一(31)章數論演算法演算法
- 演算法導論-第6章演算法
- 演算法導論FFT程式碼演算法FFT
- 《演算法導論》學習筆記演算法筆記
- 演算法導論C語言實現: 演算法基礎演算法C語言
- 史蒂芬斯與演算法導論之思演算法
- 演算法導論第二章思考題演算法
- 演算法導論第二章筆記演算法筆記
- 演算法導論第二章練習演算法
- 演算法導論 3.2-7 共軛數演算法
- 演算法導論_第七章_快速排序演算法排序
- 演算法導論學習之五:快速排序演算法排序
- 演算法導論第三章練習演算法
- 演算法導論_第四章_分治策略演算法
- 演算法導論_第六章_堆排序演算法排序
- 演算法導論學習之六:歸併排序演算法排序
- 演算法導論16.1 活動選擇問題演算法
- 演算法導論-動態規劃-鋼條切割演算法動態規劃
- 演算法導論學習之二:插入排序演算法排序
- 演算法導論學習之一:氣泡排序演算法排序
- 演算法專題 | 10行程式碼實現的最短路演算法——Bellman-ford與SPFA演算法行程
- 演算法導論 3.1-8 記號擴充套件演算法套件
- 演算法導論第三版詳細答案演算法
- 【JAVA演算法】圖論演算法 -- Dijkstra演算法Java演算法圖論
- 圖論演算法圖論演算法
- POJ 3169(Bellman-Ford演算法,差分約束系統)演算法
- hdu1874 暢通工程續 Bellman-Ford演算法SPFA演算法
- 從零開書學演算法(導論)之歸併排序演算法排序
- 演算法導論-中位數和順序統計量演算法
- 演算法導論-動態規劃-裝配線排程演算法動態規劃
- 【圖論】Floyd演算法圖論演算法
- 演算法導論_第八章_線性時間排序演算法排序
- 演算法導論學習之補漏:高精度冪運算演算法
- 演算法導論_第十章_基本資料結構演算法資料結構