<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    E81086713E446D36F62B2AA2A3502B5EB155

    Java雜家

    雜七雜八。。。一家之言

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      40 Posts :: 1 Stories :: 174 Comments :: 0 Trackbacks
    四 拓撲排序
    考慮一個任務安排的例子,比如有很多任務T1,T2,....
    這些任務又是相互關聯的,比如Tj完成前必須要求Ti已完成,這樣T1,T2....序列關于這樣的先決條件構成一個圖,其中如果Ti必須要先于Tj完成,那么<Ti,Tj>就是該圖中的一條路徑,路徑長度為1的就是一條邊。
    拓撲排序就是把這些任務按照完成的先后順序排列出來。顯然,這樣的順序可能不是唯一的,比如Tk,Tl如果沒有在一條路徑上,那么他們之間的順序是任意的。
    拓撲排序至少有兩種解法

    1)首先找出入度(連接到改點的邊的數目)為零的頂點放入隊列,然后依次遍歷這些頂點,每次訪問到其中的一個頂點時,把該定點關聯到的其它頂點的邊移去,也就是使得關聯頂點的入度減1.如果減1后該定點入度也變為0了,那么把該定點加入隊列下次從他開始處理,直到沒有入度為0的定點了。
    這里要注意,如果給定的圖有回路那么,可能不會處理完所有頂點就退出了。

    實現如下:

    private final void calculateInDegrees(int[] inDegrees)
        {
            Arrays.fill(inDegrees, 
    0);
            
    for(int v=0;v<numVertexes;v++)
            {
                
    for(Edge e=firstEdge(v);isEdge(e);e=nextEdge(e))
                {
                    inDegrees[toVertex(e)]
    ++;
                }
            }
        }
        
    /**
         * 
         * 
    @param sortedVertexes
         
    */
        
    public void topologySort(int[] sortedVertexes)
        {
            
    //first calculate the inDegrees
            int[] inDegrees=new int[numVertexes];
            calculateInDegrees(inDegrees);
            
            Arrays.fill(visitTags, 
    false);
            
            _IntQueue queue
    =new _IntQueue();
            
            
    for(int v=0;v<numVertexes-1;v++)
            {
                
    if(inDegrees[v]==0)queue.add(v);
            }
            
            
            
    int index=0;
            
    while(!queue.isEmpty())
            {
                
                
    int from=queue.remove();
                System.out.println(
    "visit:"+from);
                sortedVertexes[index
    ++]=from;
                
    for(Edge e=firstEdge(from);isEdge(e);e=nextEdge(e))
                {
                    
                    
    if(--inDegrees[toVertex(e)]==0)
                    {
                        queue.add(toVertex(e));
                    }
                }
            }
            
    if(index<numVertexes)
            {
                
    throw new IllegalArgumentException("There is a loop");
            }
            
        }
    這里一開始計算了各個頂點的入度,計算的時候,每條邊需要訪問一次。
    如果是相鄰矩陣的存儲方式,計算入度只需要計算每列的非零個數。
    一般也可以靜態的給出。

    2)借助于圖的深度優先周游,每次在回退到改頂點的時候把該頂點送入結果數組。
    這樣得到的數組恰好就是拓撲排序的逆序,因為最底層的節點是最先回退到的。
    實現:
    /**
         * 
         * 
    @param sortedVertexes
         
    */
        
    public void topologySort_byDFS(int[] sortedVertexes)
        {
            Arrays.fill(visitTags, 
    false);
            
    int num=0;
            
    for(int i=0;i<numVertexes;i++)
            {
                
    if(!visitTags[i])num=do_topsort(i,sortedVertexes,num);
            }
            
        }



        
    private final int do_topsort(int v, int[] sortedVertexes, int num) {
            visitTags[v]
    =true;
            
            
    for(Edge e=firstEdge(v);isEdge(e);e=nextEdge(e))
            {
                
    if(!visitTags[toVertex(e)])num=do_topsort(toVertex(e),sortedVertexes,num);
            }
            num
    ++;
            sortedVertexes[numVertexes
    -num]=v;
        
            
            
    return num;
        }



        
    /**
         * Given graph :
         * 
         * C1 → C3 ← C2
         * ↓    ↓    ↓
         * C8    C4   C5
         * ↓    ↓    ↓
         * C9 → C7 ← C6
         
    */
        
    public static void testTopologySort()
        {
            DefaultGraph g
    =new DefaultGraph(9);
            g.setEdge(
    010);
            g.setEdge(
    210);
            g.setEdge(
    030);
            g.setEdge(
    140);
            g.setEdge(
    250);
            g.setEdge(
    360);
            g.setEdge(
    470);
            g.setEdge(
    580);
            g.setEdge(
    670);
            g.setEdge(
    870);
            
            
            g.assignLabels(
    new String[]{"C1","C3","C2","C8","C4","C5","C9","C7","C6"});
            
            
    int[] sorted=new int[g.vertexesNum()];
    //        g.topologySort(sorted);
            g.topologySort_byDFS(sorted);
            System.out.println(
    "Topology Sort Result==============:");
            
    for(int i=0;i<sorted.length;i++)System.out.print(g.getVertexLabel(sorted[i])+",");
            System.out.println();
        }

    五 最短路徑問題

    最短路徑問題分兩類,一類是單源最短路徑問題,就是從指定頂點出發到其他各點的最短距離,還有一類是
    每兩個頂點之間的最短距離,當然第二類也可以通過對每個頂點做一次單源最短路徑求解,但是還有一種更優雅的方法(Floyd算法),這種方法一般使用相鄰矩陣的實現方式,對每個頂點看它是不是能作為其它沒兩對頂點間的直接中間節點,如果能,那么再看是不是通過它的兩兩頂點的距離是不是減小了,若果是就更新這兩對頂點間的距離,這樣通過每次“貪婪的”找出局部最優解來得到全局最優解,可以算是一個動態規劃的解法。
    首先我們需要一個輔助類來保存距離,以及回溯路徑的類:
    public static class Dist implements Comparable<Dist>
        {
            
    public int preV;
            
    public int curV;
            
    public int distance;
            
            
    public Dist(int v)
            {
                
    this.curV=v;
                
    this.preV=-1;
                
    this.distance=Integer.MAX_VALUE;
            }
            
        
            @Override
            
    public int compareTo(Dist other) {
                
    return distance-other.distance;
            }
            
        }
    下面給出第二類最短路徑的解法(Floyd算法)Java實現:
    @Override
        
    public void floyd(Dist[][] dists) {
            
    for(int i=0;i<numVertexes;i++)
            {
                dists[i]
    =new Dist[numVertexes];
                
    for(int j=0;j<numVertexes;j++)
                {
                    dists[i][j]
    =new Dist(-1);//
                    dists[i][j].preV=-1;
                    
    if(i==j)
                        dists[i][j].distance
    =0;
                    
                    
    else
                       dists[i][j].distance
    =Integer.MAX_VALUE;
                    
                }
            }
            
            
    for(int v=0;v<numVertexes;v++)
            {
                
    for(Edge e=firstEdge(v);isEdge(e);e=nextEdge(e))
                {
                    
    int to=toVertex(e);
                    dists[v][to].distance
    =e.getWeight();
                    dists[v][to].preV
    =v;
                }
            }
            
            
    for(int v=0;v<numVertexes;v++)
            {
                
    for(int i=0;i<numVertexes;i++)
                    
    for(int j=0;j<numVertexes;j++)
                    {
                        
                        
    if((dists[i][v].distance!=Integer.MAX_VALUE)&&(dists[v][j].distance!=Integer.MAX_VALUE)&&(dists[i][v].distance+dists[v][j].distance<dists[i][j].distance))
                        {
                            dists[i][j].distance
    =dists[i][v].distance+dists[v][j].distance;
                            dists[i][j].preV
    =v;
                        }
                    }
            }
            
        }

    /**
         * A Graph example
         * we mark the vertexes  with 0,1,2,.14 from left to right , up to down
         * S-8-B-4-A-2-C-7-D
         * |    |     |     |     |
         * 3    3     1     2     5
         * |    |     |     |     |
         * E-2-F-6-G-7-H-2-I
         * |    |     |     |     |
         * 6    1     1     1     2
         * |    |     |     |     |
         * J-5-K-1-L-3-M-3-T
         * 
         
    */
        
    public static void testFloyd() {
            DefaultGraph g
    =new DefaultGraph(15);
            g.setEdge(
    018);
            g.setEdge(
    108);//its a undirected graph
            g.setEdge(124);
            g.setEdge(
    214);
            g.setEdge(
    232);
            g.setEdge(
    322);
            g.setEdge(
    347);
            g.setEdge(
    437);
            
            g.setEdge(
    053);
            g.setEdge(
    503);
            g.setEdge(
    163);
            g.setEdge(
    613);
            g.setEdge(
    271);
            g.setEdge(
    721);
            g.setEdge(
    382);
            g.setEdge(
    832);
            g.setEdge(
    495);
            g.setEdge(
    945);
            
            
            g.setEdge(
    562);
            g.setEdge(
    652);
            g.setEdge(
    676);
            g.setEdge(
    766);
            g.setEdge(
    787);
            g.setEdge(
    877);
            g.setEdge(
    892);
            g.setEdge(
    982);
            
            
            g.setEdge(
    1056);
            g.setEdge(
    5106);
            g.setEdge(
    1161);
            g.setEdge(
    6111);
            g.setEdge(
    1271);
            g.setEdge(
    7121);
            g.setEdge(
    1381);
            g.setEdge(
    8131);
            g.setEdge(
    1492);
            g.setEdge(
    9142);
            
            g.setEdge(
    10115);
            g.setEdge(
    11105);
            g.setEdge(
    11121);
            g.setEdge(
    12111);
            g.setEdge(
    12133);
            g.setEdge(
    13123);
            g.setEdge(
    13143);
            g.setEdge(
    14133);
            
            g.assignLabels(
    new String[]{"S","B","A","C","D","E","F","G","H","I","J","K","L","M","T"});
            
            Dist[][] dists
    =new Dist[15][15];
            g.floyd(dists);
            
            System.out.println(
    "Shortes path from S-T ("+dists[0][14].distance+")is:");
            Stack
    <String> stack=new Stack<String>();
            
    int i=0;
            
    int j=14;
            
    while(j!=i)
            {
                
                stack.push(g.getVertexLabel(j));
                j
    =dists[i][j].preV;
                
            }
            stack.push(g.getVertexLabel(i));
            
    while(!stack.isEmpty())
            {
                System.out.print(stack.pop());
                
    if(!stack.isEmpty())System.out.print("->");
            }
            System.out.println();
            

        }



    單源最短路徑問題的解法有Dijstra提出,所以也叫Dijstra算法。
    它把頂點分為兩個集合一個是已求出最短距離的頂點集合V1,另一類是暫未求出的頂點集合V2,而可以證明下一個將求出來(V2中到出發點最短距離值最小)的頂點的最短路徑上的頂點除了該頂點不在V1中外其余頂點都在V1中。

    如此,先把出發點放入V1中(出發點的最短距離當然也就是0),然后每次選擇V2中到出發點距離最短的點加入V1,并把標記改點的最短距離.直到V2中沒有頂點為止,詳細的形式化證明見:
    Dijstra算法證明

    這里的實現我們使用最小值堆來每次從V2中挑出最短距離。

    先給出最小值堆的實現:
    package algorithms;

    import java.lang.reflect.Array;

    public class MinHeap<extends Comparable<E>>
    {
            
            
    private E[] values;
            
    int len;
            
            
    public MinHeap(Class<E> clazz,int num)
            {
                
                
    this.values=(E[])Array.newInstance(clazz,num);
                len
    =0;
            }
                
            
            
    public final E removeMin()
            {
                E ret
    =values[0];
                values[
    0]=values[--len];
                shift_down(
    0);
                
    return ret;
            }
        
            
            
    //insert to tail
            public final void insert(E val)
            {
                values[len
    ++]=val;
                shift_up(len
    -1);
                
            }
            
            
    public final void rebuild()
            {
                
    int pos=(len-1)/2;
                
    for(int i=pos;i>=0;i--)
                {
                    shift_down(i);
                }
            }
            
            
    public final boolean isEmpty()
            {
                
    return len==0;
            }
            
            
    /**
             * When insert element we  need shiftUp
             * 
    @param array
             * 
    @param pos
             
    */
            
    private final void shift_up(int pos)
            {
        
                E tmp
    =values[pos];
                
    int index=(pos-1)/2;
                
    while(index>=0)
                {
                    
    if(tmp.compareTo(values[index])<0)
                    {
                        values[pos]
    =values[index];
                        pos
    =index;
                        
    if(pos==0)break;
                        index
    =(pos-1)/2;
                    }
                    
    else break;
                }
                values[pos]
    =tmp;
            }
            
    private final void shift_down(int pos)
            {
                
                E tmp
    =values[pos];
                
    int index=pos*2+1;//use left child
                while(index<len)//until no child
                {
                    
    if(index+1<len&&values[index+1].compareTo(values[index])<0)//right child is smaller
                    {
                        index
    +=1;//switch to right child
                    }
                    
    if(tmp.compareTo(values[index])>0)
                    {
                        values[pos]
    =values[index];
                        pos
    =index;
                        index
    =pos*2+1;
                        
                    }
                    
    else
                    {
                        
    break;
                    }
                    
                }
                values[pos]
    =tmp;
                
                        
            }
        }
    下面是基于最小值堆的最短路勁算法以及一個測試方法:


        
    public void dijstra(int fromV,Dist[] dists)
        {
            MinHeap
    <Dist> heap=new MinHeap<Dist>(Dist.class,numVertexes*2);
            
            
    for(int v=0;v<numVertexes;v++)
            {
                dists[v]
    =new Dist(v);
            }
            
            Arrays.fill(visitTags, 
    false);
            dists[fromV].distance
    =0;
            dists[fromV].preV
    =-1;
            heap.insert(dists[fromV]);
            
    int num=0;
            
            
    while(num<numVertexes)
            {
                Dist dist
    =heap.removeMin();
                
    if(visitTags[dist.curV])
                {
                    
    continue;
                }
                visitTags[dist.curV]
    =true;
                num
    ++;
               
    for(Edge e=firstEdge(dist.curV);isEdge(e);e=nextEdge(e))
                {
                    
    if(!visitTags[toVertex(e)]&&e.getWeight()+dist.distance<dists[toVertex(e)].distance)
                    {
                        
                        dists[toVertex(e)].distance
    =e.getWeight()+dist.distance;
                        dists[toVertex(e)].preV
    =dist.curV;
                        heap.insert(dists[toVertex(e)]);
                        
                    }
                }
                
            }
            
            
        }


        
        
    /**
         * A Graph example
         * we mark the vertexes  with 0,1,2,.14 from left to right , up to down
         * S-8-B-4-A-2-C-7-D
         * |   |   |   |   |
         * 3   3   1   2   5
         * |   |   |   |   |
         * E-2-F-6-G-7-H-2-I
         * |   |   |   |   |
         * 6   1   1   1   2
         * |   |   |   |   |
         * J-5-K-1-L-3-M-3-T
         * 
         
    */
        
    public static void testDijstra()
        {
            DefaultGraph g
    =new DefaultGraph(15);
            g.setEdge(
    018);
            g.setEdge(
    108);//its a undirected graph
            g.setEdge(124);
            g.setEdge(
    214);
            g.setEdge(
    232);
            g.setEdge(
    322);
            g.setEdge(
    347);
            g.setEdge(
    437);
            
            g.setEdge(
    053);
            g.setEdge(
    503);
            g.setEdge(
    163);
            g.setEdge(
    613);
            g.setEdge(
    271);
            g.setEdge(
    721);
            g.setEdge(
    382);
            g.setEdge(
    832);
            g.setEdge(
    495);
            g.setEdge(
    945);
            
            
            g.setEdge(
    562);
            g.setEdge(
    652);
            g.setEdge(
    676);
            g.setEdge(
    766);
            g.setEdge(
    787);
            g.setEdge(
    877);
            g.setEdge(
    892);
            g.setEdge(
    982);
            
            
            g.setEdge(
    1056);
            g.setEdge(
    5106);
            g.setEdge(
    1161);
            g.setEdge(
    6111);
            g.setEdge(
    1271);
            g.setEdge(
    7121);
            g.setEdge(
    1381);
            g.setEdge(
    8131);
            g.setEdge(
    1492);
            g.setEdge(
    9142);
            
            g.setEdge(
    10115);
            g.setEdge(
    11105);
            g.setEdge(
    11121);
            g.setEdge(
    12111);
            g.setEdge(
    12133);
            g.setEdge(
    13123);
            g.setEdge(
    13143);
            g.setEdge(
    14133);
            
            g.assignLabels(
    new String[]{"S","B","A","C","D","E","F","G","H","I","J","K","L","M","T"});
            
            Dist[] dists
    =new Dist[15];
            g.dijstra(
    0, dists);
            
            System.out.println(
    "Shortes path from S-T ("+dists[14].distance+")is:");
            Stack
    <String> stack=new Stack<String>();
            
    for(int v=dists[14].curV;v!=-1;v=dists[v].preV)
            {
                stack.push(g.getVertexLabel(v));
            
            }
            
    while(!stack.isEmpty())
            {
                System.out.print(stack.pop());
                
    if(!stack.isEmpty())System.out.print("->");
            }
            System.out.println();
            
            
        }





    posted on 2007-12-14 21:00 DoubleH 閱讀(6416) 評論(1)  編輯  收藏 所屬分類: Memorandum

    Feedback

    # re: 圖及其算法復習(Java實現) 二:拓撲排序,最短路徑問題[未登錄] 2008-05-09 19:08 小米
    沒有圖解,不生動形象,不容易被新手和小蝦理解,可以在加一些圖解!  回復  更多評論
      

    主站蜘蛛池模板: 亚洲最大成人网色| 国产亚洲精久久久久久无码77777| 亚洲伊人久久大香线蕉苏妲己| 久久99热精品免费观看动漫| 日本红怡院亚洲红怡院最新| 久久国产乱子伦精品免费不卡 | 成人性生交视频免费观看| 亚洲 欧洲 自拍 另类 校园| 免费无码AV片在线观看软件| 亚洲精品成a人在线观看☆| 国产精品冒白浆免费视频| 猫咪免费人成在线网站| 自拍偷自拍亚洲精品情侣| 久久久久国产精品免费免费不卡| 亚洲影院在线观看| 成熟女人特级毛片www免费| 国产成人人综合亚洲欧美丁香花| 亚洲精品成人网久久久久久| a级男女仿爱免费视频| 亚洲视频在线观看不卡| 蜜桃精品免费久久久久影院| 一级毛片a免费播放王色| 亚洲国产精品无码一线岛国| 亚洲高清免费在线观看| 亚洲国产欧洲综合997久久| 亚洲人妻av伦理| 99久在线国内在线播放免费观看 | 国产成人aaa在线视频免费观看| 日韩一级片免费观看| 亚洲AV无码乱码国产麻豆穿越 | 亚洲精品无码Av人在线观看国产 | 白白国产永久免费视频| free哆拍拍免费永久视频| 337p日本欧洲亚洲大胆精品555588| 免费人成在线视频| 精精国产www视频在线观看免费| 亚洲成AV人综合在线观看| 亚洲精品国精品久久99热| AV无码免费永久在线观看| 五月天婷婷免费视频| 亚洲三级在线视频|