单源最短路径-Dijkstra算法
2016-07-10 14:34
531 查看
Dijkstra算法求解单源最短路径比Bellman-Ford算法更加高效,但是缺陷是图中不能有权值为负数的边。
本代码中为了实现Dijstra算法使用到的数据结构或算法有:最小堆排序、松弛算法、贪心算法、有向图
保存此有向图的文件MapInfo.txt的内容如下:
s 10 t
s 5 y
t 1 x
t 2 y
y 3 t
y 9 x
y 2 z
x 4 z
z 6 x
z 7 s
左右两边的字符是节点名,中间的数字是两个节点所在边的权值。
具体代码实现如下:
这里纠正一个错误,堆的英文是Heal,我一直记成了Peal,导致整篇代码中到处都是Peal。
本代码中为了实现Dijstra算法使用到的数据结构或算法有:最小堆排序、松弛算法、贪心算法、有向图
保存此有向图的文件MapInfo.txt的内容如下:
s 10 t
s 5 y
t 1 x
t 2 y
y 3 t
y 9 x
y 2 z
x 4 z
z 6 x
z 7 s
左右两边的字符是节点名,中间的数字是两个节点所在边的权值。
具体代码实现如下:
/* * 单源最短路径_Dijkstra算法 * 用到的算法或数据结构有:最小堆排序 松弛算法 贪心算法 有向图 * author: StoryMonster * Last Change Date: 2016/7/1 */ #include <iostream> #include <stdio.h> #include <stdlib.h> #ifndef TOTAL_NODES_IN_MAP #define TOTAL_NODES_IN_MAP 5 #endif #define MAX_DEEP 10000 enum {White,Grey,Black}; typedef struct MapNode { int deep; char name; int color; } MapNode; typedef struct MinPeal { MapNode *node; int index; struct MinPeal *father; struct MinPeal *left; struct MinPeal *right; } MinPeal; typedef struct NeiborTable { MapNode * node; int weight; struct NeiborTable *next; } NeiborTable; NeiborTable *Head[TOTAL_NODES_IN_MAP]; MinPeal *PealRoot = (MinPeal *)malloc(sizeof(PealRoot)); int PealNodeCount = 0; static void InitHeads(); static void ReadConfigFile(); static void InsertToNeiborTable(MapNode *,MapNode *,int); static void ShowNeiborTable(); static void PutAllNodesToMinPeal(); static void InsertToPeal(MinPeal *,MinPeal *); static void GetTheMinNode(MinPeal *,MinPeal *); static MinPeal *GetMaxIndexPealNode(MinPeal *); static void FixThePeal(MinPeal *); static void Dijkstra(char NodeName); static NeiborTable *GetNeiborNode(char); static bool AllNodesAreBlack(); static void ShowShortestDistace(); void ShowShortestDistance(void) { for(int i=0;i < TOTAL_NODES_IN_MAP;i++) { std::cout << (Head[i]->node)->name << ":"<< (Head[i]->node)->deep<<std::endl; } } NeiborTable *GetNeiborNode(char name) { for(int i=0;i < TOTAL_NODES_IN_MAP; i++) { if(name == (Head[i]->node)->name) { return Head[i]; } } return NULL; } bool AllNodesAreBlack(void) { for(int i=0;i<TOTAL_NODES_IN_MAP;i++) { if((Head[i]->node)->color != Black) return false; } return true; } void DeepAll(char name , int deep) { for(int i=0;i<TOTAL_NODES_IN_MAP;i++) { NeiborTable *p = Head[i]; while(p != NULL) { if((p->node)->name == name) { (p->node)->deep = deep; } p = p->next; } } } void ColorAll(char name, int color) { for(int i=0;i < TOTAL_NODES_IN_MAP;i++) { NeiborTable *p = Head[i]; while(p != NULL) { if((p->node)->name == name) { (p->node)->color = color; } p = p->next; } } } void Dijkstra(char NodeName) { NeiborTable *p = GetNeiborNode(NodeName); (p->node)->color = Grey; (p->node)->deep = 0; ColorAll(NodeName,Grey); DeepAll((p->node)->name,0); FixThePeal(PealRoot); while(!AllNodesAreBlack()) { MinPeal *p3 = (MinPeal *)malloc(sizeof(MinPeal)); GetTheMinNode(PealRoot,p3); if(p3 == NULL) break; NeiborTable *p1 = GetNeiborNode((p3->node)->name); NeiborTable *p2 = p1->next; (p1->node)->color = Grey; ColorAll((p1->node)->name,Grey); while(p2 != NULL) { if((p2->node)->color == White) { if((p2->node)->deep > ((p1->node)->deep)+(p2->weight)) { (p2->node)->deep = (p1->node)->deep + p2->weight; //(p2->node)->color = Grey; DeepAll((p2->node)->name,(p2->node)->deep); //ColorAll((p2->node)->name,Grey); } } p2 = p2->next; } (p1->node)->color = Black; ColorAll((p1->node)->name,Black); FixThePeal(PealRoot); } } MinPeal *GetMaxIndexPealNode(MinPeal *root) { if(root == NULL) return NULL; if(root->index == PealNodeCount) return root; MinPeal *result = GetMaxIndexPealNode(root->left); if(result == NULL) result = GetMaxIndexPealNode(root->right); return result; } void FixThePeal(MinPeal *root) { if(root->left == NULL) return ; if(((root->left)->node)->deep < (root->node)->deep) { MapNode *temp = (root->left)->node; (root->left)->node = root->node; root->node = temp; if(root->father!=NULL ) FixThePeal(root->father); else FixThePeal(root->left); } if(root->right == NULL) return ; if(((root->right)->node)->deep < (root->node)->deep) { MapNode *temp = (root->right)->node; (root->right)->node = root->node; root->node = temp; if(root->father!=NULL ) FixThePeal(root->father); else FixThePeal(root->right); } } void GetTheMinNode(MinPeal *root, MinPeal *node) { node->node = root->node; node->father = NULL; node->left = NULL; node->right= NULL; MinPeal *p = GetMaxIndexPealNode(root); root->node = p->node; if(p == root) { free(p); p = NULL; root = NULL; PealNodeCount--; return ; } if((p->father)->left == p) (p->father)->left = NULL; else (p->father)->right = NULL; p->father = NULL; free(p); p = NULL; PealNodeCount--; FixThePeal(root); } void InsertToPeal(MinPeal *root,MinPeal *node) { if(PealRoot== NULL) { PealRoot = node; return ; } if(root == NULL) return ; if(node->index == 2*(root->index)) { root->left = node; node->father = root; return ; } if(node->index == 2*(root->index)+1) { root->right = node; node->father = root; return ; } InsertToPeal(root->left,node); InsertToPeal(root->right,node); } void PutAllNodesToMinPeal(void) { for(int i=0;i < TOTAL_NODES_IN_MAP;i++) { MinPeal *p = (MinPeal *)malloc(sizeof(MinPeal)); p->father = NULL; p->left = NULL; p->right = NULL; p->index = i+1; p->node = Head[i]->node; InsertToPeal(PealRoot,p); PealNodeCount++; } } void ShowNeiborTable(void) { std::cout << "neibor table:"<<std::endl; for(int i=0;i<TOTAL_NODES_IN_MAP;i++) { NeiborTable *p = Head[i]; while(p != NULL) { std::cout << (p->node)->name <<":" << p->weight<< " "; p = p->next; } std::cout << std::endl; } std::cout << "------------------------------" << std::endl; } void InsertToNeiborTable(MapNode *head, MapNode *node, int weight) { NeiborTable *p = (NeiborTable *)malloc(sizeof(NeiborTable)); p->weight = weight; p->node = node; for(int i=0;i<TOTAL_NODES_IN_MAP;i++) { if(Head[i] == NULL) { NeiborTable *pp = (NeiborTable *)malloc(sizeof(NeiborTable)); pp->node = head; pp->weight = 0; pp->next = NULL; Head[i] = pp; Head[i]->next = p; return ; } else { if((Head[i]->node)->name == head->name) { NeiborTable *pp = Head[i]; while(pp->next != NULL) pp = pp->next; pp->next = p; return ; } } } } void ReadConfigFile() { FILE *fp = fopen("MapInfo.txt","rb"); if(!fp) { std::cout <<"Open MapInfo.txt fail"<<std::endl; fp = NULL; return ; } while(1) { int weight = 0; char name1 = 0,name2 = 0; int n = fscanf(fp,"%c %d %c\n",&name1, &weight, &name2); if(n < 1) break; MapNode *node1 = (MapNode *)malloc(sizeof(MapNode)); MapNode *node2 = (MapNode *)malloc(sizeof(MapNode)); node1->name = name1; node1->color = White; node1->deep = MAX_DEEP; node2->name = name2; node2->color = White; node2->deep = MAX_DEEP; InsertToNeiborTable(node1,node2,weight); } fclose(fp); fp = NULL; } void InitHeads(void) { for(int i=0;i < TOTAL_NODES_IN_MAP;i++) { Head[i] = NULL; } } int main() { PealRoot = NULL; InitHeads(); ReadConfigFile(); ShowNeiborTable(); PutAllNodesToMinPeal(); Dijkstra('s'); ShowShortestDistance(); return 0; }
这里纠正一个错误,堆的英文是Heal,我一直记成了Peal,导致整篇代码中到处都是Peal。
相关文章推荐
- 基于Java实现的Dijkstra算法示例
- Dijkstra和floyd——求单源点最短路径
- 初学图论-Bellman-Ford单源最短路径算法
- 初学图论-DAG单源最短路径算法
- 初学图论-Dijkstra单源最短路径算法
- 初学图论-Dijkstra单源最短路径算法基于优先级队列(Priority Queue)的实现
- Dijkstra算法的粗略学习
- 【高手回避】poj3268,一道很水的dijkstra算法题
- poj2387 Til the Cows Come Home—Dijkstra模板
- YEN算法和删除算法分别实现K可靠最短路径算法
- Dijkstra 算法实现及问题
- Djkstra
- 最短路
- 一个人的旅行
- HDU 2544
- 文章标题
- BellmanFord单源最短路径路径算法差分约束系统ZOJ–2770
- Dijkstra算法学习笔记(1)
- 最短路?那是什么 °▽°
- Dijkstra算法