由于程序是没人那么聪明的,只有遍历了。
首先,两点之间加上中间那条线,用个类保存,类说明了这段路程的三个基本属性:起始点、结束点、需要时间,剩下的五个附加属性是遍历的时候要用到的:skip、hasFrontNode、eNodeIsBranchEndNode、sNodeIsBranchEndNode、sNodeIsBranchBeginNode,skip说明这段是否已经走过, hasFrontNode说明是否还有前驱节点,eNodeIsBranchEndNode说明这段路程的尾节点是否有多个前驱,sNodeIsBranchBeginNode是头节点是否有多个后继。
首先,将所有路程信息用个数组保存起来。addProcessInfo(int sNode,int eNode,int lTime)是将一段路程的基本信息保存,setup()加入多段具体的路程信息,然后setNodeTag() 为每段路程信息的附加属性赋值。
最主要的就在searchProcess(int sNode,int eNode)函数了,这是求任意两点间的,理论上来说,顺着找和倒着找是一样的,但是为了这个项目,我用的是倒着找的,因为要的是开始点到某个点的,顺着找的话,会走好多冤枉路,倒着的话,由于起点就一个,一般可以直接找到,而不会走过去了。
下面说说这段函数的原理:
找路径,好比人走路,找最优路径,需要走遍所有的路才能知道。一开始,看看所处的位置可以有几条路,都记下来,然后,每次挑一条可以走的路,走下去,走到走不动的地方,往回走,直到回到上个叉路口,如果回到起点,只能说明,没路了.....否则,就从后退到的那个路口继续那样的找路过程。走到终点后,记下这条路,然后,回到上个叉路口,继续走,又到终点,比比原来记下来的路,看哪条好,去掉不好的。一直就这么找,直到你走完所有的可能,才可能得到最优的解。
找一个点到另一个点的最优路径,对于程序来说,问题就在于怎么保存走过的路,应该怎么保存,保存的是什么内容。由于我是倒着找的,所以在这段代码中,我保存的是new ProcessInfo(sNode, eNode,pInfo.lastingTime),实际上是不存在这样的路径的,只是为了方便回溯保存的,然后,递归找开始节点到当前路径的开始节点间的路径。
下面我把代码贴出来,再附加二个调试信息,方便大家理解,关于那个网络图的定义可以在setup()函数中修改。
首先是保存路径信息的类(ProcessInfo.java):
1
/**
2
* @author zxub Created on 2005-5-21 10:36:29
3
*
4
*/
5
public class ProcessInfo {
6
7
//基本信息:startNode,endNode,lastingTime
8
protected int startNode; //开始节点
9
protected int endNode; //终止节点
10
protected int lastingTime; //路径持续时间
11
//下面是附加信息,遍历的时候用到
12
protected boolean skip; //判断该路径是否已经走过
13
protected boolean hasFrontNode; //路径是否有前驱节点
14
protected boolean eNodeIsBranchEndNode; //路径终止节点是否有多个前驱
15
protected boolean sNodeIsBranchBeginNode; //路径开始节点是否有多个后继
16
17
/**
18
* 保存任意两点间路径信息
19
* @param sNode 开始节点
20
* @param eNode 终止节点
21
* @param lTime 持续时间
22
*/
23
public ProcessInfo(int sNode,int eNode,int lTime)
24
{
25
this.startNode=sNode;
26
this.endNode=eNode;
27
this.lastingTime=lTime;
28
//由于是刚开始保存,下面的几个信息不能确立,所以都是false
29
this.skip=false;
30
this.hasFrontNode=false;
31
this.eNodeIsBranchEndNode=false;
32
this.sNodeIsBranchBeginNode=false;
33
}
34
}
然后,是主要的处理类(ProcessOpera.java):
2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

1
import java.util.Stack;
2
3
/**
4
* @author zxub Created on 2005-5-22 10:19:51
5
*/
6
public class ProcessOpera
7
{
8
9
final int MAX = 100;
10
// 保存路径信息的数组
11
ProcessInfo process[] = new ProcessInfo[MAX];
12
// 保存路径数目
13
int numProcess = 0;
14
// 分支路径栈
15
Stack branchProcessStack = new Stack();
16
// 用于搜索回退的栈
17
Stack backTrackStack = new Stack();
18
// 保存最后结果的栈
19
Stack resultStack = new Stack();
20
// 最长持续时间
21
int maxLastingTime = 0;
22
23
/**
24
* 测试用
25
*
26
* @param args
27
*/
28
public static void main(String[] args)
29
{
30
31
ProcessOpera processOpera = new ProcessOpera();
32
processOpera.setup();
33
processOpera.setNodeTag();
34
// for (int i = 0; i < processOpera.numProcess; i++)
35
// {
36
// System.out.print(processOpera
37
// .getItemEarliestBeginTime(processOpera.process[i].startNode)
38
// + " ");
39
// System.out.print(processOpera.getProcessEarliestEndTime(
40
// processOpera.process[i].startNode,
41
// processOpera.process[i].endNode)
42
// + " ");
43
// System.out.print(processOpera.getProcessEarliestBeginTime(
44
// processOpera.process[i].startNode,
45
// processOpera.process[i].endNode)
46
// + " ");
47
// System.out.print(processOpera
48
// .getItemLatestEndTime(processOpera.process[i].startNode)
49
// + " ");
50
// System.out.print(processOpera.getProcessLatestBeginTime(
51
// processOpera.process[i].startNode,
52
// processOpera.process[i].endNode)
53
// + " ");
54
// System.out.print(processOpera.getProcessLatestEndTime(
55
// processOpera.process[i].startNode,
56
// processOpera.process[i].endNode)
57
// + " ");
58
// System.out.print(processOpera.getProcessIntervalTime(
59
// processOpera.process[i].startNode,
60
// processOpera.process[i].endNode)
61
// + " ");
62
// System.out.print(processOpera.getKeyPath(
63
// processOpera.process[i].startNode,
64
// processOpera.process[i].endNode)
65
// + " ");
66
// System.out.println();
67
// }
68
//
69
// System.out.println(processOpera.getItemEarliestBeginTime(1));
70
processOpera.searchProcess(2, 8, 0);
71
processOpera.showPath();
72
}
73
74
/**
75
* 初始化所有路径信息,放进数组中
76
*/
77
public void setup()
78
{
79
addProcessInfo(1, 2, 60);
80
addProcessInfo(2, 3, 10);
81
addProcessInfo(2, 4, 20);
82
addProcessInfo(2, 5, 40);
83
addProcessInfo(2, 7, 45);
84
addProcessInfo(3, 7, 18);
85
addProcessInfo(4, 5, 0);
86
addProcessInfo(4, 6, 30);
87
addProcessInfo(5, 7, 15);
88
addProcessInfo(6, 7, 25);
89
addProcessInfo(7, 8, 35);
90
addProcessInfo(8, 8, 0);
91
}
92
93
/**
94
* 增加路径信息到数组中
95
*
96
* @param sNode
97
* 开始节点
98
* @param eNode
99
* 终止节点
100
* @param lTime
101
* 持续时间
102
*/
103
public void addProcessInfo(int sNode, int eNode, int lTime)
104
{
105
if (numProcess < MAX) // 如果数组没满的话
106
{
107
process[numProcess] = new ProcessInfo(sNode, eNode, lTime);
108
numProcess++;
109
}
110
else
111
{
112
System.out
113
.println("ProcessInfo database full!\nAdd error,program exit!");
114
System.exit(0);
115
}
116
}
117
118
/**
119
* 给所有路径信息中的附加属性赋值,要完成的话,需要遍历路径数组中的所有元素。 对于每个元素,要查看数组中的其它元素,确立关系
120
*/
121
public void setNodeTag()
122
{
123
for (int i = 0; i < numProcess; i++) // 遍历路径数组中的所有元素,process[i]是选取的路径
124
{
125
for (int j = 0; j < numProcess; j++) // 查看其它元素
126
{
127
if (i == j) continue; // 自己比自己,没得比,继续下次循环
128
// 发现有路径可以和选取路径连接
129
if (process[j].endNode == process[i].startNode)
130
{
131
process[i].hasFrontNode = true;
132
}
133
// 两条不同路径的终结点一样
134
if (process[j].endNode == process[i].endNode)
135
{
136
process[i].eNodeIsBranchEndNode = true;
137
}
138
// 两条不同路径的起始点一样
139
if (process[j].startNode == process[i].startNode)
140
{
141
process[i].sNodeIsBranchBeginNode = true;
142
}
143
}
144
}
145
}
146
147
/**
148
* 找出以选取点为终结点的没走过的一条路径
149
*
150
* @param eNode
151
* 所选取的点
152
* @return 没被走过的以选取点为终结点的一条路径
153
*/
154
public ProcessInfo findProcessInfo(int eNode)
155
{
156
for (int i = 0; i < numProcess; i++) // 遍历路径信息
157
{
158
// process[i].skip=false 路径才没被走过
159
if ((process[i].endNode == eNode) && (!process[i].skip))
160
{
161
// 由于深度复制和浅度复制的问题,所以复制的时候要新建一个ProcessInfo,而不是引用原来
162
// 这是实现问题,算法与此可以无关
163
ProcessInfo pInfo = new ProcessInfo(process[i].startNode,
164
process[i].endNode, process[i].lastingTime);
165
process[i].skip = true;
166
pInfo.hasFrontNode = process[i].hasFrontNode;
167
pInfo.eNodeIsBranchEndNode = process[i].eNodeIsBranchEndNode;
168
return pInfo;
169
}
170
}
171
return null; // 没有合适的路径就返回null了
172
}
173
174
/**
175
* 核心部分所在,查找任意2点间最长路径 基于AI设计,简单的AI 理论上来说,顺着找和倒着找是一样的,由于项目原因,这里我是倒着找的
176
* 查找到的路径放在结果栈resultStack中
177
*
178
* @param sNode
179
* 开始节点
180
* @param eNode
181
* 终止节点
182
* @param depth
183
* 显示debug信息的时候用到,用于显示层次关系
184
*/
185
public void searchProcess(int sNode, int eNode, int depth)
186
{
187
// 变量定义尽量少放循环中,故先定义
188
int lastingTime; // 持续时间
189
ProcessInfo pInfo; // 保存路径信息的对象
190
int numStartNode = 0; // 查找起点的个数
191
Stack resultTemp; // 保存查找到路径的临时栈
192
while ((pInfo = findProcessInfo(eNode)) != null)
193
{
194
// 分支节点数目+1
195
numStartNode++;
196
// 将查找到的路径信息放到分支节点栈,然后再查
197
branchProcessStack.push(pInfo);
198
showDebugInfo("分支路径栈加入:" + pInfo.startNode + "-->" + pInfo.endNode,
199
depth);
200
}
201
if (numStartNode > 0) // 有分支的话,如果这里不成立,整个就结束了
202
{
203
for (int i = 0; i < numStartNode; i++) // 遍历分支节点栈
204
{
205
pInfo = (ProcessInfo) branchProcessStack.pop(); // 获得一条分支路径
206
showDebugInfo("分支路径栈弹出:" + pInfo.startNode + "-->"
207
+ pInfo.endNode, depth);
208
// 为了防止头尾一样的路径,有了下面的判断,理论上是没有,但实际会出现
209
if (pInfo.startNode == pInfo.endNode)
210
{
211
showDebugInfo("头尾节点一样,丢弃!", depth + 1);
212
continue;
213
}
214
215
// 如果存在可到达的路径的话,注意,这是个递归过程
216
if (pInfo.startNode == sNode)
217
{
218
// 当前路径加入回退栈,此时,回退栈里可以找出一条完整的路径了
219
backTrackStack.push(pInfo);
220
showDebugInfo("--------到达起点:" + pInfo.startNode + "-->"
221
+ pInfo.endNode + "--------", depth);
222
int numbackTrackStack = backTrackStack.size();
223
resultTemp = new Stack();
224
lastingTime = 0;
225
for (int j = 0; j < numbackTrackStack; j++)
226
{
227
pInfo = (ProcessInfo) backTrackStack.get(j);
228
showDebugInfo("回溯栈内容进入临时结果栈:" + pInfo.startNode + "-->"
229
+ pInfo.endNode, depth);
230
lastingTime += pInfo.lastingTime;
231
resultTemp.push(pInfo);
232
}
233
// 判断是不是更好的解
234
if (lastingTime > maxLastingTime)
235
{
236
showDebugInfo("========找到更优解!========", depth);
237
maxLastingTime = lastingTime;
238
resultStack = resultTemp;
239
}
240
// 找出一条后,需要回退,然后继续找下一条
241
// 获得剩余分支路径的数目
242
int numBranch = branchProcessStack.size();
243
244
if (numBranch == 0)
245
{
246
// 没分支路径了,查找结束,清空回退栈
247
backTrackStack.removeAllElements();
248
}
249
else if (numBranch > 0)
250
{
251
int index = numBranch - 1;
252
int backTrackValue = ((ProcessInfo) branchProcessStack
253
.get(index)).endNode;
254
showDebugInfo("--------回退到节点:" + backTrackValue
255
+ "--------", depth);
256
// 要回退到的节点必是分支路径栈中最上路径的尾节点
257
// 下面的循环就是一直回退,由于还有分支路径,所以可以找到要退到的点
258
do
259
{
260
pInfo = (ProcessInfo) backTrackStack.pop();
261
showDebugInfo("找到目标,回溯栈回退到:" + pInfo.startNode
262
+ "-->" + pInfo.endNode, depth);
263
}
264
while (pInfo.endNode != backTrackValue);
265
}
266
// 回退后,继续查找的话,所有路径的经过标记都要重置,否则经过了的路径是不会再去查的
267
// 由于开始路径不同,所以不会找到同样的结果
268
resetAllSkip();
269
continue;// 开始从下个分支路径查找
270
}
271
else
272
// 没有直接从sNode到eNode的工序
273
{
274
// 还没到目标
275
// 如果当前路径的起点还有前驱节点的话,需要递归查找,这是重点
276
if (pInfo.hasFrontNode)
277
{
278
ProcessInfo btPInfo = new ProcessInfo(sNode, eNode,
279
pInfo.lastingTime);
280
btPInfo.eNodeIsBranchEndNode = pInfo.eNodeIsBranchEndNode;
281
// 说明找过sNode-->eNode
282
backTrackStack.push(btPInfo);
283
showDebugInfo("回溯栈加入:" + sNode + "-->" + eNode
284
+ ",说明找过" + sNode + "-->" + eNode, depth + 1);
285
showDebugInfo("查找:" + sNode + "-->" + pInfo.startNode,
286
depth + 1);
287
searchProcess(sNode, pInfo.startNode, depth + 2);
288
}
289
else
290
// 当前路径的起点无前驱,则路径错误,需要回溯
291
{
292
// 如果当前路径的终结点还有其它前驱的话,则退出本次循环,从下个分支路径查找
293
if (pInfo.eNodeIsBranchEndNode)
294
{
295
continue;
296
}
297
// 如果当前路径的终结点没有其它前驱,就要回退了
298
else if (backTrackStack.size() > 0)
299
{
300
// 开始回退,一直到找到个路径的终止节点有多个前驱为止,或者是回退栈已经空了。
301
do
302
{
303
pInfo = (ProcessInfo) backTrackStack.pop();
304
showDebugInfo("路径错误,开始回溯,回溯栈弹出:"
305
+ pInfo.startNode + "-->"
306
+ pInfo.endNode, depth + 1);
307
}
308
while ((!pInfo.eNodeIsBranchEndNode)
309
&& (backTrackStack.size() > 0));
310
}
311
}
312
}
313
}
314
showDebugInfo("分支已被找遍", depth);
315
}
316
else
317
{
318
showDebugInfo("前面已走过这条路径且被证明走不通,或尾节点没有前驱节点", depth);
319
if (backTrackStack.size()>0)
320
{
321
pInfo = (ProcessInfo) backTrackStack.pop();
322
showDebugInfo("路径不通,回溯栈弹出:" + pInfo.startNode + "-->"
323
+ pInfo.endNode, depth - 1);
324
if (branchProcessStack.size()>0)
325
{
326
int fixNode = ((ProcessInfo) branchProcessStack.lastElement()).endNode;
327
if (fixNode != pInfo.endNode)
328
{
329
showDebugInfo("========需要调整回溯栈========", depth);
330
showDebugInfo("========开始调整回溯栈========", depth);
331
do
332
{
333
pInfo = (ProcessInfo) backTrackStack.pop();
334
showDebugInfo("回溯栈弹出:" + pInfo.startNode + "-->"
335
+ pInfo.endNode, depth + 1);
336
}
337
while (fixNode != pInfo.endNode);
338
showDebugInfo("========回溯栈调整结束========", depth);
339
}
340
}
341
}
342
}
343
}
344
345
private void showDebugInfo(String info, int blankCount)
346
{
347
String blank = "";
348
for (int i = 0; i < blankCount; i++)
349
{
350
blank += " ";
351
}
352
System.out.println(blank + info);
353
}
354
355
public int getLastingTime(int sNode, int eNode)
356
{
357
int lastingTime = 0;
358
ProcessInfo pInfo;
359
searchProcess(sNode, eNode, 0);
360
int num = resultStack.size();
361
for (int i = num - 1; i >= 0; i--)
362
{
363
pInfo = (ProcessInfo) resultStack.get(i);
364
lastingTime += pInfo.lastingTime;
365
}
366
return lastingTime;
367
}
368
369
public void showPath()
370
{
371
ProcessInfo pInfo;
372
int num = resultStack.size();
373
if (num==0)
374
{
375
showDebugInfo("========没有符合要求的路径========",0);
376
}
377
else
378
{
379
for (int i = 0; i < num; i++)
380
{
381
pInfo = (ProcessInfo) resultStack.pop();
382
System.out.print("-->" + pInfo.endNode);
383
}
384
}
385
}
386
387
public void resetAllSkip()
388
{
389
for (int i = 0; i < numProcess; i++)
390
{
391
process[i].skip = false;
392
}
393
}
394
395
public int getItemEarliestBeginTime(int itemIndex)
396
{
397
maxLastingTime = 0;
398
backTrackStack.removeAllElements();
399
resultStack.removeAllElements();
400
return getLastingTime(1, itemIndex);
401
}
402
403
public int getProcessEarliestEndTime(int sNode, int eNode)
404
{
405
for (int i = 0; i < numProcess; i++)
406
{
407
if ((process[i].startNode == sNode)
408
&& (process[i].endNode == eNode))
409
{
410
return (getItemEarliestBeginTime(sNode) + process[i].lastingTime);
411
}
412
}
413
return 0;
414
}
415
416
public int getProcessEarliestBeginTime(int sNode, int eNode)
417
{
418
return (getItemEarliestBeginTime(sNode));
419
}
420
421
public int getItemLatestEndTime(int itemIndex)
422
{
423
int maxTime = 0;
424
int t = 0;
425
int pos = -1;
426
boolean hasNextNode = false;
427
backTrackStack.removeAllElements();
428
resultStack.removeAllElements();
429
for (int i = 0; i < numProcess; i++)
430
{
431
if (process[i].startNode == itemIndex)
432
{
433
if (process[i].sNodeIsBranchBeginNode)
434
{
435
return (getItemEarliestBeginTime(itemIndex));
436
}
437
hasNextNode = true;
438
t = getItemEarliestBeginTime(process[i].endNode);
439
if (t > maxTime)
440
{
441
pos = i;
442
maxTime = t;
443
}
444
}
445
}
446
if (!hasNextNode)
447
{
448
return (getItemEarliestBeginTime(itemIndex));
449
}
450
else
451
{
452
return (t - process[pos].lastingTime);
453
}
454
}
455
456
public int getProcessLatestEndTime(int sNode, int eNode)
457
{
458
return (getItemLatestEndTime(eNode));
459
}
460
461
public int getProcessLatestBeginTime(int sNode, int eNode)
462
{
463
for (int i = 0; i < numProcess; i++)
464
{
465
if ((process[i].startNode == sNode)
466
&& (process[i].endNode == eNode))
467
{
468
return (getProcessLatestEndTime(sNode, eNode) - process[i].lastingTime);
469
}
470
}
471
return 0;
472
}
473
474
public int getProcessIntervalTime(int sNode, int eNode)
475
{
476
return (getProcessLatestEndTime(sNode, eNode) - getProcessEarliestEndTime(
477
sNode, eNode));
478
}
479
480
public int getKeyPath(int sNode, int eNode)
481
{
482
if ((getProcessIntervalTime(sNode, eNode) == 0) && (sNode != eNode))
483
{
484
return eNode;
485
}
486
else
487
{
488
return 0;
489
}
490
}
491
}
最后是调试信息(找2到8):
2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

449

450

451

452

453

454

455

456

457

458

459

460

461

462

463

464

465

466

467

468

469

470

471

472

473

474

475

476

477

478

479

480

481

482

483

484

485

486

487

488

489

490

491

















































































1
分支路径栈加入:2-->7
2
分支路径栈加入:3-->7
3
分支路径栈加入:5-->7
4
分支路径栈加入:6-->7
5
分支路径栈弹出:6-->7
6
回溯栈加入:3-->7,说明找过3-->7
7
查找:3-->6
8
分支路径栈加入:4-->6
9
分支路径栈弹出:4-->6
10
回溯栈加入:3-->6,说明找过3-->6
11
查找:3-->4
12
分支路径栈加入:2-->4
13
分支路径栈弹出:2-->4
14
回溯栈加入:3-->4,说明找过3-->4
15
查找:3-->2
16
分支路径栈加入:1-->2
17
分支路径栈弹出:1-->2
18
路径错误,开始回溯,回溯栈弹出:3-->4
19
路径错误,开始回溯,回溯栈弹出:3-->6
20
路径错误,开始回溯,回溯栈弹出:3-->7
21
分支已被找遍
22
分支已被找遍
23
分支已被找遍
24
分支路径栈弹出:5-->7
25
回溯栈加入:3-->7,说明找过3-->7
26
查找:3-->5
27
分支路径栈加入:2-->5
28
分支路径栈加入:4-->5
29
分支路径栈弹出:4-->5
30
回溯栈加入:3-->5,说明找过3-->5
31
查找:3-->4
32
前面已走过这条路径且被证明走不通,或尾节点没有前驱节点
33
路径不通,回溯栈弹出:3-->5
34
分支路径栈弹出:2-->5
35
回溯栈加入:3-->5,说明找过3-->5
36
查找:3-->2
37
前面已走过这条路径且被证明走不通,或尾节点没有前驱节点
38
路径不通,回溯栈弹出:3-->5
39
========需要调整回溯栈========
40
========开始调整回溯栈========
41
回溯栈弹出:3-->7
42
========回溯栈调整结束========
43
分支已被找遍
44
分支路径栈弹出:3-->7
45
--------到达起点:3-->7--------
46
回溯栈内容进入临时结果栈:3-->7
47
========找到更优解!========
48
--------回退到节点:7--------
49
找到目标,回溯栈回退到:3-->7
50
分支路径栈弹出:2-->7
51
回溯栈加入:3-->7,说明找过3-->7
52
查找:3-->2
53
分支路径栈加入:1-->2
54
分支路径栈弹出:1-->2
55
路径错误,开始回溯,回溯栈弹出:3-->7
56
分支已被找遍
57
分支已被找遍
58
-->7
先写到这里,以后再来修改。

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58
