Dijkstra算法 算法基础篇(三)
View Code
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 }