《数据结构与算法那》第七次课实验内容
图及图的遍历(下)
实验目的:
- 熟悉图的两种存储结构:邻接矩阵和邻接链表。
- 掌握在图的邻接表存储结构上的遍历算法的实现。
实验内容:
- 在已经开发好的c++类adjacencyGraph中,添加两个成员函数,BFSpanningTree和DFSspanningTree分别输出该图的广度优先生成树和深度优先生成树。
- 在已经开发好的c++类linkedGraph中,添加两个成员函数,BFSpanningTree和DFSpanningTree分别输出该图的广度优先生成树和深度优先生成树。
- 两个存储方式任选其一完成。
江米条想说的话:
(用的是临界数组,这个题链表比矩阵更简单,矩阵都会了,还怕链表该干什么)
这次的代码和上次的代码几乎一样,就多了两个函数而已。没看明白的看我写的《数据结构与算法》第六次去。。。。
下面我给大家讲一下这两个算法:BFS(广度优先)和DFS(深度优先)
广度优先BFS (你们记住Breadth就行):
简单地说:广度的意思就是一层一层的遍历。
看图:
从A点开始访问顺序:A->B->D->E->C->F->G
广度遍历是:
1:访问A
2:访问B,D,E(B,D,E都是A的邻接点,按照顺序访问)
3:访问C(访问B的邻接点C,访问完了C点之后,开始从D,E找)
4:访问F(因为D的邻接点没有,所以从B,D,E中的E点开始找E的下一个,即F)
5:访问G(访问F的下一个G)
6:G点之后没有了,往上找发现F也没未访问的子节点了,在往上也发现:E也没有未访问的子节点了(B,D,E都没了),所以再往上看A也没有未访问的子节点了,至此,访问结束。
深度优先DFS (你们记住Depth就行):
简单地说:深度就是沿着一条路走到底,走完了再折回来走其他的路。
看图:
从A点开始访问的顺序:A->B->C->D->E->F->G
深度遍历是:(邻接链表)
1: 访问A
2: 访问B(在这个过程里面,A的邻接点有B、D、E,但是B的顺序在前面,所以先访问B)
3: 访问C(在这个过程里面,B的邻接点有C、D,但是C的顺序在前面,所以先访问C)
4: 访问D(C之后没邻接点了,所以往上倒一层,找B的另一个邻接点D)
5: 访问E(D之后没邻接点了,所以往上倒一层,B之后的点都被访问了,再往上倒一层,找A的另一个邻接点E)
6: 访问F(E的下一个是F)
7: 访问G(F的下一个是G)
8: G访问没了,往上倒一层到了F,F的邻接点都被访问了,再往上倒一层到了E,E的邻接点都被访问了,再再往上倒一层到了A,A的邻接点也都被访问了,至此,访问结束
头文件:
#include<iostream>
using namespace std;
class adjacencyGraph
{
public:
adjacencyGraph(int n, int e);
void setElement(int n, int value);
int getIndex(int value);
void insertEdge(int vertex1, int vertex2);
void eraseEdge(int vertex1, int vertex2);
void BFSpanningTree(int v);
void DFSpanningTree(int v);
void dfs(int v);
void outputGraph();
private:
int **matrix;
int *element;
int numberOfVertices;
int numberOfEdges;
int *reach = new int[numberOfVertices];
int count = 0;
};
adjacencyGraph::adjacencyGraph(int n, int e)
{
numberOfVertices = n;
numberOfEdges = e;
matrix = new int *[numberOfVertices];
for (int i = 0; i < numberOfVertices; i++)
matrix[i] = new int[numberOfVertices];
for (int i = 0; i < numberOfVertices; i++)
for (int j = 0; j < numberOfVertices; j++)
matrix[i][j] = 0;
element = new int[numberOfVertices];
}
void adjacencyGraph::setElement(int n, int value)
{
element[n - 1] = value;
}
int adjacencyGraph::getIndex(int value)
{
for (int i = 0; i < numberOfVertices; i++)
if (element[i] == value)
return i;
}
void adjacencyGraph::insertEdge(int vertex1, int vertex2)
{
matrix[vertex1][vertex2] = 1;
matrix[vertex2][vertex1] = 1;
}
void adjacencyGraph::eraseEdge(int vertex1, int vertex2)
{
matrix[vertex1][vertex2] = 0;
matrix[vertex2][vertex1] = 0;
}
void adjacencyGraph::BFSpanningTree(int v)
{
int l = 0, r = 1;
for (int i = 0; i < numberOfVertices; i++)
reach[i] = NULL;
reach[0] = v;
while (reach[numberOfVertices - 1] == NULL)
{
int tl = l, tr = r;
l = r;
for (tl; tl < tr; tl++)
{
int index = getIndex(reach[tl]);
for (int j = 0; j < numberOfVertices; j++)
if (matrix[index][j] == 1)
{
int k;
for (k = 0; k < r; k++)
if (element[j] == reach[k])
break;
if (k == r)
{
reach[r] = element[j];
r++;
}
}
}
}
cout << "这个无向图的广度优先搜索为:";
for (int i = 0; i < numberOfVertices; i++)
cout << reach[i];
cout << endl;
}
void adjacencyGraph::DFSpanningTree(int v)
{
for (int i = 0; i < numberOfVertices; i++)
reach[i] = NULL;
reach[0] = v;
dfs(v);
for (int i = 0; i < numberOfVertices; i++)
cout << reach[i];
cout << endl;
}
void adjacencyGraph::dfs(int v)
{
int index = getIndex(v);
for (int i = 0; i < numberOfVertices; i++)
//if(reach[i]==0)
if (matrix[index][i] == 1)
{
int k;
for (k = 0; k < count; k++)
if (element[i] == reach[k])
break;
if (k == count)
{
bool t = false;//设置这个变量是为了防止出现从父结点再次遍历到子节点的情况,比如两个父结点都连着一个子节点。
for(int a=0;a<count+1;a++)
if (element[i] == reach[a])
{
t = true;
break;
}
if (t == false)
{
count++;
reach[count] = element[i];
dfs(reach[count]);
}
}
}
}
void adjacencyGraph::outputGraph()
{
for (int i = 0; i < numberOfVertices; i++)
{
for (int j = 0; j < numberOfVertices; j++)
cout << matrix[i][j] << " ";
cout << endl;
}
}
主函数:
#include<iostream>
#include"adjacencyGraph.h"
using namespace std;
int main()
{
adjacencyGraph *temp;
temp = new adjacencyGraph(0, 0);
while (1)
{
cout << "1.用邻接矩阵描述一个无向图" << endl;
cout << "2.删除无向图的一条边" << endl;
cout << "3.对无向图广度优先搜索"<<endl;
cout<< "4.对无向图深度优先搜索"<<endl;
cout << "0.退出" << endl;
int option;
cin >> option;
switch (option)
{
case 1:
{
int n, e;
cout << "请输入顶点的数目:";
cin >> n;
cout << "请输入边的数目:";
cin >> e;
temp = new adjacencyGraph(n, e);
for (int i = 1; i <= n; i++)
{
int value;
cout << "请输入第" << i << "个顶点";
cin >> value;
temp->setElement(i, value);
}
for (int i = 1; i <= e; i++)
{
int value1, value2;
cout << "请输入第" << i << "条边的第1个顶点:";
cin >> value1;
cout << "请输入第" << i << "条边的第2个顶点:";
cin >> value2;
temp->insertEdge(temp->getIndex(value1), temp->getIndex(value2));
}
temp->outputGraph();
}
break;
case 2:
{
int value1, value2;
cout << "请输入要删除边的第一个顶点:";
cin >> value1;
cout << "请输入要删除边的第二个顶点:";
cin >> value2;
temp->eraseEdge(temp->getIndex(value1), temp->getIndex(value2));
temp->outputGraph();
}
break;
case 3:
{
int v;
cout<< "请输入搜索的起点值:";
cin>>v;
temp->BFSpanningTree(v);
}
break;
case 4:
{
int v;
cout << "请输入搜索的起点值:";
cin >> v;
temp->DFSpanningTree(v);
}
break;
case 0:
return 0;
default:
break;
}
}
}