【資料結構】第六章學習小結--- 圖

EpisodeW發表於2019-05-19

在第十一和第十二週的學習中,我瞭解到了有關圖的一些知識,圖是一種比線性表和樹更為複雜的資料結構,她不像線性表一樣,資料元素之間具有線性關係,每個元素對應一個前驅和一個後繼,她也不像樹一樣,資料元素之間有明顯的層次關係,簡而言之,在圖結構中,結點之間的關係可以是任意的,圖中任意兩個資料元素之間都可能相關。感覺自己這一週有點鬆懈了,pta上面的題目都只是看一遍題目覺得不會就去翻書,或是求助同學,缺少獨立思考!!!欸,還是先講講有關圖的一些基本知識吧。

1、 圖的定義

         圖是由頂點的有窮非空集合和頂點之間邊的集合組成,通過表示為G(V,E),其中,G標示一個圖,V是圖G中頂點的集合,E是圖G中邊的集合。

         無邊圖:若頂點Vi到Vj之間的邊沒有方向,則稱這條邊為無項邊(Edge),用序偶對(Vi,Vj)標示。

         對於下圖無向圖G1來說,G1=(V1, {E1}),其中頂點集合V1={A,B,C,D};邊集合E1={(A,B),(B,C),(C,D),(D,A),(A,C)}:

                                

         有向圖:若從頂點Vi到Vj的邊是有方向的,則成這條邊為有向邊,也稱為弧(Arc)。用有序對(Vi,Vj)標示,Vi稱為弧尾,Vj稱為弧頭。如果任意兩條邊之間都是有向的,則稱該圖為有向圖。

         有向圖G2中,G2=(V2,{E2}),頂點集合(A,B,C,D),弧集合E2={<A,D>,{B,A},<C,A>,<B,C>}.

         權(Weight):有些圖的邊和弧有相關的數,這個數叫做權(Weight)。這些帶權的圖通常稱為網(Network)。

2、  圖的儲存結構

鄰接矩陣:圖的鄰接矩陣儲存方式是用兩個陣列來標示圖。一個一位陣列儲存圖頂點的資訊,一個二維陣列(稱為鄰接矩陣)儲存圖中邊或者弧的資訊。

設圖G有n個頂點,則鄰接矩陣是一個n*n的方陣,定義為:

圖的鄰接矩陣儲存表示:

#define MaxInt 10000  //表示極大值,即∞
#define MVNum 100    //最大頂點數
typedef char VerTexType;//假設頂點的資料型別為字元型
typedef int ArcType;        //假設邊的權值型別為整型
typedef struct
{
    VerTexType Vexs[MVNum]; //頂點表
    ArcType arcs[MVNum] [MVNum]; //鄰接矩陣
    int vexnum,arcnum;           //圖的當前點數和邊數
}AMGraph;

 

鄰接表:圖的鏈式儲存結構

#define MvNum 100       //最大頂點數 
typedef struct ArcNode    //邊結點
{
    int adjvex;            //該邊所指向的頂點的位置 
    struct ArcNode *nextarc;//指向下一條邊的指標 
}ArcNode;

typedef struct VNode    //頂點資訊
{
    VertexType data;
    ArcNode *firstarc;  //指向第一條依附該頂點的邊的指標 
}VNode,AdjList[MvNum];  //AdjList表示鄰接表型別

typedef struct
{
    AdjList Vertices;   //一維陣列
    int vexnum,arcnum;  //圖的當前頂點數和邊數 
}Graph;

採用鄰接表表示法建立無向圖:

Void CreateUDG(ALGraph &G)
{/*採用鄰接表表示法建立無向圖G*/
 cin>>G.vexnum>>G.arcnum;/*輸入總頂點數,總邊數*/
for(i=0;i<G.vexnum;++i)
{
 cin>>G.vertices[i].data;/*頂點值*/
 G.vertices[i].firstarc=NULL;
}
for(k=0;k<G.arcnum;++k)
{/*輸入各邊,構造鄰接表*/
cin>>v1>>v2;/*一條邊對應的兩個頂點*/
i=LocateVex(G,v1);
j=LocateVex(G,v2);/*確定v1,v2在G.vertices[i]的序號*/
p1=new ArcNode;
p1->adjvex=j;
p1->nextarc=G.vertices[i].firstarc;
G.vertices[i].firstarc=p1;
p2=new ArcNode;
p2->adjvex=i;
p2->nextarc=G.vertices[j].firstarc;
G.vertices[j].firstarc=p1
}
}

3、圖的遍歷

(1)深度優先搜尋遍歷

深度優先搜尋遍歷連通圖是一個遞迴的過程(劃重點?)

輔助陣列:vi[i]--訪問標誌陣列,賦初值為"false"(若已被訪問,則將相應的分量置為true。

鄰接矩陣表示的深度優先搜尋遍歷

void DFS(Graph a,int b) //深度優先搜尋 
{
    visited[b]=true;    //令頂點對應的visited陣列為true,表示該頂點已被訪問過 
    cout<<b<<" ";   //輸出頂點編號及空格 
     
    for(int i=0;i<a.vexnum;i++)
    {
        if(a.arcs[b][i]==1 && visited[i]==false)DFS(a,i);   //若頂點對應的鄰接點未被訪問,則遞迴呼叫DFS函式 
}
}

 

(2)廣度優先搜尋遍歷

特點:儘可能先對橫向進行搜尋

輔助陣列:visited[i]-訪問標誌陣列!!!

void BFS(Graph a,int b) //廣度優先搜尋 
{
    int temp;   //定義引數 
     
    while(!q.empty())   //若佇列不為空 
    {
        temp=q.front(); //取隊頭元素值為temp 
        q.pop();    //隊頭元素出隊 
             
        cout<<temp<<" ";    //輸出temp值及空格 
     
        for(int i=0;i<a.vexnum;i++)
        {
            if(a.arcs[temp][i]==1 && visited[i]==false) //若頂點對應的鄰接點未被訪問,則鄰接點入隊 
            {
                q.push(i);  //鄰接點入隊 
                visited[i]=true;    //鄰接點對應的visited陣列取true,表示已被訪問 
            }
        }
    visited[b]=true;    //第一次入隊的頂點對應的visited陣列值取true,表示已被訪問
    }
}

4、圖的應用

(1)最小生成樹--在一個連通的所有生成樹之中,各邊權值之和最小的那個生成樹

a 普里姆演算法(從名字上就能看出非常的高大上)又稱為“加點法”(逐步增加U中的頂點)

輔助陣列:clsoedge[i]--記錄從U到U-V具有最小權值的邊(lowcost+adjvex)

struct{
VerTexType adjvex;
ArcType lowcost;
}closedge[MVNUM];

b 克魯斯卡爾演算法---“加邊法”(逐步增加生成樹的邊)

輔助陣列:Edge[i]--儲存邊的資訊

struct{

VerTexType Head;

VerTexType Tail;

ArcType lowcost;

}Edge[arcnum];

                 Vexset[i]--標識各個頂點所屬的連通分量

int VexSet[MVNUM];

(2)最短路徑--從源點到其餘各頂點的最短路徑

迪傑斯特拉演算法(按照路徑長短遞增的次序產生最短路徑)

 

目標的完成情況:

  這幾週上課沒能集中精力,沒有及時複習上一章的內容,被上次的小測成績打擊到了,有點遺憾,平時打的練習題還不夠多。這兩週都有儘量去pta上答題,可是效率不高,遇到程式設計題就不會,沒有思路,結果到現在還沒完成。

接下來的目標:這幾天深夜加班爆肝一下,嘗試自己把題目弄懂,必要時多多借鑑同學的部落格,看別人在遇到問題時是怎樣解決的。

參考資料:大話資料結構-圖論 https://www.cnblogs.com/w-wanglei/p/figure.html

 

相關文章