用邻接矩阵实现无向图(深度遍历、广度遍历)
【输入输出】 第一行输入顶点的个数n,第二行输入n个顶点的值。第三行输入边的个数m,下面m行输入边的起点和终点坐标。最后一行输入遍历的起始点的值。从指定的顶点出发无法访问到的顶点不用遍历。
【测试数据】
8
A B C D E F G H
9
0 1
0 2
1 3
1 4
2 5
2 6
3 7
4 7
5 6
A
输出
【代码】
/**使用邻接矩阵存储图
无向图
*/
#include<iostream>
#include<limits.h>
#define MAX_V_NUM 20 //顶点的最大个数
using namespace std;
/**图类*/
template <class T>
class MGraph
{
private:
T vertex[MAX_V_NUM];//图元素的一维数组
int arc[MAX_V_NUM][MAX_V_NUM];//图的邻接矩阵,二维数组
int vexNum, arcNum;//元素个数,边的个数
public:
MGraph()//构造函数,根据类型创建邻接矩阵
{
cin >> vexNum;
for (int i = 0; i < vexNum; i++)
{
cin >> vertex[i]; //输入图元素的一维数组
}
for (int i = 0; i < vexNum; i++)
{
for (int j = 0; j < vexNum; j++)
arc[i][j] = 0;
}
cin >> arcNum;
for (int i = 0; i < arcNum; i++)
{
int start, end;
cin >> start >> end;
arc[start][end] = 1;
arc[end][start] = 1;
}
}
~MGraph( ) {};
void DFSTraverse(int v);//深度遍历
void BFSTraverse(int v);//广度遍历
int getIndex(T vertex1);//获得指定顶点的下标
};
//深度遍历,递归
template <class T>
void MGraph<T>::DFSTraverse(int v)
{
static int visited[MAX_V_NUM]={0}; //定义为静态数组
cout<<vertex[v]<<" ";
visited[v]=1;
for(int j=0;j<vexNum;j++)
{
if(arc[v][j]==1&&visited[j]==0) //有边并且没被访问过
{
DFSTraverse(j);
}
}
}
//广度遍历,队列
template <class T>
void MGraph<T>::BFSTraverse(int v)
{
bool visited[MAX_V_NUM] = {false}; // 标记顶点是否被访问过
int queue[MAX_V_NUM]; // 用于存储待访问的顶点
int front = 0, rear = 0;
visited[v] = true;
cout << vertex[v] << " ";
queue[rear++] = v;
while (front != rear)
{
int cur = queue[front++];
for (int i = 0; i < vexNum; i++)
{
if (arc[cur][i] == 1 && !visited[i])
{
visited[i] = true;
cout << vertex[i] << " ";
queue[rear++] = i;
}
}
}
}
template <class T>
/**获取对应值的下标*/
int MGraph<T>::getIndex(T vertex1)
{
int i;
for(i=0;i<vexNum;i++)
{
if(vertex[i]==vertex1)
{
return i;
}
}
return -1;//找不到对应的顶点
}
int main()
{
MGraph<char> graph;
//graph.printMG();
//graph.printMatrix();
char v;
//cout<<"\n请输入遍历的起始顶点";
cin>>v;
cout<<"-----------------\n深度优先遍历的结果:";
graph.DFSTraverse(graph.getIndex(v));
cout<<"\n-----------------\n广度优先遍历的结果:";
graph.BFSTraverse(graph.getIndex(v));
//cout<<"\n-----------------\n"<<v<<"的度:"<<graph.getDegree(v);
return 0;
}
用邻接表实现有向网(深度遍历、广度遍历)
【输入输出】 第一行输入顶点的个数n,第二行输入n个顶点的值,为字符型。第三行输入边的个数m,下面m行输入边的起点下标、终点下标和权值(int型)。最后一行输入遍历的起始点,用点的值表示。从指定的起始点出发无法访问到的顶点不用进行遍历。
采用头插法插入链表。
【测试数据】
8
A B C D E F G H
8
0 1 1
0 2 2
1 3 3
4 1 4
3 5 5
5 4 6
2 6 7
2 7 8
A
输出
【代码】
/**邻接表表示有向网*/
#include<iostream>
#include<queue>
#define MAX_V_NUM 20//最大顶点个数
using namespace std;
/**边表的结构体*/
struct ArcNode
{
int adjvex;//邻接点在数组中的位置下标
struct ArcNode* nextArc;//指向下一个邻接点的指针
int weight;//权值,网才有权值
};
/**顶点的结构体*/
template <class T>
struct VNode
{
T vertex;//顶点的数据域
ArcNode* firstArc;//指向邻接点的指针
};
/**邻接表类*/
template <class T>
class ALGraph
{
private:
VNode<T> AdjList[MAX_V_NUM];//顶点表的数组
int vexNum, arcNum;//记录图中顶点数和边或弧数
bool visited[MAX_V_NUM] = { false }; // 定义visited数组
public:
ALGraph();//构造函数
~ALGraph() {}; //析构函数
int getIndex(T vertex);//获得顶点的下标
void DFSTraverse(int v);
void BFSTraverse(int v);
void createDN();//构造有向网
void setVertex(int index, T value);
void incrementVexNum();
};
template <class T>
ALGraph<T>::ALGraph() {
// 将顶点数和边数初始化为0
vexNum = 0;
arcNum = 0;
// 顶点表的数组初始化
for (int i = 0; i < MAX_V_NUM; i++) {
AdjList[i].firstArc = NULL;
}
}
// 构建有向图
template <class T>
void ALGraph<T>::createDN() {
int u, v, w;
// 输入起点下标,终点下标,权值
cin >> u >> v >> w;
ArcNode* p = new ArcNode; //定义邻接表的p指针
p->adjvex = v; //传入邻接点在数组中的终点位置下标
p->weight = w; //传入对应的权值
// 头插法插入新的数据
p->nextArc = AdjList[u].firstArc;
AdjList[u].firstArc = p;
arcNum++; //边数增加
}
template <class T>
void ALGraph<T>::DFSTraverse(int v) {
visited[v] = true;
cout << AdjList[v].vertex << " ";
for (ArcNode* p = AdjList[v].firstArc; p != NULL; p = p->nextArc) {
int w = p->adjvex;
if (!visited[w]) {
DFSTraverse(w);
}
}
}
//广度遍历
template <class T>
void ALGraph<T>::BFSTraverse(int v) {
queue<int> q;
//visited数组进行初始化
for (int i = 0; i < vexNum; i++)
{
visited[i] = false;
}
visited[v] = true;
q.push(v);
while (!q.empty()) {
int u = q.front();
q.pop();
cout << AdjList[u].vertex << " ";
ArcNode* p = AdjList[u].firstArc;
while (p!=NULL)
{
if (!visited[p->adjvex])//判断顶点是否被访问过,没有的话就进入队列,把它的visited值设置为已访问
{
q.push(p->adjvex);
visited[p->adjvex] = true;
}
p = p->nextArc;//指向下一个结点
}
}
}
//获取顶点的下标
template <class T>
int ALGraph<T>::getIndex(T vertex) { //传入顶点
for (int i = 0; i < vexNum; i++) { //遍历顶点表
if (AdjList[i].vertex == vertex) { //如果顶点表的数据域与传入要查找的顶点相同的话,就返回此时的下标
return i;
}
}
return -1; //如果没找到,就返回-1
}
//更改顶点表的数据域,传入下标和数据
template <class T>
void ALGraph<T>::setVertex(int index, T value) {
if (index >= 0 && index < MAX_V_NUM) {
AdjList[index].vertex = value;
}
}
//vexNum为私有属性,不能直接访问
template <class T>
void ALGraph<T>::incrementVexNum() {
if (vexNum < MAX_V_NUM) {
vexNum++;
}
}
int main()
{
ALGraph<char> graph;
int n, m;
// 输入顶点的个数
cin >> n;
// 输入顶点
for (int i = 0; i < n; i++) {
char v;
cin >> v;
graph.setVertex(i, v);
graph.incrementVexNum();
}
// 输入边的个数
cin >> m;
// 输入边的起点下标,终点下标和权值。
for (int i = 0; i < m; i++) {
graph.createDN();
}
//graph.printALG();
char v;
//cout<<"\n请输入遍历的起始顶点";
cin >> v;
cout << "-----------------\n深度优先遍历的结果:";
graph.DFSTraverse(graph.getIndex(v));
cout << "\n-----------------\n广度优先遍历的结果:";
graph.BFSTraverse(graph.getIndex(v));
return 0;
}