介紹
- 學習記錄
- 定義
使用方陣A[n][n]表示n個頂點之間構成的圖,其中每個單元負責對一對頂點之間鄰接關係進行描述
- 缺點
方陣可以描述所有可能存在的邊的關係, 但是實際問題邊並沒有出現那麼多,浪費了大量的空間; 可以使用A[n] = LIST代替(鄰接列表),列表中只存放當前節點一定存在的鄰接頂點
實現
//
// Created by carso on 2020/3/14.
//
#ifndef C___GRAPMATRIX_H
#define C___GRAPMATRIX_H
#include <Graph.h>
#include <Vector.h>
#include <limits.h>
// 定義頂點
template<typename Tv>
struct Vertex {
Tv data; // 數據
int inDegree, outDegree, // 入度,出度
VStatus
status; // 狀態 未發現,發現,訪問
int dTime, fTime; // 時間標籤 (用來算法判斷邊類型)
int parent; // 遍歷樹中的父級頂點
int priority; // 遍歷樹中的優先級
// 構造函數
Vertex(Tv const &d = (Tv) 0) : data(d), inDegree(0), outDegree(0), status(UNDETERMINED),
dTime(-1), fTime(-1), parent(-1), priority(INT_MAX) {}
};
// 定義邊
template<typename Te>
struct Edge {
Te data; // 數據
int weight; //權重
EType type; // 邊類型
// 構造函數
Edge(Te const &d, int w) : data(d), weight(w), type(UNDETERMINED) {}
};
// 定義鄰接矩陣
template<typename Tv, typename Te>
class GraphMatrix : public Graph {
private:
// 頂點集(向量)
Vector <Vertex<Tv>> V;
// 邊集合 (鄰接矩陣)
Vector <Vector<Edge<Te> *>> E;
public:
// 構造函數
GraphMatrix() { n = e = 0 }
// 析構函數
~GraphMatrix() {
// 刪除所有邊
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
delete E[i][j];
}
delete V[i];
}
}
// 頂點操作
// 返回特定頂點的數據
virtual Tv &vertex(int i) { return V[i].data; }
// 入度
virtual int inDegree(int i) {
return V[i].inDegree;
}
// 出度
virtual int outDegree(int i) {
return V[i].outDegree;
}
// 首個鄰接頂點
virtual int firstNbr(int i) {
return nextNbr(i, n);
}
// 下一個鄰接頂點, 注意不包含下標j
virtual int nextNbr(int i, int j) {
while (j > -1 && !exist(i, --j)) {}
return j;
}
// 狀態
virtual VStatus &status(int i) { return V[i].status; }
// 時間標籤
virtual int &dTime(int i) {
return V[i].dTime;
}
virtual int &fTime(int i) {
return V[i].fTime;
}
// 在遍歷樹中父節點
virtual int &parent(int i) { return V[i].parent; }
// 遍歷樹中的優先級
virtual int &priority(int i) {
return V[i].priority;
}
// 頂點動態操作
// 插入頂點,返回編號
virtual int insert(Tv const &vertex) {
// 各個頂點預留一條潛在的關聯邊
for (int i = 0; i < n; ++i) {
E[i].insert(NULL);
}
// 總頂點數+1
n++;
// 創建新邊
Vector < Edge<Te> * > newEdgePoint = new Vector(n, n, (Edge<Te> *) NULL);
E.insert(newEdgePoint);
// 頂點向量增加一個頂點
return V.insert(Vertex(vertex));
}
// 刪除頂點和關聯邊
virtual Tv remove(int i) {
// 刪除可能存在的邊
for (int j = 0; j < n; ++j) {
if (exists(i, j)) {
delete E[i][j];
V[j].inDegree--;
}
}
E.remove(i);
n--;
// 刪除頂點
Tv vBak = V.remove(i);
// 刪除所有的入邊
for (int k = 0; k < n; ++k) {
if (Edge(Te) * e = E[k].remove(i)) {
delete e;
V[k].outDegree--;
}
}
return vBak;
}
// 邊操作
// 邊(i,j)是否存在
virtual bool exists(int i, int j) {
return i > 0 && j > 0 && i < n && j < n && (E[i][j] != NULL);
}
// 邊的類型
virtual EType &type(int i, int j) {
return E[i][j]->type;
}
// 邊的數據
virtual Te &edge(int i, int j) {
return E[i][j]->data;
}
// 邊的權重
virtual int &weight(int i, int j) {
return E[i][j]->weight;
}
// 插入操作
virtual void insert(Te const &edge, int w, int i, int j) {
// 如果邊已經存在
if (exists(i, j)) {
return;
}
// 創建新邊
E[i][j] = new Edge(edge, w);
e++;
V[i].outDegree++;
V[J].inDegree++;
}
// 邊刪除操作
virtual Te remove(int i, int j) {
// 邊不存在
if (!exists(i, j)) {
return;
}
Te edge = edge(i, j);
// 刪除邊
delete E[i][j];
// 維持空邊
E[i][j] = NULL;
// 出度入度
V[i].outDegree--;
V[j].inDegree--;
// 邊數
e--;
return edge;
}
};
#endif //C___GRAPMATRIX_H