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

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

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

    E81086713E446D36F62B2AA2A3502B5EB155

    Java雜家

    雜七雜八。。。一家之言

    BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
      40 Posts :: 1 Stories :: 174 Comments :: 0 Trackbacks
    四 拓?fù)渑判?br /> 考慮一個(gè)任務(wù)安排的例子,比如有很多任務(wù)T1,T2,....
    這些任務(wù)又是相互關(guān)聯(lián)的,比如Tj完成前必須要求Ti已完成,這樣T1,T2....序列關(guān)于這樣的先決條件構(gòu)成一個(gè)圖,其中如果Ti必須要先于Tj完成,那么<Ti,Tj>就是該圖中的一條路徑,路徑長(zhǎng)度為1的就是一條邊。
    拓?fù)渑判蚓褪前堰@些任務(wù)按照完成的先后順序排列出來(lái)。顯然,這樣的順序可能不是唯一的,比如Tk,Tl如果沒有在一條路徑上,那么他們之間的順序是任意的。
    拓?fù)渑判蛑辽儆袃煞N解法

    1)首先找出入度(連接到改點(diǎn)的邊的數(shù)目)為零的頂點(diǎn)放入隊(duì)列,然后依次遍歷這些頂點(diǎn),每次訪問到其中的一個(gè)頂點(diǎn)時(shí),把該定點(diǎn)關(guān)聯(lián)到的其它頂點(diǎn)的邊移去,也就是使得關(guān)聯(lián)頂點(diǎn)的入度減1.如果減1后該定點(diǎn)入度也變?yōu)?了,那么把該定點(diǎn)加入隊(duì)列下次從他開始處理,直到?jīng)]有入度為0的定點(diǎn)了。
    這里要注意,如果給定的圖有回路那么,可能不會(huì)處理完所有頂點(diǎn)就退出了。

    實(shí)現(xiàn)如下:

    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");
            }
            
        }
    這里一開始計(jì)算了各個(gè)頂點(diǎn)的入度,計(jì)算的時(shí)候,每條邊需要訪問一次。
    如果是相鄰矩陣的存儲(chǔ)方式,計(jì)算入度只需要計(jì)算每列的非零個(gè)數(shù)。
    一般也可以靜態(tài)的給出。

    2)借助于圖的深度優(yōu)先周游,每次在回退到改頂點(diǎn)的時(shí)候把該頂點(diǎn)送入結(jié)果數(shù)組。
    這樣得到的數(shù)組恰好就是拓?fù)渑判虻哪嫘?,因?yàn)樽畹讓拥墓?jié)點(diǎn)是最先回退到的。
    實(shí)現(xiàn):
    /**
         * 
         * 
    @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();
        }

    五 最短路徑問題

    最短路徑問題分兩類,一類是單源最短路徑問題,就是從指定頂點(diǎn)出發(fā)到其他各點(diǎn)的最短距離,還有一類是
    每?jī)蓚€(gè)頂點(diǎn)之間的最短距離,當(dāng)然第二類也可以通過對(duì)每個(gè)頂點(diǎn)做一次單源最短路徑求解,但是還有一種更優(yōu)雅的方法(Floyd算法),這種方法一般使用相鄰矩陣的實(shí)現(xiàn)方式,對(duì)每個(gè)頂點(diǎn)看它是不是能作為其它沒兩對(duì)頂點(diǎn)間的直接中間節(jié)點(diǎn),如果能,那么再看是不是通過它的兩兩頂點(diǎn)的距離是不是減小了,若果是就更新這兩對(duì)頂點(diǎn)間的距離,這樣通過每次“貪婪的”找出局部最優(yōu)解來(lái)得到全局最優(yōu)解,可以算是一個(gè)動(dòng)態(tài)規(guī)劃的解法。
    首先我們需要一個(gè)輔助類來(lái)保存距離,以及回溯路徑的類:
    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實(shí)現(xiàn):
    @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算法。
    它把頂點(diǎn)分為兩個(gè)集合一個(gè)是已求出最短距離的頂點(diǎn)集合V1,另一類是暫未求出的頂點(diǎn)集合V2,而可以證明下一個(gè)將求出來(lái)(V2中到出發(fā)點(diǎn)最短距離值最?。┑捻旤c(diǎn)的最短路徑上的頂點(diǎn)除了該頂點(diǎn)不在V1中外其余頂點(diǎn)都在V1中。

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

    這里的實(shí)現(xiàn)我們使用最小值堆來(lái)每次從V2中挑出最短距離。

    先給出最小值堆的實(shí)現(xiàn):
    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;
                
                        
            }
        }
    下面是基于最小值堆的最短路勁算法以及一個(gè)測(cè)試方法:


        
    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) 評(píng)論(1)  編輯  收藏 所屬分類: Memorandum

    Feedback

    # re: 圖及其算法復(fù)習(xí)(Java實(shí)現(xiàn)) 二:拓?fù)渑判?,最短路徑問題[未登錄] 2008-05-09 19:08 小米
    沒有圖解,不生動(dòng)形象,不容易被新手和小蝦理解,可以在加一些圖解!  回復(fù)  更多評(píng)論
      

    主站蜘蛛池模板: 亚洲an日韩专区在线| 亚洲日韩国产精品无码av| 亚洲AV无码片一区二区三区| 最近2019中文字幕免费大全5| 亚洲精品无码乱码成人| 成人免费一区二区三区| 亚洲午夜日韩高清一区| 99精品免费视频| 亚洲深深色噜噜狠狠爱网站| 又硬又粗又长又爽免费看 | 一个人看的www免费在线视频| 国产免费久久精品| 边摸边吃奶边做爽免费视频网站| 免费欧洲毛片A级视频无风险| 国产精品亚洲专区在线播放| 免费人成无码大片在线观看| 深夜a级毛片免费无码| 亚洲视频人成在线播放| 黄色网站软件app在线观看免费| 亚洲AV无码一区二区乱孑伦AS | 成人免费福利视频| 亚洲人成77777在线播放网站不卡| 毛色毛片免费观看| 黄色一级毛片免费| 国产亚洲人成网站在线观看不卡 | 一个人看的www免费在线视频| 亚洲AV永久无码区成人网站| 2022久久国产精品免费热麻豆| 精品日韩99亚洲的在线发布| 免费高清在线影片一区| eeuss影院免费92242部| 亚洲视频一区在线播放| 暖暖免费高清日本中文| h视频在线免费观看| 亚洲视频在线观看网址| 免费看美女被靠到爽的视频| 亚洲阿v天堂在线2017免费 | 国产精品亚洲片在线观看不卡 | 亚洲人成网站色在线观看| 亚洲电影日韩精品| 午夜理伦剧场免费|