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