亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C > 正文

基于C中一個行壓縮圖的簡單實現代碼

2020-01-26 16:17:56
字體:
來源:轉載
供稿:網友

首先簡單說一下什么是行壓縮圖,其實嚴格意義上應該是行壓縮矩陣。正常情況下,矩陣是用二維數組簡單存儲的,但是如果是稀疏矩陣,也就是零很多的時候,這樣比較浪費空間。所以就有各種節省空間的存儲方式,三元組存儲就是其中一種。

什么是三元組呢?一個三元組就是(row,col,value),這樣把所有不為零的值組成一個向量。這種存儲方式比二維數組節省了不少空間,當然還可以進一步節省,因為三元組里面row或者col重復存儲了,一行或者一列存一次就行了,按這種思路走下去就是行壓縮存儲了。

那具體什么是行壓縮存儲呢?行壓縮存儲的思想就是,把所有不為零的值按行訪問的順序組成一個向量,然后再把每一行值不為0的列的下標存下來,這個兩個向量的大小和稀疏矩陣中不為0的值得個數相同,當然要實現對行壓縮矩陣的訪問,還要把每一行的不為0的列的下標在第二個向量中開始的位置存下來,有人把這個叫做指針。有了這三個向量就可以實現對矩陣實現高效的按行訪問了。行壓縮存儲比三元組優秀的不僅是空間的壓縮,還有就是行訪問時的高效。三元組如果是有序的,可以二分查找來訪問一行,但是行壓縮存儲按行訪問時的時間復雜度是常數級的。 大家可以參考下面這個行壓縮矩陣示意圖:

可能你會有疑問,你明明實現的行壓縮圖,怎么扯了這么多行壓縮矩陣呢?其實圖和矩陣是等價的,矩陣的一行可以看做是圖一個節點的出邊,矩陣的一列可以看做圖一個節點的入邊。當然這里需要滿足兩個條件:第一個就是圖節點編號必須是從0或者1開始的連續數值(這個可以通過對圖的節點做一次映射解決),第二個就是圖必須至少是弱連通的(非連通圖可以拆成連圖片)。實現了稀疏矩陣的高效存儲訪問,也就實現了圖的高效存儲訪問。

下面來說一下,我的實現。我的實現跟經典的行壓縮矩陣有兩個不同:第一個就是經典的行壓縮矩陣沒有考慮一行全為0的情況,我對這種情況做了處理(之所以處理當然不是因為我無聊,而是因為有這個需求)。第二個就是經典的行壓縮圖對按列訪問比較慢(當然是相對于按行訪問的速度而言),對行壓縮圖按列訪問時,時間復雜度是線性的。我也對這種情況做了處理。

這里簡單說一下我的思路:

第一個問題,我是通過將所有指針默認設為-1,即表示該行可能全為0,只有當有非零值時才設置為其正確的指針。當然訪問時也要做相應的處理。

第二個問題,我是這樣解決的。我按列壓縮存儲的方式,存了一份每一列不為0的行下標,以及每一列不為0的行下標開始的位置。這樣我的實現中就多了兩個向量,浪費了存儲空間,但是提高了按列訪問時的效率。

好了,talk is cheap,show me the code。下面是我的代碼(可能有錯,我只做了簡單的測試)

利用邊向量構造壓縮圖

復制代碼 代碼如下:

/*
 * buildGraph 利用邊向量 構造壓縮圖
 * 對邊分別按第一個頂點、第二個頂點排序
 * 然后分別按行壓縮圖和列壓縮圖構造行、列索引和指針
 * 全零行和全零列,指針置為-1
 */
    private void buildGraph(Vector<Edge> edges) {
        int edgeSize = edges.size();
        weight = new Vector<Float>(edgeSize);
        rowIndex = new Vector<Integer>(edgeSize);
        rowPtr = new Vector<Integer>(nodeCount + 1);
        colIndex = new Vector<Integer>(edgeSize);
        colPtr = new Vector<Integer>(nodeCount + 1);
        // set default value as -1
        for (int i = 0; i < nodeCount; ++i) {
            rowPtr.add(-1);
            colPtr.add(-1);
        }
        rowPtr.add(edges.size());
        colPtr.add(edges.size());

        // sort the edge based on first node
        EdgeBasedOnFirstNodeComparator cmp = new EdgeBasedOnFirstNodeComparator();
        Collections.sort(edges, cmp);
        // build row index and pointer
        int curNode = edges.elementAt(0).getFirstNode();
        int curPtr = 0;
        for (int i = 0; i < edgeSize; ++i) {
            Edge e = edges.elementAt(i);
            // System.out.println("curNode" + curNode + "firstNode: "
            // + e.getFirstNode());
            weight.add(e.getWeight());
            rowIndex.add(e.getSecondNode());
            if (curNode != e.getFirstNode()) {
                rowPtr.set(curNode, curPtr);
                curNode = e.getFirstNode();
                curPtr = i;
            }

        }
        rowPtr.set(curNode, curPtr);
        // sort the edge based on second node
        EdgeBasedOnSecondNodeComparator cmp2 = new EdgeBasedOnSecondNodeComparator();
        Collections.sort(edges, cmp2);
        // build column index and pointer
        curNode = edges.elementAt(0).getSecondNode();
        curPtr = 0;
        for (int i = 0; i < edgeSize; ++i) {
            Edge e = edges.elementAt(i);
            colIndex.add(e.getFirstNode());
            if (curNode != e.getSecondNode()) {
                colPtr.set(curNode, curPtr);
                curNode = e.getSecondNode();
                curPtr = i;
            }

        }
        colPtr.set(curNode, curPtr);
    }

復制代碼 代碼如下:

獲得一個節點的出邊
/*
 * getOutEdges 返回結點所有的出邊(即所有由結點指出的邊)
 *
 * @param node 要查找的結點
 *
 * @return 返回結點所有的出邊組成的向量
 */
@Override
public Vector<Edge> getOutEdges(int node) {
    Vector<Edge> res = new Vector<Edge>();
    int startIndex = getStartIndex(node, true);
    if (startIndex == -1) {
        // 沒有出邊的點
        return null;
    }
    int endIndex = getEndIndex(node, true);
    float value;
    Edge e;
    int outNode;
    for (int index = startIndex; index < endIndex; ++index) {
        value = weight.elementAt(index);
        outNode = rowIndex.elementAt(index);
        e = new Edge(node, outNode, value);
        res.add(e);
    }
    return res;
}

獲得一個節點的入邊
?
/*
 * getInEdges 獲取結點所有的入邊(即所有指向結點的邊)
 *
 * @param node 要查找的結點
 *
 * @return 返回所有由結點入邊組成的向量
 */
@Override
public Vector<Edge> getInEdges(int node) {
    Vector<Edge> res = new Vector<Edge>();
    int startIndex = getStartIndex(node, false);
    // 沒有入邊的點
    if (startIndex == -1) {
        return null;
    }
    int endIndex = getEndIndex(node, false);
    float value;
    Edge e;
    int inNode;
    for (int index = startIndex; index < endIndex; ++index) {
        inNode = colIndex.elementAt(index);
        value = getWeight(inNode, node);
        e = new Edge(inNode, node, value);
        res.add(e);
    }
    return res;
}


這里訪問方式就跟按行訪問不一樣了,行訪問時,直接讀weight向量里面對應的值就行了,這里不行,應該weight向量是按行訪問順序存的。我的解決方法,獲取入節點,然后對整個節點對按行訪問獲得對應值。這樣雖然繞了一下,但是對于稀疏圖來說,基本上也是常數級的。下面是getWeight的代碼
復制代碼 代碼如下:

/*
     * getWeight 獲得特定邊的weight
     */
    private float getWeight(int row, int col) {
        int startIndex = getStartIndex(row, true);
        if(startIndex==-1)
            return 0;
        int endIndex = getEndIndex(row, true);
        for (int i = startIndex; i < endIndex; ++i) {
            if (rowIndex.elementAt(i) == col)
                return weight.elementAt(i);
        }
        return 0;
    }

最后是對行或者列全0時的特殊處理,這里處理,體現在從指針向量獲取開始和結束位置的函數上
復制代碼 代碼如下:

/*
 * getStartIndex 獲取特定頂點的開始索引
 */
    private int getStartIndex(int node, boolean direction) {
        // true : out edge
        if (direction)
            return rowPtr.elementAt(node);
        else
            return colPtr.elementAt(node);
    }

 
?
/*
 * getEndIndex 獲取特定頂點的結束索引
 */
    private int getEndIndex(int node, boolean direction) {
        // true:out edge
        if (direction) {
            int i = 1;
            while ((node + i) < nodeCount) {
                if (rowPtr.elementAt(node + i) != -1)
                    return rowPtr.elementAt(node + i);
                else
                    ++i;
            }
            return rowPtr.elementAt(nodeCount);
        } else {
            int i = 1;
            while ((node + i) < nodeCount) {
                if (colPtr.elementAt(node + i) != -1)
                    return colPtr.elementAt(node + i);
                else
                    ++i;
            }
            return colPtr.elementAt(nodeCount);
        }
    }


這里我只實現了兩個最簡單的功能,獲取入邊和出邊。一方面是因為,對于我做的東西,這兩個函數就夠了,另一方面,對于一個圖來說,有這兩個函數,其他函數都可以相應實現。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品国产1区2区| 91精品视频播放| 亚洲精品小视频在线观看| 国产精品九九久久久久久久| 中文字幕久久久av一区| 亚洲午夜久久久影院| 亚洲xxxxx性| 久久视频中文字幕| 国外成人性视频| 中文字幕视频一区二区在线有码| 国产一区二区三区在线看| 欧美激情综合色综合啪啪五月| 最新中文字幕亚洲| 蜜月aⅴ免费一区二区三区| 成人伊人精品色xxxx视频| 91啪国产在线| 亚洲国产精品人久久电影| 91亚洲国产精品| 国产精品欧美激情在线播放| 国产日产欧美a一级在线| 亚洲综合中文字幕在线观看| 欧美丝袜第一区| 久久精品国产91精品亚洲| 在线观看欧美日韩国产| 久久久久久久香蕉网| 91精品在线一区| 国产精品爽爽爽爽爽爽在线观看| 91性高湖久久久久久久久_久久99| 日韩精品一区二区视频| 久久久久久久久久久网站| 国产69精品久久久久久| 欧亚精品中文字幕| 一区二区三区在线播放欧美| 中文字幕亚洲图片| 亚洲美女精品成人在线视频| 亚洲伊人久久综合| 成人在线一区二区| 国产精品第一视频| 亚洲japanese制服美女| 中文字幕久精品免费视频| 亚洲黄色www| 欧美精品激情在线观看| 日韩av在线免播放器| 亚洲最大的av网站| 国产精品日韩电影| 中文字幕亚洲字幕| 国产精品专区第二| 亚洲精品国产品国语在线| 色综合天天狠天天透天天伊人| 亚洲精品久久久久| 96精品久久久久中文字幕| 久久久免费高清电视剧观看| 91在线无精精品一区二区| 黄色一区二区在线| 91沈先生在线观看| 色七七影院综合| 亚洲a成v人在线观看| 91久久久久久久| 国产亚洲精品久久久优势| 亚洲国产精品久久| 中文字幕九色91在线| 国产精品久久久久免费a∨| 国产精品第1页| 粉嫩老牛aⅴ一区二区三区| 精品国产一区二区三区四区在线观看| 亚洲成人久久久| 这里只有精品视频在线| 久久久久久12| 精品国产福利在线| 精品小视频在线| 伊人一区二区三区久久精品| 国产美女扒开尿口久久久| 91极品视频在线| 日韩暖暖在线视频| 成人欧美一区二区三区在线湿哒哒| 欧美性jizz18性欧美| 日韩欧亚中文在线| 亚洲毛片一区二区| 亚洲欧美一区二区激情| 国产午夜精品一区理论片飘花| 最近中文字幕日韩精品| 日韩欧美有码在线| 久久久www成人免费精品张筱雨| 欧洲亚洲在线视频| 欧美黑人国产人伦爽爽爽| 久久国产精品免费视频| 欧美日韩在线免费| 欧美激情欧美激情| 色综合色综合久久综合频道88| 日韩精品视频在线观看免费| 成人免费看吃奶视频网站| 亚洲理论片在线观看| 欧美日韩成人免费| 国产精品麻豆va在线播放| 91高清免费在线观看| 在线一区二区日韩| 亚洲一区二区三区乱码aⅴ蜜桃女| 91久久精品国产91久久| 欧美大片在线看免费观看| 91久久精品日日躁夜夜躁国产| 亚洲精品欧美日韩专区| 91久久久在线| 欧美午夜美女看片| 亚洲美女在线视频| 色老头一区二区三区| 日韩av片免费在线观看| 91天堂在线观看| 日韩亚洲欧美中文高清在线| 欧美又大粗又爽又黄大片视频| 亚洲a在线观看| 日韩黄色在线免费观看| 欧美高清不卡在线| 久久久久久国产精品三级玉女聊斋| 亚洲精品久久久久久下一站| 国产69精品久久久久久| 国产亚洲人成网站在线观看| 欧美一区二区三区免费视| 欧美国产日韩免费| 欧美大片大片在线播放| 亚洲四色影视在线观看| 久久在线视频在线| 伊人久久久久久久久久久久久| 亚洲色图综合网| 91精品综合久久久久久五月天| 国产精品99导航| 久久国产精品久久久久久| 97在线视频观看| 亚洲无线码在线一区观看| 91禁外国网站| 成人精品一区二区三区电影黑人| 国产91色在线播放| 亚洲精品小视频在线观看| 国产精品美女www| 欧美激情精品久久久| 日韩在线免费av| 91在线视频导航| 精品国产91乱高清在线观看| 日韩av影视综合网| 欧美性猛交xxxx偷拍洗澡| 在线观看亚洲区| 欧美精品18videos性欧美| 久久成人精品一区二区三区| 日韩黄色av网站| 国产精品va在线播放我和闺蜜| 日韩视频免费中文字幕| 欧美日韩亚洲高清| 欧洲成人在线观看| 92看片淫黄大片欧美看国产片| 中文字幕在线观看日韩| 亚洲 日韩 国产第一| 精品人伦一区二区三区蜜桃网站| 亚洲天堂第二页| 一区二区三区视频免费| 欧美日韩人人澡狠狠躁视频| 精品呦交小u女在线| 国产精品福利在线| 国产亚洲精品高潮| 欧美视频免费在线观看| 国内偷自视频区视频综合| 免费91麻豆精品国产自产在线观看| 中文日韩电影网站| 亚洲精品国产精品国自产在线| 久久综合久久八八| 久久91精品国产91久久跳|