圖是很是重要的數據結構,現實中的不少問題都歸結於圖的問題,這裏咱們討論一下圖,關於圖的基礎:頂點、邊等概念可參考文檔:Graph Data Stucture,這裏再也不細述。ios
圖有兩種表示方法:鄰接矩陣、鄰接鏈表。不一樣的場景及算法可能須要不一樣的圖表示方式,通常狀況下當結點數量很是龐大時,會形成矩陣很是稀疏,空間開銷會較大,此時使用鄰接鏈表的表示方式會佔用較少的空間。而若是是稠密矩陣或者須要快速判斷任意兩個結點是否有邊相連等狀況,可能鄰接矩陣更合適。c++
#include<iostream>
using namespace std;
// 無向有權圖
class Graph {
public:
Graph(int numVertices) {
this->numVertices = numVertices;
matrix = new int*[numVertices];
for (int i = 0; i < numVertices; ++i) {
matrix[i] = new int[numVertices];
for (int j = 0; j < numVertices; ++j) {
matrix[i][j] = 0;
}
}
}
void addEdge(int v1, int v2, int value = 1) {
matrix[v1][v2] = value;
matrix[v2][v1] = value;
}
void removeEdge(int v1, int v2) {
matrix[v1][v2] = 0;
matrix[v2][v1] = 0;
}
bool isEdge(int v1, int v2) {
return matrix[v1][v2] != 0 ? true : false ;
}
void print() {
for (int i = 0; i < numVertices; ++i) {
cout << i << " : ";
for (int j = 0; j < numVertices; ++j) {
cout << matrix[i][j] << " ";
}
cout << endl;
}
}
~Graph() {
for (int i = 0; i < numVertices; ++i) {
delete[] matrix[i];
}
delete[] matrix;
}
private:
int **matrix;
int numVertices;
};
複製代碼
#include<iostream>
#include<list>
using namespace std;
//有向無權圖
class Graph {
public:
Graph(int numVertices) {
this->numVertices = numVertices;
adjLists = new list<int>[numVertices];
}
void addEdge(int src, int dst) {
adjLists[src].push_back(dst);
}
void removeEdge(int src, int dst) {
adjLists[src].remove(dst);
}
void print() {
for (int i = 0; i < numVertices; ++i) {
cout << i << " : ";
for (auto it = adjLists[i].begin(); it != adjLists[i].end(); ++it) {
cout << *it << " ";
}
cout << endl;
}
}
~Graph() {
delete[] adjLists;
}
private:
list<int> *adjLists;
int numVertices;
};
複製代碼
遍歷分兩種,深度優先與廣度優先。在遍歷時結點有兩種狀態:已訪問、未訪問,這樣若是一個結點在遍歷過程當中已訪問的話就能夠避免再次訪問。算法
深度優先算法的過程以下:數據結構
void depthFirstSearch(int vertex) {
bool visited[this->numVertices];
for (auto i = 0; i < this->numVertices; ++i) {
visited[i] = false;
}
stack<int> m_stack;
m_stack.push(vertex);
while (!m_stack.empty()) {
auto v = m_stack.top();
if (visited[v]) {
m_stack.pop();
continue;
}
visit(v);
visited[v] = true;
m_stack.pop();
for (auto it = this->adjLists[v].begin(); it != this->adjLists[v].end(); ++ it) {
if (!visited[*it]) {
m_stack.push(*it);
}
}
}
}
複製代碼
廣度優先遍歷的步驟以下:ui
void breadthFirstSearch(int vertex) {
bool visited[this->numVertices];
for (auto i = 0; i < this->numVertices; ++i) {
visited[i] = false;
}
queue<int> m_queue;
m_queue.push(vertex);
while(!m_queue.empty()) {
auto v = m_queue.front();
if (visited[v]) {
m_queue.pop();
continue;
}
visit(v);
visited[v] = true;
m_queue.pop();
for (auto it = this->adjLists[v].begin(); it != this->adjLists[v].end(); ++it) {
if (!visited[*it]) {
m_queue.push(*it);
}
}
}
}
複製代碼
可關注公衆號: this