《資料結構》C++程式碼 鄰接表與鄰接矩陣
阿新 • • 發佈:2019-02-19
上一篇“BFS與DFS”寫完,突然意識到這個可能偏離了“資料結構”的主題,所以回來介紹一下圖的儲存:鄰接表和鄰接矩陣。
存圖有兩種方式,鄰接矩陣嚴格說就是一個bool型的二維陣列,map[i][j]表示i到j有沒有單向邊,鄰接表則是對1~N中每個點都拉出一個連結串列來,連結串列E[i]中存的每個點j都表示i到j有一條單向邊。 這兩種方式各有利弊,在稀疏圖中,鄰接表更好,省時間而且省空間;在稠密圖中,鄰接矩陣更好,不浪費時間的同時省去了指標域的空間。
而實際寫程式碼時,對於鄰接矩陣,我們可能會考慮用int型的鄰接矩陣來同時表達邊的權值,這取決於具體情況;對於鄰接表,我們在對每個點拉出一個連結串列時,可以實際分配一個一維陣列作為表頭,以簡化刪除邊時的程式碼,同時方便存每個點的資訊,也可以像本文程式碼中直接用指標來作為表頭,省些空間。
本文僅僅給出相對基本的程式碼,邊上的資訊僅有一個權值,想必這已經夠了。如果資訊增多,大家在同樣的位置新增資訊即可。另外,臨界表在很多情況下是可以用靜態記憶體來代替動態記憶體的,這個方法本文程式碼就不贅述了,方法同“線性表”一文中所述。
注意!對於鄰接表和鄰接矩陣,我並未試過用類來寫,在此僅僅給出一個很醜的類版程式碼,不是為了供大家參考,而是拋磚引玉,希望有高手能給出更好的類版實現程式碼,不勝感激!
清爽版:
const int maxn = 10000; // 鄰接矩陣 struct edge { bool p; // p表示此邊有無,也可以通過c取一個題目中不可能取到的值來代替p的作用 int c; edge():p(false) {} }map[maxn+1][maxn+1]; void Clear() { for(int i=1;i<=maxn;++i) for(int j=1;j<=maxn;++j) map[i][j].p=false; } void AddEdge(int u,int v,int c) { map[u][v].p=true; map[u][v].c=c; } void DelEdge(int u,int v) { map[u][v].p=false; } // 鄰接表 struct edge { int v; int c; edge *next; edge(int _v=0,int _c=0): v(_v), c(_c) {} }*E[maxn+1]; // 全域性定義,初始便都是0;若在區域性定義,則應先清0 void Clear() { edge *p; for(int i=1;i<=maxn;++i) while(E[i]) { p=E[i]; E[i]=p->next; delete p; } } void AddEdge(int u,int v,int c) { edge *p=new edge(v,c); p->next=E[u]; E[u]=p; } void DelEdge(int u,int v) { if(E[u]->v==v) { E[u]=E[u]->next; return; } for(edge *p=E[u],*q=p->next;q;p=q,q=p->next) if(q->v==v) { p->next=q->next; delete q; return; // 如果有重邊,則此處不應返回,應待迴圈完再返回 } }
類版:
// 鄰接表 struct edge { int v; int c; edge *next; edge(int _v=0,int _c=0): v(_v), c(_c) {} }; class Map { static const int maxn = 10000; edge *E[maxn+1]; public: Map() { for(int i=1;i<=maxn;++i) E[i]=0; } void clear() { edge *p; for(int i=1;i<=maxn;++i) while(E[i]) { p=E[i]; E[i]=p->next; delete p; } } void add(int u,int v,int c) { edge *p=new edge(v,c); p->next=E[u]; E[u]=p; } void del(int u,int v) { if(E[u]->v==v) { E[u]=E[u]->next; return; } for(edge *p=E[u],*q=p->next;q;p=q,q=p->next) if(q->v==v) { p->next=q->next; delete q; return; // 如果有重邊,則此處不應返回,應待迴圈完再返回 } } edge* begin(int u) { return E[u]; } edge* next(edge *p) { return p->next; } }G;