图的两种存储方式---邻接矩阵和邻接表
? ?圖:圖是一種數據結構,由頂點的有窮非空集合和頂點之間邊的集合組成,表示為G(V,E),V表示為頂點的集
合,E表示為邊的集合。
? ?首先肯定是要對圖進行存儲,然后進行一系列的操作,下面對圖的兩種存儲方式鄰接矩陣和鄰接表盡行介紹。
? ?(一)、鄰接矩陣存儲:
? ?用兩個數組分別進行存儲數據元素(頂點)的信息和數據元素之間的關系(邊或弧)的信息。
? ?存儲頂點:用一個連續的空間存儲n個頂點。
? ?存儲頂點之間的邊:將由n個頂點組成的邊用一個n*n的矩陣來存儲,如果兩個頂點之間有邊,則表示為1,否
則表示為0。
? ?下面用代碼來實現鄰接矩陣的存儲:
#define SIZE 10class Graph { public:Graph(){MaxVertices = SIZE;NumVertices = NumEdges = 0;VerticesList = new char[sizeof(char)*MaxVertices];Edge = new int*[sizeof(int*)*MaxVertices];int i,j;for(i = 0;i<MaxVertices;i++)Edge[i] = new int[sizeof(int)*MaxVertices];for(i = 0;i<MaxVertices;i++){for(j = 0;j<MaxVertices;++j)Edge[i][j] = 0;}}void ShowGraph(){int i,j;cout<<" ";for(i = 0;i<NumVertices;i++)cout<<VerticesList[i]<<" ";cout<<endl;for(i = 0;i<NumVertices;i++){cout<<VerticesList[i]<<" ";for(j = 0;j<NumVertices;j++)cout<<Edge[i][j] <<" ";cout<<endl;}cout<<endl;}int GetVertexPos(char v){int i;for(i = 0;i<NumVertices;i++){if(VerticesList[i] == v)return i;}return -1;}~Graph(){Destroy();}void Insert(char v){if(NumVertices < MaxVertices){VerticesList[NumVertices] = v;NumVertices++; }}void InsertEdge(char v1,char v2) {int i,j;int p1 = GetVertexPos(v1); int p2 = GetVertexPos(v2);if(p1 == -1 || p2 == -1)return ;Edge[p1][p2] = Edge[p2][p1] = 1;NumEdges++; }void RemoveEdge(char v1,char v2){int p1 = GetVertexPos(v1);int p2 = GetVertexPos(v2);if(p1 == -1 || p2== -1)return;if(Edge[p1][p2] == 0) return;Edge[p1][p2] = Edge[p2][p1] = 0;NumEdges--;}void Destroy(){delete[] VerticesList;VerticesList = NULL;for(int i = 0;i<NumVertices;i++){delete Edge[i];Edge[i] = NULL;}delete[] Edge;Edge = NULL;MaxVertices = NumVertices = 0;}void RemoveVertex(char v){int i,j;int p = GetVertexPos(v);int reNum = 0;if(p == -1)return;for(i = p;i<NumVertices-1;i++) {VerticesList[i] = VerticesList[i+1];}for(i = 0;i<NumVertices;i++){if(Edge[p][i] != 0)reNum++;}for(i = p;i<NumVertices-1;i++){for(j = 0;j<NumVertices;j++){Edge[i][j] = Edge[i+1][j];}}for(i = p;i<NumVertices;i++){for(j = 0;j<NumVertices;j++)Edge[j][i] = Edge[j][i+1];}NumVertices--;NumEdges = NumEdges - reNum;} private:int MaxVertices;int NumVertices;int NumEdges;char *VerticesList;int **Edge; };? ? 上面的類中的數據有定義最大的頂點的個數(MaxVertices),當前頂點的個數(NumVertices),當前邊的個數
(NumEdges),保存頂點的數組,保存邊的數組。其中的方法是(1)構造函數:對定義的數據進行初始化。(2)顯
示構造的圖的信息的函數。(3)得到頂點位置信息的函數。(4)析構函數:調用銷毀函數。(5)插入頂點函數。
(6)插入邊的函數。(7)刪除邊的函數。(8)銷毀函數,釋放開辟的內存空間。(9)刪除頂點函數。
? (二)、鄰接表存儲:
? ?鄰接表是圖的一種鏈式存儲結構。用數組存儲頂點,用鏈表存儲和頂點相關聯的邊,邊值為當前頂點在數組中的下
標。用如下圖可以表示鄰接表的存儲方式:
? ? ? ? ? ? ? ? ?
? ? ? ? ? ? ? ? ??
? ?下面用代碼來實現鄰接表的存儲:
#define SIZE 10 typedef char T; struct Edge {Edge(int v):destvalue(v),link(NULL){}int destvalue;Edge *link; }; struct Vertex {Vertex():list(NULL){}T data;Edge *list; }; class GraphLnk { public:GraphLnk();~GraphLnk(){}void InsertVertex(T v);void InsertEdge(T v1,T v2);int GetVertexI(T v);void ShowGraph();void RemoveEdge(T v1,T v2);void RemoveVertex(T v);void DestroyGraph(); private:int MaxVertex;int NumVertex;int NumEdge;Vertex *VertexTable; };GraphLnk::GraphLnk() {MaxVertex = SIZE;NumVertex = NumEdge = 0;VertexTable = new Vertex[MaxVertex]; } void GraphLnk::InsertVertex(T v) {if(NumVertex >= MaxVertex)return;VertexTable[NumVertex++].data = v; } void GraphLnk::ShowGraph() {int i;for(i = 0;i<NumVertex;i++){cout<<i<<" "<<VertexTable[i].data<<":->";Edge *p = VertexTable[i].list;while(p != NULL){cout<<p->destvalue<<"->";p = p->link;}cout<<"nul"<<endl;}cout<<endl; } int GraphLnk::GetVertexI(T v) {int i;for(i = 0;i<NumVertex;i++){if(VertexTable[i].data == v)return i;}return -1; } void GraphLnk::InsertEdge(T v1,T v2) {int p1 = GetVertexI(v1);int p2 = GetVertexI(v2);if(p1 == -1 || p2 == -1)return;//v1 -> v2Edge *ed = new Edge(p2);ed->link = VertexTable[p1].list;VertexTable[p1].list = ed;//v2 -> v1ed = new Edge(p1);ed->link = VertexTable[p2].list;VertexTable[p2].list = ed;NumEdge++; }void GraphLnk::RemoveEdge(T v1,T v2) {int p1 = GetVertexI(v1);int p2 = GetVertexI(v2);if(p1 == -1 || p2 == -1)return;Edge *q = NULL; //標識要刪除邊鏈表的前一個Edge *p; p = VertexTable[p1].list; //從鏈表開頭開始//查找v2所在位置while(p != NULL && p->destvalue != p2){q = p;p = p->link;}if(p == NULL) //兩個頂點之間沒有邊的存在¨return;//找到所要刪除的邊if(q == NULL) //所要刪除的為鏈表開頭 {VertexTable[p1].list = p->link;}else{q->link = p->link;}delete p;p = NULL;q = NULL;p = VertexTable[p2].list;while(p->destvalue != p1){q = p;p = p->link;}if(q == NULL){VertexTable[p2].list = p->link;}else{q->link = p->link;}delete p;p = NULL;NumEdge--; }void GraphLnk::RemoveVertex(T vertex) {int v = GetVertexI(vertex);if(v == -1)return;//刪除和結點相關的邊Edge*p=VertexTable[v].list;Edge *s;Edge *t = NULL;int k;while(p != NULL){k = p->destvalue;s = VertexTable[k].list;while(s != NULL&&s->destvalue != v){t = s;s = s->link;}if(s != NULL){if(t == NULL) //第一個結點 {VertexTable[k].list = s->link;}else{t->link = s->link;}delete s;s = NULL;}VertexTable[v].list = p->link;delete p;p = VertexTable[v].list;}/*刪除結點,用最后一個結點覆蓋要刪除的結點,并把和最后一個結點相關聯的邊的下標改正*/NumVertex--;VertexTable[v].data = VertexTable[NumVertex].data; VertexTable[v].list = VertexTable[NumVertex].list; s = VertexTable[v].list;while(s != NULL){k = s->destvalue;p = VertexTable[k].list;while(p != NULL){if(p->destvalue == NumVertex) {p->destvalue = v;break;}p = p->link;}s = s->link;} }void GraphLnk::DestroyGraph() {Edge *p;for(int i = 0;i<NumVertex;i++){p = VertexTable[i].list;while(p != NULL){VertexTable[i].list = p->link;delete p;p = VertexTable[i].list;}}delete []VertexTable;MaxVertex = NumEdge = NumVertex = 0; }? ?在代碼實現的過程中,先定義出頂點和邊的數據結構,然后在類中定義了最大頂點數,當前頂點的個數,當前的
邊的個數,頂點類型的數組,還有在類中進行了函數的聲明,包括(1)構造函數。(2)析構函數。(3)插入頂點
函數。(4)插入邊函數。(5)得到頂點位置的函數。(6)顯示構造出的圖的信息函數。(7)刪除邊函數。(8)
刪除頂點函數。(9)銷毀函數。
?
轉載于:https://www.cnblogs.com/XNQC1314/p/9076698.html
總結
以上是生活随笔為你收集整理的图的两种存储方式---邻接矩阵和邻接表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: yml语法规则 (5.spring b
- 下一篇: wget命令【转】