Dijkstra算法优先级队列版 算法基础篇(三)

View Code
  1 // 优先队列的Dijkstra算法.cpp : 定义控制台应用程序的入口点。
  2 //
  3 
  4 #include "stdafx.h"
  5 #include <stdio.h>
  6 #include <queue>
  7 #include <vector>
  8 #include <stdlib.h>
  9 using namespace std;
 10 #define  NotAVertex (-1)
 11 #define  NumVertex 20
 12 #define  Infinity 1000
 13 typedef int Vertex;
 14 typedef int Arc;
 15 typedef int DistType;
 16 //typedef struct TableEntry* List;
 17 
 18 struct TableNode     //表节点
 19 {
 20     Vertex V;
 21     DistType Weigh;       //边重
 22     struct TableNode* NextArc;
 23 };
 24 
 25 typedef struct TableNode* EdgeNode;
 26 typedef struct ListNode* VexNode; //定义头节点指针
 27 struct ListNode     //头节点
 28 {
 29     Vertex V;
 30     EdgeNode FirstArc;
 31     DistType Dist;
 32     int  Known;
 33     Vertex Path;
 34 
 35     friend bool operator> ( struct ListNode n1,struct ListNode n2) //因为使用到greater模板 需要操作符>重载
 36     {
 37         return n1.Dist> n2.Dist;
 38     }
 39 
 40 };
 41 
 42 //typedef struct ListNode Node[NumVertex];
 43 typedef struct ListNode ListNode;
 44 priority_queue<ListNode,vector<ListNode>,greater<ListNode> > PriorVexQue; //申明优先级队列的类型 默认是less
 45 
 46 struct Graphic                 //图的结构体 包括有边数,点数,头节点数组
 47 {
 48     Vertex VertexNum;
 49     Arc    ArcNum;
 50     struct ListNode Adj[NumVertex];
 51 };
 52 
 53 typedef struct Graphic* Graph;
 54 
 55 void ReadGraph(Graph G)             //图的输入函数
 56 {
 57     Vertex from,to;
 58     DistType weight;
 59     struct TableNode *S;
 60     printf("请输入节点数和边数,注意为整型!\n");
 61     scanf("%d%d",&(G->VertexNum),&(G->ArcNum));
 62     if(G->ArcNum<=0||G->VertexNum<=0)
 63     {
 64         printf("图边数或点数必须大于零\n");
 65         return;
 66     }
 67     for(int i =0;i<G->ArcNum;i++)
 68     {
 69         printf("请输入第%d条边的起点,终点和权值!\n",i+1);
 70         scanf("%d%d%d",&from,&to,&weight);
 71         S=(EdgeNode)malloc(sizeof(struct TableNode));
 72         S->V=to;
 73         S->Weigh=weight;
 74         S->NextArc=G->Adj[from].FirstArc;       //这里是from的头边给S的下一条边,这里是表节点插入细节,好好体会下。
 75         G->Adj[from].FirstArc=S;
 76     }
 77 
 78 }
 79 
 80 void InitNode(Graph G)                     //图的初始化
 81 {
 82     int i ;
 83     for(i=0;i<NumVertex;i++)
 84     {
 85         G->Adj[i].V=i;
 86         G->Adj[i].Path=NotAVertex;
 87         G->Adj[i].Known=false;
 88         G->Adj[i].Dist=Infinity;
 89         G->Adj[i].FirstArc=NULL;
 90     }
 91     ReadGraph(G);
 92     G->Adj[0].Dist=0;
 93 }
 94 #if 0
 95 
 96 Vertex ExtractMin(Graph G)                              //较为简单的寻找最小值函数,复杂度O(n),一直不是很满意
 97 {
 98     int i;int j=Infinity;
 99     Vertex Min=Infinity;
100     for(i=0;i<G->VertexNum;i++)
101     {
102         if(!(G->Adj[i].Known)&&Min>G->Adj[i].Dist)//刚开始犯了一个很傻的错误,这里的第二个条件放到第一个循环了,总是不对。
103         {
104             Min=G->Adj[i].Dist;
105             j=i;
106         }
107     }
108     if(j==Infinity) return -1;
109     return j;
110 }
111 #endif
112 
113 
114 
115 void PrintPath(Graph G,Vertex V)             //打印分支函数,只能打印一条分支。
116 {
117     if(G->Adj[V].Path!=NotAVertex)
118     {
119         PrintPath(G,G->Adj[V].Path);
120             printf("to");
121     }
122     printf("  %d  ",V);
123 }
124 
125 
126 
127 void Dijkstra(Graph G)                      //函数::步步贪心,最终全体贪心
128 {
129     Vertex Value;
130     EdgeNode pVex;
131     PriorVexQue.push(G->Adj[0]);
132     for(int i=0;i<G->VertexNum;i++)
133     {
134         Value=PriorVexQue.top().V;     //抽取图中最小距离的点,纳入{S}
135         PriorVexQue.pop();
136         if(Value==NotAVertex)
137             break;
138         G->Adj[Value].Known=true;
139         pVex=G->Adj[Value].FirstArc;
140     //    pEdge=pVex->NextArc;
141         while(pVex!=NULL)                    //对图{Q-S}点的集合中与距离最小点毗邻的点做松弛操作
142         {
143             
144             if(!(G->Adj[pVex->V].Known))     //邻接的节点更新
145             {
146                 if(G->Adj[Value].Dist+pVex->Weigh< G->Adj[pVex->V].Dist)
147                 {
148                     G->Adj[pVex->V].Dist=G->Adj[Value].Dist+pVex->Weigh;
149                     G->Adj[pVex->V].Path=Value;
150                 }
151                 PriorVexQue.push(G->Adj[pVex->V]);
152             }
153             pVex=pVex->NextArc;
154         }
155     }
156 }
157 
158 Vertex ReturnDistMax(Graph G) //这个函数是为了方便Print调用的,可以不要。
159 {
160     int i;
161     Vertex key=0;
162     DistType Max=0;
163     for(i=0;i<G->VertexNum;i++)
164         if(G->Adj[i].Dist>Max)
165         {
166             Max=G->Adj[i].Dist;
167             key=i;
168         }
169         return key;
170 
171 
172 }
173 
174 
175 int _tmain(int argc, _TCHAR* argv[])
176 {
177     int i;
178     Vertex V;
179     Graph G=(Graph)malloc(sizeof(Graphic));
180     InitNode(G);
181     Dijkstra(G);
182 //    PrintPath(G,4);
183     printf("\n");
184     for(i=0;i<G->VertexNum;i++)
185     {
186         printf("##  %d  ##",G->Adj[i].Dist);
187         printf("##$  %d  $##",G->Adj[i].Path);
188     }
189 
190     V=ReturnDistMax(G);
191         
192     PrintPath(G,V);
193 
194 
195 
196     return 0;
197 }
原文地址:https://www.cnblogs.com/cslave/p/2549131.html