关于工序设计中最优解的一个算法【原创】

  以前做了个什么网络计划的算法,昨天拿来一看,好像还有问题,早上过来,弄了下,加了注释,和调试信息输出的功能,方便理解,我调试了下,没发现什么问题,如果大家发现的话,请告诉我,谢谢。
  由于程序是没人那么聪明的,只有遍历了。
  首先,两点之间加上中间那条线,用个类保存,类说明了这段路程的三个基本属性:起始点、结束点、需要时间,剩下的五个附加属性是遍历的时候要用到的: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 */

 5public 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):
  1import java.util.Stack;
  2
  3/**
  4 * @author zxub Created on 2005-5-22 10:19:51
  5 */

  6public 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(280);
 71        processOpera.showPath();
 72    }

 73
 74    /**
 75     * 初始化所有路径信息,放进数组中
 76     */

 77    public void setup()
 78    {
 79        addProcessInfo(1260);
 80        addProcessInfo(2310);
 81        addProcessInfo(2420);
 82        addProcessInfo(2540);
 83        addProcessInfo(2745);
 84        addProcessInfo(3718);
 85        addProcessInfo(450);
 86        addProcessInfo(4630);
 87        addProcessInfo(5715);
 88        addProcessInfo(6725);
 89        addProcessInfo(7835);
 90        addProcessInfo(880);
 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):
分支路径栈加入:7-->8
分支路径栈加入:
8-->8
分支路径栈弹出:
8-->8
  头尾节点一样,丢弃
!
分支路径栈弹出:
7-->8
  回溯栈加入:
2-->8,说明找过2-->8
  查找:
2-->7
    分支路径栈加入:
2-->7
    分支路径栈加入:
3-->7
    分支路径栈加入:
5-->7
    分支路径栈加入:
6-->7
    分支路径栈弹出:
6-->7
      回溯栈加入:
2-->7,说明找过2-->7
      查找:
2-->6
        分支路径栈加入:
4-->6
        分支路径栈弹出:
4-->6
          回溯栈加入:
2-->6,说明找过2-->6
          查找:
2-->4
            分支路径栈加入:
2-->4
            分支路径栈弹出:
2-->4
            
--------到达起点:2-->4--------
            回溯栈内容进入临时结果栈:
2-->8
            回溯栈内容进入临时结果栈:
2-->7
            回溯栈内容进入临时结果栈:
2-->6
            回溯栈内容进入临时结果栈:
2-->4
            
========找到更优解!========
            
--------回退到节点:7--------
            找到目标,回溯栈回退到:
2-->4
            找到目标,回溯栈回退到:
2-->6
            找到目标,回溯栈回退到:
2-->7
            分支已被找遍
        分支已被找遍
    分支路径栈弹出:
5-->7
      回溯栈加入:
2-->7,说明找过2-->7
      查找:
2-->5
        分支路径栈加入:
2-->5
        分支路径栈加入:
4-->5
        分支路径栈弹出:
4-->5
          回溯栈加入:
2-->5,说明找过2-->5
          查找:
2-->4
            分支路径栈加入:
2-->4
            分支路径栈弹出:
2-->4
            
--------到达起点:2-->4--------
            回溯栈内容进入临时结果栈:
2-->8
            回溯栈内容进入临时结果栈:
2-->7
            回溯栈内容进入临时结果栈:
2-->5
            回溯栈内容进入临时结果栈:
2-->4
            
--------回退到节点:5--------
            找到目标,回溯栈回退到:
2-->4
            找到目标,回溯栈回退到:
2-->5
            分支已被找遍
        分支路径栈弹出:
2-->5
        
--------到达起点:2-->5--------
        回溯栈内容进入临时结果栈:
2-->8
        回溯栈内容进入临时结果栈:
2-->7
        回溯栈内容进入临时结果栈:
2-->5
        
--------回退到节点:7--------
        找到目标,回溯栈回退到:
2-->5
        找到目标,回溯栈回退到:
2-->7
        分支已被找遍
    分支路径栈弹出:
3-->7
      回溯栈加入:
2-->7,说明找过2-->7
      查找:
2-->3
        分支路径栈加入:
2-->3
        分支路径栈弹出:
2-->3
        
--------到达起点:2-->3--------
        回溯栈内容进入临时结果栈:
2-->8
        回溯栈内容进入临时结果栈:
2-->7
        回溯栈内容进入临时结果栈:
2-->3
        
--------回退到节点:7--------
        找到目标,回溯栈回退到:
2-->3
        找到目标,回溯栈回退到:
2-->7
        分支已被找遍
    分支路径栈弹出:
2-->7
    
--------到达起点:2-->7--------
    回溯栈内容进入临时结果栈:
2-->8
    回溯栈内容进入临时结果栈:
2-->7
    分支已被找遍
分支已被找遍
-->4-->6-->7-->8
  下面来个找3到7的:
 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
  先写到这里,以后再来修改。
原文地址:https://www.cnblogs.com/zxub/p/261426.html