最短路是个老问题了,大神们留下很多文档但是很多都是针对算法使用一些固定大小的数组进行数据存储在实际应用中受到限制,这里自己练习一下,主要用了一些c++的stl,减少了固定长度数组的依赖,换一种写法试图提高可读性。有兴趣的同学可以试着将map/set 换成 hash_set/hash_map 应该能获得更高的效率,对于稀疏表,内存还是能省不少的。
参考文献: http://www.cnblogs.com/hxsyl/p/3270401.html
1
/*
**********************************************************************
*/
2
/*
尽量用简单快速好理解的方法完成图的最短路径
*/
3
/*
**********************************************************************
*/
4 #include <stdio.h>
5 #include <
string.h>
6 #include <malloc.h>
7
8 #include <iostream>
9 #include <sstream>
10 #include <
string>
11
12 #include <
set>
13 #include <map>
14 #include <vector>
15 #include <queue>
16
17 #include <algorithm>
18
19
using
namespace std;
20
21 typedef size_t Index;
22
23
//
使用整数比string快
24
map<
string, Index> g_mapNode;
//
string -> index
25
map<Index,
string> g_mapNodeIndex;
//
index -> string
26
map<Index,
set<Index> > g_mapLink;
//
邻接表
27
28 inline
bool IsNullString(
const
char* pcName)
29 {
30
return (NULL == pcName) && (
'
\0
' == pcName[
0]);
31 }
32
33 inline
bool IsNodeExist(
const
string& strName)
34 {
35
return g_mapNode.end() != g_mapNode.find(strName);
36 }
37
38
bool FindPath1(Index uSource, Index uTarget, vector<Index>& vecRlst)
39 {
40 map<Index, size_t> mapDistence;
41 map<Index, Index> mapPath;
42
43
//
inistalize
44
map<Index,
set<Index> >::iterator iterInit = g_mapLink.begin();
45
for (; iterInit != g_mapLink.end(); ++iterInit)
46 {
47
if (iterInit->second.count(uTarget) !=
0)
48 {
49 mapDistence[iterInit->first] =
1;
50 mapPath[iterInit->first] = uTarget;
51 }
52 }
53
54
//
find
55
size_t uNodeNum = g_mapNode.size();
56
for (size_t i =
0; i < uNodeNum; ++i)
57 {
58
for (size_t j =
0; j < uNodeNum; ++j)
59 {
60
if (g_mapLink.count(i) !=
0 && g_mapLink[i].count(j) !=
0)
//
i - > j 是通的
61
{
62
if (mapDistence.count(j) !=
0
//
j -> uTarget是通的
63
&& (mapDistence.count(i) ==
0
//
i -> uTarget 不存在或者 比从 j走远
64
|| (mapDistence[j] +
1 < mapDistence[i])))
65 {
66 mapDistence[i] = mapDistence[j] +
1;
//
更新距离
67
mapPath[i] = j;
//
更新下一跳地址
68
}
69 }
70 }
71 }
72
73
//
不可到达
74
if (mapDistence.count(uSource) ==
0)
75 {
76
return
false;
77 }
78
79
while (uSource != uTarget)
80 {
81 vecRlst.push_back(uSource);
82 uSource = mapPath[uSource];
83 }
84 vecRlst.push_back(uSource);
85
86
return
true;
87 }
88
89
bool FindPath2(Index uSource, Index uTarget, vector<Index>& vecRlst)
90 {
91 map<Index, Index> mapLastJump;
92 queue<Index> queNodeQue;
93
94
bool bIsFind =
false;
95 queNodeQue.push(uSource);
96
while (!queNodeQue.empty() && !bIsFind)
97 {
98 Index uIdx = queNodeQue.front();
99 queNodeQue.pop();
100
if (g_mapLink.count(uIdx) ==
0)
101 {
102
continue;
103 }
104
105
set<Index>::iterator iter = g_mapLink[uIdx].begin();
106
for (; iter != g_mapLink[uIdx].end(); iter++)
107 {
108
if (mapLastJump.count(*iter) !=
0)
109 {
110
continue;
111 }
112
113 mapLastJump[*iter] = uIdx;
114
if (*iter == uTarget)
115 {
116 bIsFind =
true;
117
break;
118 }
119 queNodeQue.push(*iter);
120 }
121 }
122
123
if (!bIsFind)
124 {
125
return
false;
126 }
127
128
while(uTarget != uSource)
129 {
130 vecRlst.push_back(uTarget);
131 uTarget = mapLastJump[uTarget];
132 }
133 vecRlst.push_back(uSource);
134
135 reverse(vecRlst.begin(), vecRlst.end());
136
137
return
true;
138 }
139
140
void cmdInitialize()
141 {
142 g_mapNode.clear();
143 g_mapLink.clear();
144 }
145
146
bool cmdAddNode(
const
char *pcNode)
147 {
148
if (IsNullString(pcNode))
149 {
150
return
false;
151 }
152
153
string strName(pcNode);
154
if (IsNodeExist(strName))
155 {
156
return
false;
157 }
158
159 Index uIndex = g_mapNode.size();
160 g_mapNode[strName] = uIndex;
161 g_mapNodeIndex[uIndex] = strName;
162
163
return
true;
164 }
165
166
bool cmdAddLink(
const
char *pcSource,
const
char *pcTarget)
167 {
168
if (IsNullString(pcSource) || IsNullString(pcTarget))
169 {
170
return
false;
171 }
172
173
string strSource(pcSource);
174
string strTarget(pcTarget);
175
176
if (!IsNodeExist(strSource) || !IsNodeExist(strTarget) || strSource == strTarget)
177 {
178
return
false;
179 }
180
181 g_mapLink[g_mapNode[strSource]].insert(g_mapNode[strTarget]);
182 g_mapLink[g_mapNode[strTarget]].insert(g_mapNode[strSource]);
183
184
return
true;
185 }
186
187
bool cmdFindPath(
const
char *pcSource,
const
char *pcTarget,
char **ppcRlstPath)
188 {
189
if (NULL == ppcRlstPath)
190 {
191
return
false;
192 }
193 *ppcRlstPath = NULL;
194
195
string strSource(pcSource);
196
string strTarget(pcTarget);
197
198
if (!IsNodeExist(strSource) || !IsNodeExist(strTarget) || strSource == strTarget)
199 {
200
return
false;
201 }
202
203 vector<Index> vecPath;
204
//
if(!FindPath1(g_mapNode[strSource], g_mapNode[strTarget], vecPath))
205
if(!FindPath2(g_mapNode[strSource], g_mapNode[strTarget], vecPath))
206 {
207
return
false;
208 }
209
210
string strOutPut;
211 stringstream ssOutPut(
"");
212
for (size_t u =
0; u < vecPath.size(); ++u)
213 {
214 ssOutPut << g_mapNodeIndex[vecPath[u]] <<
"
->
";
215 }
216
217 strOutPut = ssOutPut.str();
218 strOutPut = strOutPut.substr(
0, strOutPut.length() -
2);
219
220 *ppcRlstPath = (
char *)malloc(
sizeof(
char) * (strOutPut.length() +
1));
221
if (NULL == *ppcRlstPath)
222 {
223
return
false;
224 }
225
226 strcpy(*ppcRlstPath, strOutPut.c_str());
227
228
return
true;
229 }
230
231
int main()
232 {
233 cmdInitialize();
234
235 cmdAddNode(
"
A
");
236 cmdAddNode(
"
B
");
237 cmdAddNode(
"
C
");
238 cmdAddNode(
"
D
");
239
240 cmdAddLink(
"
A
",
"
B
");
241 cmdAddLink(
"
B
",
"
C
");
242 cmdAddLink(
"
C
",
"
D
");
243 cmdAddLink(
"
B
",
"
D
");
244
245
char *pcPath = NULL;
246
if (cmdFindPath(
"
A
",
"
D
", &pcPath))
247 {
248 printf(
"
%s\n
", pcPath);
249 free(pcPath);
250 pcPath = NULL;
251 }
252
253
return
0;
254 }