图是一种比线性结构和树形结构更为复杂的数据结构。在这种非线性结构中,结点之间的关系可以是任意的
线性结构:唯一前驱,唯一后继,反映一种线性关系。
树形结构:唯一前驱,多个后继,反映一种层次关系。
图结构:不限制前驱和后继的个数,反映一种网状结构。
所以线性表和树可以看作是受限图。
图的存储:图可以用相邻矩阵(邻接矩阵)表示
图的周游:
深度优先周游:图的深度优先搜索(DFS)类似于树的先根次序周游,特点是尽可能先对纵深方向进行搜索
广度优先周游:广度优先搜索的过程类似于树的按层次次序周游。可以使用FIFO队列保存已访问过的顶点,从而使得先访问的顶点的邻接点在下一轮被优先访问到。在搜索过程中,每访问到一个顶点后将其入队,当队头元素出队使将其未被访问的邻接点入队,每个顶点只入队一次
例:对下图进行周游
相邻矩阵(邻接矩阵):
0,1,0,0,0,0,0,
0,0,1,1,0,0,0,
1,0,0,0,0,0,0,
1,0,1,0,0,0,0,
0,0,0,0,0,1,1,
0,1,0,0,0,0,1,
0,0,0,1,0,0,0,
深度优先周游结果:V0->V1->V2->V3->V4->V5->V6
广度优先周游结果:V0->V1->V2->V3->V4->V5->V6
代码及说明如下:
编译器:VisualStudio2017
代码文件结构:
头文件:
Edge.h
#pragma once
template<class T>
class Edge//边类
{
public:
int from;//边的始点
int to;//边的终点
int weight;//边的权值
Edge();//缺省构造函数
Edge(int from, int to, int weight);//给定参数的构造函数
};
//**********一场过云雨**********
Graph.h
#pragma once
#include"Edge.cpp"
template<class T>
class Graph
{
public:
static const int UNVISITED = 0;//未访问的顶点设置为0
static const int VISITED = 1;//已访问的顶点设置为1
int numVertex;//图中顶点的个数
int numEdge;//图中边的条数
int *Mark;//标记图的顶点是否被访问过
int *Indegree;//存放图中顶点的入度
Graph(int numVertex=1);//图的构造函数
~Graph();//析构函数
int VerticcesNum();//返回图的顶点个数
int EdgesNum();//返回图的边数
bool isEdge(Edge<T> oneEdge);//oneEdge是否为边
void resetMark();//所有顶点设置成未访问状态
int FromVertex(Edge<T> oneEdge);//返回oneEdge的起点
int ToVertex(Edge<T> oneEdge);//返回oneEdge的终点
int Weight(Edge<T> oneEdge);//返回oneEdge的权
virtual Edge<T> FirstEdge(int oneVertex) = 0;
virtual Edge<T> NextEdge(Edge<T> preEdge) = 0;
virtual void setEdge(int from, int to, int weight) = 0;
virtual void delEdge(int from, int to) = 0;
};
//**********一场过云雨**********
Graphm.h
#pragma once
//#include"Edge.h"
#include"Graph.cpp"
template<class T>
class Graphm : public Graph<T>
{
private:
int **matrix;
public:
Graphm(int numVertex);
~Graphm();
Edge<T> FirstEdge(int oneVertex);
Edge<T> NextEdge(Edge<T> preEdge);
void setEdge(int from, int to, int weight);
void delEdge(int from, int to);
void IniGraphm(Graphm* Graphm, int* pWArray2D);
void DFS(Graph<T>&G, int v);
void BFS(Graph<T>&G, int v);
void Visit(Graph<T>&G, int v);
void Travel(Graph<T>&G, int startVertex = 0, int travelType = 0);
void TravelByDFS(Graph<T>&G, int startVertex = 0);
};
//**********一场过云雨**********
源文件:
Edge.cpp
#include "Edge.h"
template<class T>
inline Edge<T>::Edge()
{
from = -1;
to = -1;
weight = 0;
}
template<class T>
Edge<T>::Edge(int from, int to, int weight)
{
this->from = from;
this->to = to;
this->weight = weight;
}
//**********一场过云雨**********
Graph.cpp
#include "Graph.h"
template<class T>
inline Graph<T>::Graph(int numVertex)
{
this->numVertex = numVertex;
this->numEdge = 0;
this->Indegree = new int [numVertex];
this->Mark = new int[numVertex];
for (int i = 0; i < this->numVertex; i++) {
this->Mark[i] = this->UNVISITED;
this->Indegree[i] = 0;
}
}
template<class T>
Graph<T>::~Graph()
{
delete[]this->Mark;
delete[]this->Indegree;
}
template<class T>
int Graph<T>::VerticcesNum()
{
return numVertex;
}
template<class T>
int Graph<T>::EdgesNum()
{
return numEdge;
}
template<class T>
bool Graph<T>::isEdge(Edge<T> oneEdge)
{
if (oneEdge.weight > 0 && oneEdge.from >= 0 && oneEdge.to >= 0)
return true;
else return false;
}
template<class T>
void Graph<T>::resetMark()
{
for (int i = 0; i < this->numVertex; i++) {
this->Mark[i] = this->UNVISITED;
}
}
template<class T>
int Graph<T>::FromVertex(Edge<T> oneEdge)
{
return oneEdge.from;
}
template<class T>
int Graph<T>::ToVertex(Edge<T> oneEdge)
{
return oneEdge.to;
}
template<class T>
int Graph<T>::Weight(Edge<T> oneEdge)
{
return oneEdge.weight;
}
/*template<class T>
const int Graph<T>::UNVISITED = 0;
template<class T>
const int Graph<T>::VISITED = 1;*/
//**********一场过云雨**********
Graphm.cpp
#include "Graphm.h"
#include<iostream>
#include<queue>
using namespace std;
template<class T>
inline Graphm<T>::Graphm(int numVertex) :Graph<T>(numVertex)
{
int i, j;
this->matrix = (int **)new int *[numVertex];
for (i = 0; i < numVertex; i++) {
this->matrix[i] = new int[numVertex];
}
for (i = 0; i < numVertex; i++) {
for (j = 0; j < this->numVertex; j++) {
this->matrix[i][j] = 0;
}
}
}
template<class T>
Graphm<T>::~Graphm()
{
for (int i = 0; i < this->numVertex; i++) {
delete[] matrix[i];
}
delete [] matrix;
}
template<class T>
Edge<T> Graphm<T>::FirstEdge(int oneVertex)
{
Edge<T> myEdge;
myEdge.from = oneVertex;
for (int i = 0; i < this->numVertex; i++) {
if (matrix[oneVertex][i] > 0) {
myEdge.to = i;
myEdge.weight = this->matrix[oneVertex][i];
break;
}
}
return myEdge;
}
template<class T>
Edge<T> Graphm<T>::NextEdge(Edge<T> preEdge)
{
Edge<T> myEdge;
myEdge.from = preEdge.from;
if (preEdge.to < this->numVertex) {
for (int i = preEdge.to + 1; i < this->numVertex; i++) {
if (matrix[preEdge.from][i] > 0) {
myEdge.to = i;
myEdge.weight = matrix[preEdge.from][i];
break;
}
}
}
return myEdge;
}
template<class T>
void Graphm<T>::setEdge(int from, int to, int weight)
{
if (matrix[from][to] <= 0) {
this->numEdge++;
this->Indegree[to]++;
}
matrix[from][to] = weight;
}
template<class T>
void Graphm<T>::delEdge(int from, int to)
{
if (matrix[from][to] > 0) {
this->numEdge--;
this->Indegree[to]--;
}
matrix[from][to] = 0;
}
template<class T>
void Graphm<T>::IniGraphm(Graphm * Graphm, int * pWArray2D)
{
int N = this->numVertex;
int array_i_j = 0;
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
array_i_j = *(pWArray2D + i * N + j);
if (array_i_j > 0)
Graphm->setEdge(i, j, array_i_j);
}
}
}
template<class T>
void Graphm<T>::DFS(Graph<T>& G, int v)
{
G.Mark[v] = Graphm<T>::VISITED;
this->Visit(G, v);
for (Edge<T> e = G.FirstEdge(v); G.isEdge(e); e = G.NextEdge(e)) {
if (G.Mark[e.to] == Graphm<T>::UNVISITED)
this->DFS(G, e.to);
}
}
template<class T>
void Graphm<T>::BFS(Graph<T>& G, int v)
{
using std::queue;
queue<int> Q;
this->Visit(G, v);
G.Mark[v] =Graphm<T>::VISITED;
Q.push(v);
while (!Q.empty()) {
int u = Q.front();
Q.pop();
for(Edge<T> e=G.FirstEdge(u);G.isEdge(e);e=G.NextEdge(e))
if (G.Mark[e.to] == Graphm<T>::UNVISITED) {
this->Visit(G, e.to);
G.Mark[e.to] = Graphm<T>::VISITED;
Q.push(e.to);
}
}
}
template<class T>
void Graphm<T>::Visit(Graph<T>& G, int v)
{
cout << v <<"->";
}
template<class T>
void Graphm<T>::Travel(Graph<T>& G, int startVertex, int travelType)
{
for (int i = startVertex, n = 0; n < this->numVertex; i++, n++) {
i%=this->numVertex;
if (Graphm<T>::UNVISITED == G.Mark[i]) {
switch (travelType)
{
case 0:
DFS(G, i);
break;
case 1:
BFS(G, i);
break;
default:
cout << "error" << endl;
break;
}
}
}
}
template<class T>
void Graphm<T>::TravelByDFS(Graph<T>& G, int startVertex)
{
for (int i = startVertex, n = 0; n < this->numVertex; i++, n++) {
i %= this->numVertex;
if (Graphm<T>::UNVISITED == G.Mark[i]) {
this->DFS(G, i);
}
}
}
//**********一场过云雨**********
DS07_02.cpp(主函数)
// DS07_02.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include"Graphm.cpp"
using namespace std;
int main()
{
const int N = 7;
int start1 = 0;
int A[N][N] = {
0,1,0,0,0,0,0,
0,0,1,1,0,0,0,
1,0,0,0,0,0,0,
1,0,1,0,0,0,0,
0,0,0,0,0,1,1,
0,1,0,0,0,0,1,
0,0,0,1,0,0,0,
};
Graphm<int> aGraphm(N);
aGraphm.IniGraphm(&aGraphm, (int*)A);
/*cout << "DFS:\t\t";
aGraphm.DFS(aGraphm, start1);
cout << endl;
aGraphm.resetMark();
cout << "BFS:\t\t";
aGraphm.BFS(aGraphm, start1);
cout << endl;*/
aGraphm.resetMark();
cout << "DFS Travel:\t";
aGraphm.Travel(aGraphm, start1, 0);
cout << endl;
aGraphm.resetMark();
cout << "BFS Travel:\t";
aGraphm.Travel(aGraphm, start1, 1);
cout << endl;
return 0;
}
//**********一场过云雨**********
运行结果: