圖論——鄰接表

圖論——鄰接表

鄰接表表示

在這裏插入圖片描述

對於上圖的鄰接表如下

0:1->2  意思是頂點0保持着一個鏈表,鏈表裏存放頂點0的鄰接頂點
1:0->3  意思是頂點1保持着一個鏈表,鏈表裏存放頂點1的鄰接頂點
2:0->3
3:1->2

代碼

public class AdjList {
    private int V;//頂點數
    private int E;//邊數
    private LinkedList<Integer>[] adj;//鄰接表,鏈表數組存儲

    public AdjList(String filename){
        File file = new File(filename);
        try(Scanner scanner = new Scanner(file)){
            V = scanner.nextInt();//頂點數
            if(V<=0) throw new RuntimeException("頂點個數必須大於0");
            adj = new LinkedList[V];
            for(int i=0;i<V;i++){
                adj[i] = new LinkedList<>();
            }
            E = scanner.nextInt();//邊數
            if(E<0) throw new RuntimeException("邊數不能爲負數");
            for(int i=0;i<E;i++){
                int a = scanner.nextInt();
                validateVertex(a);
                int b = scanner.nextInt();
                validateVertex(b);
                //自環邊檢測
                if(a==b){
                    throw new RuntimeException("簡單圖不能包含自環邊");
                }
                //平行邊檢測
                if(adj[a].contains(b)){
                    throw new RuntimeException("簡單圖不能包含平行邊");
                }
                adj[a].add(b);
                adj[b].add(a);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    private void validateVertex(int v){
        if(v<0||v>=V){
            throw new RuntimeException("頂點下標溢出");
        }
    }
    
    public int vertexNum(){
        return V;
    }
    
    public int edgeNum(){
        return E;
    }
    
    public boolean hasEdge(int v,int w){
        validateVertex(v);
        validateVertex(w);
        return adj[v].contains(w);
    }

    //鄰接頂點
    public List<Integer> adj(int v){
        validateVertex(v);
        return adj[v];
    }

    //度
    public int degree(int v){
        validateVertex(v);
        return adj[v].size();
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(String.format("V = %d,E = %d\n",V,E));
        for(int i=0;i<adj.length;i++){
            sb.append(i+":");
            for (Iterator<Integer> it = adj[i].iterator(); it.hasNext(); ) {
                sb.append(it.next()+" ");
            }
            sb.append("\n");
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        AdjList adjList = new AdjList("graph.txt");
        System.out.println(adjList);
        System.out.println(adjList.degree(6));
    }

graph.txt

7 6
0 1
0 2
1 3
2 6
2 3
1 4

複雜度分析

時間複雜度:
建圖:O(E*V) 這個V是平行邊檢測消耗的時間
判斷兩個頂點是否有邊:O(degree(v))
求一個頂點的鄰接頂點:O(degree(v)) 返回list給用戶,用戶也得遍歷,所以這裏不是O(1)
求一個頂點的度:O(1)

空間複雜度:O(V+E)

對於時間複雜度建圖過程需要花費V的時間檢測平行邊,這是因爲我們用的數據結構是LinkedList,如果改爲TreeSet,建圖只需要O(E*logV),甚至改爲HashSet只需要O(E),下一節介紹

發佈了143 篇原創文章 · 獲贊 74 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章