Bellman_Ford算法和Dijkstra算法都可以用来求解有向图的单源最短路径问题,但是,相比于Dijkstra算法, Bellman_Ford算法允许边的权重为负值。
算法的详细讨论见算法导论或者下面这个博客http://blog.csdn.net/niushuai666/article/details/6791765
代码如下:
#include<iostream> using namespace std; #define Inf 65535 #define NotAVerter -1 /////////////////////邻接链表的相关定义////////////////////// typedef struct EdgeNode *position; typedef struct Led_table* Table; struct EdgeNode //边表结点 { int adjvex; // 邻接点域,存储该顶点对应的下标 int weight; // 对应边的权值 int dis; //此数据记录从源点到该节点的最短距离 int precursor; //此数据记录该节点在广度优先树种的前驱节点 position next; // 链域,指向下一个邻接点 }; struct Led_table // 邻接表结构 { int data; //邻接表的大小 position *firstedge; //边表头指针,可以理解为数组 }; //////////////////////////邻接链表相关函数定义/////////////// Table Creat_Lable(int MaxElements) //MaxElements参数为希望创建的节点数 { Table table1 = static_cast<Table> (malloc(sizeof(struct Led_table))); table1->data = MaxElements; if (table1 == NULL) { cout << "out of space!!!"; } table1->firstedge = static_cast<position*>(malloc(sizeof(position)*(table1->data))); if (table1->firstedge == NULL) { cout << "out of space!!!"; } //给每个表头赋值,从0开始 for (int i = 0; i <= table1->data - 1; ++i) { table1->firstedge[i] = static_cast<position>(malloc(sizeof(EdgeNode))); //申请一个节点 if (table1->firstedge[i] == NULL) { cout << "out of space!!!"; } table1->firstedge[i]->adjvex = 0; //表头这个参数没有意义 table1->firstedge[i]->weight = 0; //表头这个参数没有意义 table1->firstedge[i]->dis = Inf; table1->firstedge[i]->precursor = NotAVerter; table1->firstedge[i]->next = NULL; } return table1; } void Insert(Table table1, int v, int w, int weig) //表示存在一条边为<v,w> { position p = static_cast<position>(malloc(sizeof(EdgeNode))); //申请一个节点 if (p == NULL) { cout << "out of space!!!"; } p->adjvex = w; p->weight = weig; //对于无权图来说,该域可以设置为1 p->dis = Inf; //对于普通节点来说无意义 p->precursor = NotAVerter; //对于普通节点来说无意义 p->next = table1->firstedge[v]->next; table1->firstedge[v]->next = p; } void init_yuandian(Table table1, int s) //把s设置为图的源点 { table1->firstedge[s]->adjvex = 0; table1->firstedge[s]->weight = 0; table1->firstedge[s]->dis = 0; //源点的这个值设置为0 table1->firstedge[s]->precursor = NotAVerter; } bool Bellman_Ford(Table table1, int s) { for (int i = 1; i <= table1->data - 1; ++i) //每条边进行N-1次松弛操作 { for (int j = 0; j <= table1->data - 1; ++j) //对每条边 { position p = table1->firstedge[j]->next; while (p != NULL) { if (table1->firstedge[p->adjvex]->dis > table1->firstedge[j]->dis + p->weight) //松弛操作 { table1->firstedge[p->adjvex]->dis = table1->firstedge[j]->dis + p->weight; table1->firstedge[p->adjvex]->precursor = j; } p = p->next; } } } bool flag = true; for (int j = 0; j <= table1->data - 1; ++j) //对每条边 { position p = table1->firstedge[j]->next; while (p != NULL) { if (table1->firstedge[p->adjvex]->dis > table1->firstedge[j]->dis + p->weight) { flag = false; break; } p = p->next; } } return flag; } void print_path(Table table1, int v) { if (table1->firstedge[v]->precursor != NotAVerter) print_path(table1, table1->firstedge[v]->precursor); cout << "v" << v << endl; } int main() { Table table_1 = Creat_Lable(5); //创建一个大小为5的邻接表 Insert(table_1, 0, 1, 6); Insert(table_1, 0, 3, 7); Insert(table_1, 1, 2, 5); Insert(table_1, 1, 3, 8); Insert(table_1, 1, 4, -4); Insert(table_1, 2, 1, -2); Insert(table_1, 3, 2, -3); Insert(table_1, 3, 4, 9); Insert(table_1, 4, 0, 2); Insert(table_1, 4, 2, 7); init_yuandian(table_1, 0); //把0设置为图的源点 cout << Bellman_Ford(table_1, 0) << endl; cout << table_1->firstedge[4]->dis << endl; print_path(table_1, 4); return 0; }
夜深了,夜更深了