有向圖的鄰接表標記法

來源:互聯網
上載者:User

圖的鄰接表標記法類似於樹的孩子鏈表標記法。對於圖G中的每個頂點vi,該方法把所有鄰接於vi的頂點vj鏈成一個帶頭結點的單鏈表,這個單鏈表就稱為頂點vi的鄰接表(Adjacency List)。

1. 鄰接表的結點結構


(1)表結點結構
    ┌────┬───┐ 
    │adjvex  │next  │
    └────┴───┘
     鄰接表中每個表結點均有兩個域:
 ① 鄰接點域adjvex
  存放與vi相鄰接的頂點vj的序號j。
 ② 鏈域next
  將鄰接表的所有表結點鏈在一起。
  注意:
     若要表示邊上的資訊(如權值),則在表結點中還應增加一個資料域。

(2)頭結點結構
    ┌────┬─────┐ 
    │vertex  │firstedge │
    └────┴─────┘
     頂點vi鄰接表的頭結點包含兩個域:
 ① 頂點域vertex
  存放頂點vi的資訊
 ② 指標域firstedge
  vi的鄰接表的頭指標。
  注意:
     ① 為了便於隨機訪問任一頂點的鄰接表,將所有頭結點順序儲存在一個向量中就構成了圖的鄰接表表示。
     ② 有時希望增加對圖的頂點數及邊數等屬性的描述,可將鄰接表和這些屬性放在一起來描述圖的儲存結構。

2.代碼執行個體

#include<iostream><br />using namespace std;<br />#define MAX_VERTEX_NUM 50//定義圖的最大頂點數<br />typedef char VertexData;<br />typedef struct EdgeNode//表結點<br />{<br />int adjvex;//鄰接點域<br />VertexData data;<br />EdgeNode *next;//邊結點所對應的下一個邊結點<br />} EdgeNode;<br />typedef struct VertexNode//頭結點<br />{<br />VertexData data;<br />EdgeNode *firstedge;//頭結點所對應的第一個邊結點<br />}VertexNode;<br />typedef struct AdjList<br />{<br />int VexNum,ArcNum;//定義圖的頂點數和邊數<br />VertexNode vertex[MAX_VERTEX_NUM];//定義頭結點數組。<br />}AdjList;<br />void CreateGraph(AdjList *adj,int *n)<br />{<br />int e,s,d;<br />cout<<"輸入頂點數和邊數"<<endl;<br />cin>>*n>>e;//輸入頂點數和邊數。<br />adj->VexNum=*n;<br />adj->ArcNum=e;<br />EdgeNode *q=NULL;<br />//初始化表頭結點<br />int i;<br />for(i=1;i<=*n;i++)<br />{<br />cout<<"輸入第"<<i<<"個結點的頂點名稱"<<endl;<br />cin>>adj->vertex[i].data;//頂點名稱,是一個字元<br />adj->vertex[i].firstedge=NULL;<br />}<br />for(i=1;i<=e;i++)<br />{<br /> cout<<"輸入第"<<i<<"條邊的起點和終點"<<endl;<br />cin>>s>>d;//輸入邊的起始和終止<br /> // cout<<"輸入表結點資訊"<<endl;<br />q=(EdgeNode *)malloc(sizeof(EdgeNode));//建立一個表結點<br />if(q==NULL)<br />return;<br />q->adjvex=d;<br />//cin>>q->data;<br />q->next=adj->vertex[s].firstedge;//新加入的節點都是在頭結點之後,原來在頭結點之後的節點要後移。<br />adj->vertex[s].firstedge=q;<br />}<br />}<br />void DisplayGraph(AdjList *adj)<br />{<br />int n=adj->VexNum;//頂點個數,後面要遍曆每一個點點<br />EdgeNode *q=NULL;<br />int i;<br />for( i=1;i<=n;i++)<br />{<br />//cout<<n<<endl;<br />q=adj->vertex[i].firstedge;<br />if(q==NULL)//表示頭結點後面沒有跟其他結點<br />{<br />cout<<"沒用從"<<adj->vertex[i].data<<"出發的節點"<<endl;<br />}<br />else<br />{<br />cout<<"從結點"<<adj->vertex[i].data<<"出發的邊有"<<endl;<br />while(q!=NULL)<br />{<br />//cout<<adj->vertex[i].data<<"->"<<q->data<<endl;<br />cout<<adj->vertex[i].data<<"->"<<adj->vertex[q->adjvex].data<<endl;<br />q=q->next;<br />}<br />}<br />}<br />}<br />void main()<br />{<br />int n;<br />AdjList *adj=(AdjList *)malloc(sizeof(AdjList));<br />CreateGraph(adj,&n);<br />DisplayGraph(adj);<br />//cout<<"hello world!"<<endl;<br />} 

輸出結果為:

輸入頂點數和邊數<br />6 6<br />輸入第1個結點的頂點名稱<br />a<br />輸入第2個結點的頂點名稱<br />b<br />輸入第3個結點的頂點名稱<br />c<br />輸入第4個結點的頂點名稱<br />d<br />輸入第5個結點的頂點名稱<br />e<br />輸入第6個結點的頂點名稱<br />f<br />輸入第1條邊的起點和終點<br />1 3<br />輸入第2條邊的起點和終點<br />2 4<br />輸入第3條邊的起點和終點<br />2 1<br />輸入第4條邊的起點和終點<br />4 3<br />輸入第5條邊的起點和終點<br />3 6<br />輸入第6條邊的起點和終點<br />3 5<br />從結點a出發的邊有<br />a->c<br />從結點b出發的邊有<br />b->a<br />b->d<br />從結點c出發的邊有<br />c->e<br />c->f<br />從結點d出發的邊有<br />d->c<br />沒用從e出發的節點<br />沒用從f出發的節點 

3.代碼執行個體2(ps:補充於2011-6-14)

      總體而言,鄰接表標記法中主要含有兩種結點,分別是頭結點和表結點(也叫做邊結點),在頭結點(s)到表結點(d)之間存在著一條邊。如果頭結點後面有多個表結點,即s->d1->d2,則表示存在著兩條邊,分別是e(s,d1)和e(s,d2)。鄰接表標記法中,頭結點的數量是固定的,就是圖中的頂點數量V,表結點的數量由邊的數量來決定。如果是有向圖,表結點的數量=邊的數量;如果是無向圖,則表結點的數量=邊的數量*2。

      在構造圖的時候,如果一個頭結點後面有多個表結點,那麼表結點按次序添加在頭結點後面。比如原先有結構s->d1->d2,現在需要添加表結點d3,那麼需要打斷s->d1的指標,讓d3指向d1,s指向d3。即s->d3->d1->d2。

#include<iostream><br />#include<stdlib.h><br />using namespace std;<br />#define MAX_VERTEX_NUM 50//定義圖的最大頂點數<br />typedef char VertexData;//頂點名稱是字元型。<br />typedef struct EdgeNode//表結點<br />{<br />int adjvex;//鄰接點域<br />VertexData data;<br />EdgeNode *next;//表結點所對應的下一個表結點<br />} EdgeNode;<br />typedef struct VertexNode//頭結點<br />{<br />VertexData data;<br />EdgeNode *firstedge;//頭結點所對應的第一個表結點<br />}VertexNode;<br />typedef struct AdjList//圖的資料結構<br />{<br />int VexNum,ArcNum;//定義圖的頂點數和邊數<br />VertexNode vertex[MAX_VERTEX_NUM];//定義頭結點數組。<br />}AdjList;<br />void CreateGraph(AdjList *adj)<br />{<br />int s,d;<br />int i;<br />cout<<"輸入頂點數和邊數"<<endl;<br />cin>>adj->VexNum>>adj->ArcNum;//輸入圖的頂點數和邊數。<br />EdgeNode *q=NULL;//定義表結點<br />//初始化表頭結點<br />cout<<"輸入"<<adj->VexNum<<"個頭結點的名稱"<<endl;<br />for(i=1;i<=adj->VexNum;i++)<br />{<br />//adj->vertex[i]是頭結點數組<br />cin>>adj->vertex[i].data;//頂點名稱,是一個字元<br />adj->vertex[i].firstedge=NULL;//初始狀態下頭結點後面不跟表結點,因此firstedge=null<br />}<br />//在初始化頭結點以後,就需要開始將表結點添加到頭結點後面去。<br />cout<<"輸入"<<adj->ArcNum<<"條邊的起點和終點"<<endl;<br />for(i=1;i<=adj->ArcNum;i++)<br />{<br />cin>>s>>d;//輸入邊的起始和終止,起始s就是頭結點位置,終止d就是表結點位置<br />q=(EdgeNode *)malloc(sizeof(EdgeNode));//建立一個表結點,為其分配空間<br />if(q==NULL)<br />return;<br />/*<br />如果原來的鏈表是s->a->b-c>,現在要加入一個表結點q,那麼加入以後就變成了s->q->a->b->c<br />因此:<br />1.q所指向的應該是當前s所指向的元素。<br />2.q的鄰接點域是d<br />3.s的指標指向q<br />操作如以下三行代碼<br />*/<br />q->adjvex=d;//表結點的鄰接點域是d<br />q->next=adj->vertex[s].firstedge;//新加入的節點都是在頭結點之後,原來在頭結點之後的節點要後移。<br />adj->vertex[s].firstedge=q;<br />}<br />}<br />void DisplayGraph(AdjList *adj)<br />{<br />int n=adj->VexNum;//頂點個數,後面要遍曆每一個點點<br />EdgeNode *q=NULL;<br />int i;<br />for( i=1;i<=adj->VexNum;i++)<br />{<br />//cout<<n<<endl;<br />q=adj->vertex[i].firstedge;//q為頭結點i所指向的表結點,i->q之間存在邊<br />if(q==NULL)//表示頭結點後面沒有跟其他結點<br />{<br />cout<<"沒用從"<<adj->vertex[i].data<<"出發的節點"<<endl;<br />}<br />else<br />{<br />cout<<"從結點"<<adj->vertex[i].data<<"出發的邊有"<<endl;<br />while(q!=NULL)<br />{<br />//cout<<adj->vertex[i].data<<"->"<<q->data<<endl;<br />cout<<adj->vertex[i].data<<"->"<<adj->vertex[q->adjvex].data<<endl;<br />q=q->next;//鏈表往後跳<br />}<br />}<br />}<br />}<br />void main()<br />{<br />int n;<br />AdjList *adj=(AdjList *)malloc(sizeof(AdjList));<br />CreateGraph(adj);<br />DisplayGraph(adj);<br />system("pause");<br />}<br />/*<br />輸入頂點數和邊數<br />6 6<br />輸入6個頭結點的名稱<br />a b c d e f<br />輸入6條邊的起點和終點<br />1 3<br />2 4<br />2 1<br />4 3<br />3 6<br />3 5<br />從結點a出發的邊有<br />a->c<br />從結點b出發的邊有<br />b->a<br />b->d<br />從結點c出發的邊有<br />c->e<br />c->f<br />從結點d出發的邊有<br />d->c<br />沒用從e出發的節點<br />沒用從f出發的節點<br />請按任意鍵繼續. . .<br />*/ 

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.