<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
    六。 最小支撐樹MST
    給定一個簡單有向圖,要求權值最小的生成樹,即求最小支撐樹問題。
    所謂生成樹,就是說樹的頂點集合等于給定圖的頂點集合,且邊集合包含于圖的邊集合。
    也就說找出構成樹的,經過所有頂點的,且權值最小的邊集。
    樹的定義是要求無回路的,然后是要求連通的。

    有兩個比較經典的算法是:
    1)Prim算法: 該算法的思想跟Dijstra算法非常相似,Dijstra算法中每次求出下一個頂點時依據的是離初始頂點最近的,而Prim算法則找離V1整個集合最近的,也就是從V1中某個節點出發到該頂點的邊的權值最小。
    其原理也是每次找局部最優,最后構成全局最優。
    實現如下

    @Override
        
    public Edge[] prim() {
            MinHeap
    <Edge> heap=new MinHeap<Edge>(Edge.class,numEdges);
            Edge[] edges
    =new Edge[numVertexes-1];
            
    //we start from 0
            int num=0;//record already how many edges;
            int startV=0;
            Arrays.fill(visitTags, 
    false);
            Edge e;
            
    for(e=firstEdge(startV);isEdge(e);e=nextEdge(e))
            {
                heap.insert(e);
            }
            visitTags[startV]
    =true;
            
            
    while(num<numVertexes-1&&!heap.isEmpty())//tree's edge number was n-1
            {
                
                e
    =heap.removeMin();
            
                startV
    =toVertex(e);
                
    if(visitTags[startV])
                {
                    
    continue;
                }
                visitTags[startV]
    =true;
                edges[num
    ++]=e;
                
    for(e=firstEdge(startV);isEdge(e);e=nextEdge(e))
                {
                    
    if(!visitTags[toVertex(e)])//can't add already visit vertex, this may cause cycle
                    heap.insert(e);
                }
                
                    
                
            }
            
    if(num<numVertexes-1)
            {
                
    throw new IllegalArgumentException("not connected graph");
            }
            
    return edges;
        }

    /**
         * 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 testPrimMST() {
        

            
            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"});
            Edge[] edges
    =g.prim();
            
    int total=0;
            
    for(int i=0;i<edges.length;i++)
            {
                System.out.println(edges[i].toString(g));
                total
    +=edges[i].getWeight();
            }
            System.out.println(
    "MST total cost:"+total);
    }

    2)Kruskal算法:
    該算法開始把,每個節點看成一個獨立的兩兩不同的等價類,每次去權值最小的邊,如果關聯這條邊的兩個頂點在同一個等價類里那么這條邊不能放入MST(最小生成樹)中,否則放入MST中,并把這兩個等價類合并成一個等價類。
    繼續從剩余邊集里選最小的邊,直到最后剩余一個等價類了。
    該算法涉及等價類的合并/查找,一般用父指針樹來實現。下面先給出父指針樹實現的并查算法。
    帶路徑壓縮的算法,其查找時間代價可以看做是常數的。

    package algorithms;

    /**
     * 
    @author yovn
     *
     
    */
    public class ParentTree {
        
        
        
    private static class PTreeNode
        {
            
    int parentIndex=-1;
            
    int numChildren=0;//only make sense in root

            
    void setParent(int i) {
                
                parentIndex
    =i;
                
            }
        }
        PTreeNode[] nodes;
        
    int numPartions;
        
    public ParentTree(int numNodes)
        {
            nodes
    =new PTreeNode[numNodes];
            numPartions
    =numNodes;
            
    for(int i=0;i<numNodes;i++)
            {
                nodes[i]
    =new PTreeNode();
                nodes[i].parentIndex
    =-1;//means root
                
            }
            
        }
        
        
    /**
         * use path compress
         * 
    @param i
         * 
    @return
         
    */
        
    public int find(int i)
        {
            
    if(nodes[i].parentIndex==-1)
            {
                
    return i;
            }
            
    else
            {
                nodes[i].setParent(find(nodes[i].parentIndex));
    //compress the path
                return nodes[i].parentIndex;
            }
        }
        
        
    public int numPartions()
        {
            
    return numPartions;
        }
        
    public boolean union(int i,int j)
        {
            
    int pi=find(i);
            
    int pj=find(j);
            
    if(pi!=pj)
            {
                
    if(nodes[pi].numChildren>nodes[pj].numChildren)
                {
                    nodes[pj].setParent(pi);
                    nodes[pj].numChildren
    +=nodes[pi].numChildren;
                    nodes[pi].numChildren
    =0;
                    
                }
                
    else
                {
                    nodes[pi].setParent(pj);
                    nodes[pi].numChildren
    +=nodes[pj].numChildren;
                    nodes[pj].numChildren
    =0;
                }
                numPartions
    --;
                
    return true;
            }
            
    return false;
        }
        
    }


    從邊集里權最小的邊,我們又可以借助最小值堆來完成。有了父指針樹以及最小值堆,現實Kruskal算法就很簡單了:

    @Override
        
    public Edge[] kruskal() {
            Edge[] edges
    =new Edge[numVertexes-1];
            ParentTree ptree
    =new ParentTree(numVertexes);
            MinHeap
    <Edge> heap=new MinHeap<Edge>(Edge.class,numEdges);
            
    for(int i=0;i<numVertexes;i++)
            {
                
    for(Edge e=firstEdge(i);isEdge(e);e=nextEdge(e))
                {
                    heap.insert(e);
                }
            }
            
    int index=0;
            
    while(ptree.numPartions()>1)
            {
                Edge e
    =heap.removeMin();
                
    if(ptree.union(fromVertex(e),toVertex(e)))
                {
                    edges[index
    ++]=e;
                }
            }
            
    if(index<numVertexes-1)
            {
                
    throw new IllegalArgumentException("Not a connected graph");
            }
            
    return edges;
            
        }
    OK,到此,圖論的大概的算法算是復習完了。

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

    Feedback

    # re: 圖及其算法復習(Java實現) 三:最小支撐樹(Prim,Kruskal算法) 2010-10-27 23:16 斯蒂芬
    toString沒有定義。
    不好使  回復  更多評論
      

    主站蜘蛛池模板: 亚洲AV永久青草无码精品| 亚洲精品成人久久久| 两个人看的www免费视频| 亚洲中文字幕无码久久2020| 亚洲乱码日产一区三区| 免费一级一片一毛片| 性盈盈影院免费视频观看在线一区| 外国成人网在线观看免费视频| 一级毛片完整版免费播放一区| 亚洲人成毛片线播放| 特级av毛片免费观看| 97无码免费人妻超级碰碰夜夜| 精品国产一区二区三区免费| 亚洲免费在线观看| 欧洲亚洲综合一区二区三区| 亚洲字幕AV一区二区三区四区| 亚洲高清免费在线观看| 亚洲AV午夜成人片| 国精无码欧精品亚洲一区| 亚洲精品乱码久久久久久不卡| 国产一卡二卡≡卡四卡免费乱码| 最近最新的免费中文字幕| 成年在线观看网站免费| 我的小后妈韩剧在线看免费高清版| 久久久久国产精品免费看| 青青青国产手机频在线免费观看| 久久精品免费大片国产大片 | 免费人妻精品一区二区三区| 国产色婷婷精品免费视频| 和日本免费不卡在线v| 免费国产黄网站在线观看可以下载| 一区二区三区在线观看免费| 免费人成视频在线播放| 色天使色婷婷在线影院亚洲| 精品韩国亚洲av无码不卡区| 国产亚洲综合精品一区二区三区| 亚洲av永久中文无码精品综合| 日本系列1页亚洲系列| 国产精品亚洲专一区二区三区| 美女视频免费看一区二区| 日韩免费高清一级毛片|