數據結構之無向圖


前言:  

      我們所討論的圖模型中,邊僅僅是兩個頂點之間的連接。一般使用0-(V-1)來表示一張含有V個頂點的圖中的各個頂點。用v-w的記法表示v點和w點之間的邊(又可以寫成w-v)。

      特殊的兩種圖:

         自環:  一條連接一個頂點和其自身的邊。

         平行邊: 連接同一對頂點的兩條邊。

     以下所說的圖兩個頂點之間僅含有一條邊。

相關術語:

  

當邊連接兩個頂點時,我們說頂點彼此 相鄰。

頂點的度數為依附於他的邊的總數。

子圖是一幅圖所有被邊的一個子集(包括他們所依附的頂點)。

路徑是由邊連接的頂點序列,沒有重復的邊。

簡單路徑是沒有重復頂點的路徑。

是一條至少含有一條邊且起點和終點相同的路徑。

簡單環是一條(除了起點和終點必須相同之外)不含重復頂點和邊的環。

路徑或環的長度為其包含的邊數。

如果從任意一個頂點都存在一條路徑到達另一個任意頂點,則稱這幅圖是連通圖

一個非連通圖由若干連通圖組成,它們都是極大連通子圖

無環圖是一個不包含環的圖。

是一副無環連通圖。互不相連的樹組成森林。連通圖的生成樹是他的一副子圖,它含有圖中的所有頂點且是一顆樹。圖的生成森林是他的所有連通子圖的生成樹的集合。

關於樹的定義,以下五種說法是等價的:(一副含有V個頂點的圖G)

1:G有V-1條邊並且不含環。

2:G有V-1條邊並且是聯通的

3:G是連通的且刪除任意一條邊都會使他不連通。

4:G是無環圖且添加任意一條邊都會使他產生一條環。

5:G中任意一對頂點間僅存在一條簡單路徑。

 

我們定義以下圖的基本操作API:

Public  class   Graph

                 Graph(int V)   //創建一個含有V個頂點但不含邊的圖

                 Graph(InputStream in) //從標准輸入流中讀取一個圖

          int     V()    //頂點數

          int     E()    //邊數

          void addEdge(int v,int w)  //添加邊V-W

    Iterable<Integer> adj(int v)   //遍歷與v相鄰的頂點

           String toString()      // @Override

 

相關實現:

計算V的度數:

       public static int degree(Graph g,int v)

{    int  degree=0;

    for(int w: g.adj(v)) degree++;

   return degree;

}

計算所有頂點的最大度數:

   public static int maxDegree(Graph g)

{    int  max=0;

     for(int v=0;v<g.v();v++)

             if(degree(g,v)>max)

                   max=degree(g,v);

          return  max;   }

計算自環的個數:

public static int numberOfSefLoops(Graph g)

{   int count=0;

       for(int v=0;v<g.v();v++)

           for(int w:g.adj(v))

            if(w==v)  count++;

       return count/2;

}

//覆寫toString方法@Override

  public String toString()

{

    String s=V+”vertices”+E+” edges\n”;//建議你用StringBuilder

       for(int v=0;v<g.v();v++)

        {   s+=v+”:  ”;

              for(int w:this.adj(v))

                 s+=“\n”;

}

   return  s;

}

 

圖的幾種表示方法:

要求:  1、必須為各種情況下遇到的圖預留足夠空間。

             2、快。

  鄰接矩陣:

      用一個V * V的Boolean矩陣表示,1代表相連。

       //不滿足第一種要求。

  邊的數組:

       使用一個Edge類,含有兩個int變量。

       /不滿足第二個要求,比如調用adj方法。

  鄰接表數組:(推薦)

      使用以頂點為索引的列表數組,其中每個元素都是和該頂點相連的頂點列表。如下圖:

     

要連接一條v到w的邊,我們要將w添加到v的鄰接表中並把v添加到w的臨界表中。因此這種結構中每條邊都會出現兩次。

  代碼實現:

//我們使用前面介紹過的Bag,Stack實現,相關代碼請看數據結構之隊列、棧

 1 public class Graph {
 2 
 3     private final int V;
 4     private int E;
 5     private Bag<Integer> adj[];
 6     
 7     @SuppressWarnings("unchecked")
 8     public Graph(int V)
 9     {   if (V < 0) throw new IllegalArgumentException("Number of vertices must be nonnegative");
10         this.V=V;
11         this.E=0;
12         adj= (Bag<Integer>[])new Bag[V];
13         for(int i=0;i<V;i++)
14         {
15             adj[i]=new Bag<Integer>();
16         }
17     }
18     
19     public Graph(Graph G) {
20         this(G.V());
21         this.E = G.E();
22         for (int v = 0; v < G.V(); v++) {
23          
24             Stack<Integer> reverse = new Stack<Integer>();
25             for (int w : G.adj[v]) {
26                 reverse.push(w);
27             }
28             for (int w : reverse) {
29                 adj[v].add(w);
30             }
31         }
32     }
33     
34     public int V()
35     {
36         return this.V;
37     }
38     
39     public int E()
40     {
41         return this.E;
42     }
43     
44     private void validateVertex(int v) {
45         if (v < 0 || v >= V)
46             throw new IllegalArgumentException("vertex " + v + " is not between 0 and " + (V-1));
47     }
48     
49     public void addEdge(int v,int w)
50     {  validateVertex(v);
51        validateVertex(w);
52      adj[v].add(w);    
53      adj[w].add(v);
54      E++;
55     }
56     
57      public Iterable<Integer> adj(int v) {
58             validateVertex(v);
59             return adj[v];
60         }
61      
62       public int degree(int v) {
63             validateVertex(v);
64             return adj[v].size();
65         }
66       
67        public String toString() {
68             StringBuilder s = new StringBuilder();
69             s.append(V + " vertices, " + E + " edges " );
70             for (int v = 0; v < V; v++) {
71                 s.append(v + ": ");
72                 for (int w : adj[v]) {
73                     s.append(w + " ");
74                 }
75                 s.append("\r");
76             }
77             return s.toString();
78         }
79 
80 }
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM