鄰接矩陣


(以下圖為例子)采用鄰接矩陣的方法定義圖的數據結構,並實現圖的深度優先周游算法。

1.首先先定義並實現圖的邊Edge類,Edge類中的成員變量有:from->起點 to->終點 weight->權值(權值初始化為0)

Edge.h

 1 class Edge  2 {  3 public:  4 int from, to, weight;  5 public:  6  Edge() {  7 from = -1;  8 to = -1;  9 weight = 0; 10  } 11 12 Edge(int f, int t, int w){ 13 from = f; 14 to = t; 15 weight = w; 16  } 17 ~Edge() {} 18 };

 

2.定義圖的基類,便於鄰接矩陣的繼承

Graph.h

 1 #include "Edge.h"  2 class Graph  3 {  4 protected:  5 const int UNVISITED;  6 const int VISITED;  7 public:  8 int numVertex; //圖中頂點的總個數  9 int numEdge; //邊數 10 int *Mark; //標記 11 //int *Indegree; //存放圖中頂點的入度 12 public: 13 bool IsEdge(Edge oneEdge); //判斷是否為邊 14 Graph(int numVertex); 15 ~Graph(); 16 };

Graph.cpp

 1 #include "Graph.h"  2  3 Graph::Graph(int numVertex):UNVISITED(0),VISITED(1){  4 this->numVertex = numVertex;  5 this->numEdge = 0; //初始化頂點數為0  6 this->Mark = new int [numVertex]; //為標記數組動態分配空間  7 //this->Indegree = new int [numVertex];   8  9 for (int i = 0; i < numVertex; i++) 10  { 11 Mark[i] = UNVISITED; //將全部點初始化為未訪問 12 //Indegree[i] = 0; 13  } 14 } 15 16 Graph::~Graph(){ 17  delete []Mark; 18 //delete []Indegree; 19 } 20 21 bool Graph::IsEdge(Edge oneEdge){ 22 if (oneEdge.weight > 0 && oneEdge.to >= 0) 23  { 24 return true; 25  } 26 else return false; 27 }

 

3.定義Graph類的子類,將圖轉換為鄰接矩陣

tips:  Initialize函數形參中的*pWArray2D傳進的是一個二維數組。

Graphm.h

 

 1 #include "Graph.cpp"  2  3 class Graphm:public Graph  4 {  5 private:  6 int **matrix; //指向鄰接矩陣的指針  7 public:  8 Edge FirstEdge(int oneVertex); //返回以oneVertex為頂點的第一條Edge  9 Edge NextEdge(Edge preEdge); //返回與preEdge有相同頂點的下一條邊 10 void setEdge(int from,int to,int weigth); //設置邊 11 void delEdge(int from,int to); //刪除邊 12 void Initialize(Graphm *Graphm,int *pWArray2D ); //初始化圖 13 void Visited(Graphm &M,int v); //輸出訪問過的點 14 void DFS(Graphm &M,int v); //深度優先周游 15 int ToVertex(Edge oneEdge); //返回邊的終點 16 void Travel(Graphm &G,int startVertex); //周游全圖 17 Graphm(int numVertex); 18 ~Graphm(); 19 };

 

Graphm.cpp

 1 #include "Graphm.h"  2 #include <iostream>  3 using namespace std;  4  5 //構造函數  6 Graphm::Graphm(int numVertex):Graph(numVertex){  7 int i,j;  8 matrix = (int **)new int *[numVertex]; //申請matrix數組行向量數組  9  10 for (i = 0; i < numVertex; i++){  11 matrix[i] = new int[numVertex]; //申請行的存儲空間(列向量)  12  }  13  14 for (i = 0; i < numVertex; i++){  15 for (j = 0; j < numVertex; j++){  16 matrix[i][j] = 0;  17  }  18  }  19 cout << "構造函數執行!" << endl;  20 }  21 //析構函數釋放二維數組的動態分配的空間  22 Graphm::~Graphm(){  23 for (int i = 0; i < numVertex; i++)  24  {  25  delete [] matrix[i];  26  }  27  delete [] matrix;  28 cout << "釋放空間成功!" << endl;  29 }  30 //初始化圖  31 void Graphm::Initialize(Graphm *Graphm,int *pWArray2D){  32 cout << "開始初始化!" << endl;  33 int N = numVertex;  34 int array_i_j = 0;  35 for (int i = 0; i < N; i++)  36  {  37 for (int j = 0; j < N; j++)  38  {  39 array_i_j = *(pWArray2D + i*N + j); //獲得二維數組中每一個元素的值  40 //cout << array_i_j << endl;  41 if (array_i_j > 0) //當元素的值大於0時,證明有從i指向j的邊  42  {  43 Graphm->setEdge(i,j,array_i_j); //設置邊  44  }  45  }  46  }  47 cout << "初始化成功!" << endl;  48 /*for (int i = 0; i < numVertex; i++)  49  {  50  for (int j = 0; j < numVertex; j++)  51  {  52  cout << matrix[i][j] << " ";  53  }  54  cout << endl;  55  56  }*/  57 }  58 //返回以oneVertex為頂點的第一條Edge  59 Edge Graphm::FirstEdge(int oneVertex){  60  Edge myEdge;  61 myEdge.from = oneVertex;  62  63 for (int i = 0; i < numVertex; i++)  64  {  65 if (matrix[oneVertex][i] != 0)  66  {  67 myEdge.to = i;  68 myEdge.weight = matrix[oneVertex][i];  69 break;  70  }  71  }  72 return myEdge;  73 }  74 //返回與preEdge有相同頂點的下一條Edge  75 Edge Graphm::NextEdge(Edge preEdge){  76  Edge myEdge;  77 myEdge.from = preEdge.from;  78 if (preEdge.to+1 < numVertex)  79  {  80 for (int i = preEdge.to+1; i < numVertex; i++)  81  {  82 if (matrix[preEdge.from][i] != 0)  83  {  84 myEdge.to = i;  85 myEdge.weight = matrix[preEdge.from][i];  86 break;  87  }  88  }  89  }  90 return myEdge;  91 }  92 //為圖設置邊  93 void Graphm::setEdge(int from,int to,int weigth){  94 if (matrix[from][to] <= 0)  95  {  96 numEdge++; //邊的個數加1  97 //Indegree[to]++;  98  }  99 matrix[from][to] = weigth; 100 } 101 //刪除邊 102 void Graphm::delEdge(int from,int to){ 103 if (matrix[from][to] > 0) 104  { 105 numEdge--; //邊的個數減1 106 //Indegree[to]--; 107  } 108 matrix[from][to] = 0; 109 } 110 //輸出訪問過的點 111 void Graphm::Visited(Graphm &M,int v){ 112 cout << "v" << v << " "; 113 } 114 //返回邊的終點 115 int Graphm::ToVertex(Edge oneEdge){ 116 return oneEdge.to; 117 } 118 //深度優先周游 119 void Graphm::DFS(Graphm &M,int v){ 120 M.Mark[v] = VISITED; 121  Visited(M,v); 122 for (Edge e = M.FirstEdge(v); M.IsEdge(e); e = M.NextEdge(e)) 123  { 124 if (M.Mark[M.ToVertex(e)] == UNVISITED) 125  { 126 //cout << M.ToVertex(e) << endl; 127  DFS(M,M.ToVertex(e)); 128  } 129  } 130 } 131 //周游完整的圖 132 void Graphm::Travel(Graphm &G,int startVertex){ 133 DFS(G,startVertex); //不一定能周游每一個頂點 134 //更換頂點周游 135 for (int i = 0; i < numVertex; i++) 136  { 137 if (G.Mark[i] == UNVISITED) 138  { 139  DFS(G,i); 140  } 141  } 142 }

 

 

4.主函數的實現

tips: 先根據圖畫出鄰接矩陣,再將鄰接矩陣作為實參進行傳遞

Main.cpp

 1 #include "Graphm.cpp"  2 #define N 8  3 int main(int argc, char const *argv[])  4 {  5  6 //int N = 8;  7 int M[N][N] = {  8 0,0,0,1,0,0,0,0,  9 1,0,0,0,0,0,0,0, 10 1,1,0,0,0,0,0,1, 11 0,1,0,0,0,1,0,0, 12 0,0,1,0,0,0,0,0, 13 0,0,0,0,0,0,0,0, 14 0,0,0,0,1,1,0,0, 15 0,1,0,0,1,1,1,0 16  }; 17  Graphm G(N); 18 G.Initialize(&G,(int*)M); 19 cout << "全部深度周游:"; 20 21 G.Travel(G,3); 22 cout << endl; 23 24 return 0; 25 }

注:以下總結僅代表個人觀點(如有錯誤,歡迎指出)

總結:1.將圖寫為基類在此處體現出來的意義其實並不大(在此題中完全可以將Graph類與Graphm類合並起來),但是也是為了養成良好的習慣。

   2.主函數中二維數組的傳遞值得一記,傳遞的過程將其當成一位數組進行傳遞。

   3.周游的過程中需要考慮到當圖為不連通圖時,以某個頂點為起點時可能周游出來的結果不完整(以上的Travvel函數則能周游出全部的點。

   4.熟練掌握根據圖畫出對應的鄰接矩陣。

   5.無權圖的權值可設為1。

   6.動態分配的空間記得手動釋放,最好的做法是寫在析構函數中。


免責聲明!

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



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