实验要求:
- 创建图类,存储结构使用邻接矩阵。
- 输入图的节点数n(小于10个)、边数m,节点分别用1-n代表。
- 采用“起始节点,终止节点,权值”输入图的m条边,创建图。
- 输出从节点1开始的BFS遍历,在遍历过程中,如有多个可以选择的节点,则优先选择编号较小的节点。
- 输出从节点1开始的DFS遍历,在遍历过程中,如有多个可以选择的节点,则优先选择编号较小的节点。
- 输出从第1节点到第n节点最短路径的长度,如果没有路经,输出0。
(输出格式如下图所示)
实验难点:
- 自己定制图类(因为懒,所以定制图类是能省则省,能不写就不写,嘿嘿);
- 寻找最短路径的Dijkstra算法(也可以用深度优先搜索算法来实现,但是因为学习了Dijkstra算法,所以用来练习,难点);
- 控制输出格式,尤其是逗号,下面的算法用了commaFlag来实现逗号输出控制(讨巧实现);
- 对于STL中的list和queue的使用(也可以用自己写的,但是我懒,所以用现成的,嘿嘿);
- 要时刻注意一些细节,比如邻接数组的边界,new的数组的初始化和释放等等。
//my solution
#include <iostream>
#include <queue>
#include <list>
#include <algorithm>
#include <iterator>
#define label 1//reached label
#define noPredecessor 0//no predecessor
#define maxCapacity 11
using namespace std;
//weighted graph(desribed by ajacency matrix)
template<class T>
class Graph
{
public:
Graph(int = 0, T = (T)0);
~Graph() { clearMatrix(); };
void creatGraph(int);
void insertEdge(int, int, T);
//both bfs and dfs are traverrsal from vertex 1
void bfs() const;
void dfs() const;
void realDfs(int, bool*, bool) const;
void shortestPath() const;
void clearMatrix();
protected:
int vertexNum;
int edgeNum;
T** ajacencyMatrix;
T noEdge;
};
template<class T>
Graph<T>::Graph(int vn,T theNoEdge)
{
vertexNum = vn;
edgeNum = 0;
noEdge = theNoEdge;
//creat ajacency matrix
ajacencyMatrix = new T* [vn + 1];
for (int i = 0; i <= vn; i++) ajacencyMatrix[i] = new T[vn + 1];
//initialize
for (int j = 1; j <= vertexNum; j++)
fill(ajacencyMatrix[j], ajacencyMatrix[j] + vertexNum + 1, noEdge);
}
template<class T>
void Graph<T>::insertEdge(int v1, int v2, T w)
{
ajacencyMatrix[v1][v2] = w;
ajacencyMatrix[v2][v1] = w;
edgeNum++;
}
template<class T>
void Graph<T>::creatGraph(int en)
{
char c;
int v1, v2, w;
//insert
for (int k = 1; k <= en; k++)
{
cin >> v1 >> c >> v2 >> c >> w;
insertEdge(v1, v2, w);
}
}
template<class T>
void Graph<T>::bfs() const
{
int start = 1;
//commaFlag is used to control output of comma.
bool commaFlag = true;
queue<int> q;
//isReached is used to judge whether a vertex has been reached
//value 0(false) means NOT REACHED and value 1(true) means REACHED
bool* isReached=new bool[maxCapacity]();
isReached[start] = label;
q.push(start);
while (!q.empty())
{
int v = q.front();
q.pop();
//output bfs traversal result
if (commaFlag)
{
cout << v;
commaFlag = false;
}
else cout<< ',' << v;
for (int i = 1; i <= vertexNum; i++)
{
if (ajacencyMatrix[v][i] != noEdge && !isReached[i])
{
q.push(i);
isReached[i] = label;
}
}
}
delete[]isReached;
}
template<class T>
void Graph<T>::dfs() const
{
//commaFlag is used to control output of comma.
bool commaFlag = true;
bool* isReached = new bool[maxCapacity]();
realDfs(1, isReached, commaFlag);
delete[]isReached;
}
template<class T>
void Graph<T>::realDfs(int vertex, bool* isReached, bool commaFlag) const
{
//output dfs traversal result
if (commaFlag)
{
cout << vertex;
commaFlag = false;
}
else cout << "," << vertex;
isReached[vertex] = label;
for (int i = 1; i <= vertexNum; i++)
if (ajacencyMatrix[vertex][i] != noEdge && !isReached[i])
realDfs(i,isReached,commaFlag);
}
//Dijkstra Funtion
template<class T>
void Graph<T>::shortestPath() const
{
int source = 1, distination = vertexNum;
int* previous=new int[maxCapacity];
T* presentDistance=new T[maxCapacity];
list<int> newReach;
//initialize presentDistance
for (int x = 0; x < maxCapacity; x++) presentDistance[x] = noEdge;
for (int i = 1; i <= distination; i++)
{
presentDistance[i] = ajacencyMatrix[source][i];
if (presentDistance[i] != noEdge)
{
previous[i] = source;
newReach.push_front(i);
}
else previous[i] = noPredecessor;
}
previous[source] = -1;//source has no predecessor
while (!newReach.empty())
{
list<int>::iterator itNewReach = newReach.begin();
list<int>::iterator end = newReach.end();
list<int>::iterator itMin = newReach.begin();
int vMin = *itNewReach;
for (; itNewReach != end; itNewReach++)
{
if (presentDistance[vMin] > presentDistance[*itNewReach])
{
vMin = *itNewReach;
itMin = itNewReach;
}
}
newReach.erase(itMin);
for (int k = 1; k <= distination; k++)
{
if (ajacencyMatrix[vMin][k] != noEdge &&
(previous[k] == noPredecessor || presentDistance[k] > presentDistance[vMin] + ajacencyMatrix[vMin][k]))
{
presentDistance[k] = presentDistance[vMin] + ajacencyMatrix[vMin][k];
if (previous[k] == noPredecessor) newReach.push_front(k);
previous[k] = vMin;
}
}
}
if (presentDistance[distination] != noEdge) cout << presentDistance[distination] << endl;
else cout << "0" << endl;
delete[]presentDistance;
delete[]previous;
}
template<class T>
void Graph<T>::clearMatrix()
{
for (int i = 0; i <= vertexNum; i++) delete[]ajacencyMatrix[i];
delete[]ajacencyMatrix;
}
int main()
{
int n, m;
char c;
cout << "Input" << endl;
cin >> n >> c >> m;
Graph<int> g(n);
g.creatGraph(m);
cout << "Output" << endl;
g.bfs(); cout << endl;
g.dfs(); cout << endl;
g.shortestPath();
cout << "End" << endl;
system("pause");
return 0;
}
实验体会:
最后一次数据结构实验了,但考试月又来了