目的要求
1.掌握图的存储策略及其存储实现。
2.掌握图的深度、广度优先遍历的算法策略及其程序实现。
3.掌握图的常见算法策略及其程序实现。
实验内容
1.键入或随机生成数据,建立一个有向图的邻接表。
2.输出该邻接表。
3.以有向图邻接表为基础上,计算各顶点的度并输出。
4.以有向图邻接表为基础,输出其拓扑排序序列。
5.采用邻接表存储,实现无向图的非递归DFS遍历。
6.采用邻接表存储,实现无向图的BFS优先遍历。
7.判断无向图任意两个顶点间是否有路径,若有则输出路径上的顶点序列。
8.在主函数中设计一个简单的菜单,调用上述算法。
实验说明
1.类型定义(邻接表存储)
const int MAX_ VERTEX_NUM=8; // 顶点的最大个数
typedef struct ArcNode;
{
int adjvex ;
struct ArcNode *nextarc ;
int weight; // 边的权
} ArcNode ; // 表结点
typedef VertexType int; // 顶点元素类型
typedef struct VNode
{
int degree, indegree; // 顶点的度,入度
VertexType data;
ArcNode *firstarc;
} VNode /头结点/, AdjList[MAX_VERTEX_NUM] ;
typedef struct
{
AdjList vertices;
int vexnum, arcnum; // 顶点的实际数,边的实际数
} ALGraph ;
2.上述类型定义可根据情况适当调整。
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <string.h>
#include <map>
#include <set>
#include <queue>
#include <deque>
#include <list>
#include <bitset>
#include <stack>
#include <stdlib.h>
using namespace std;
#define MAXSIZE 20
int indegree[MAXSIZE], outdegree[MAXSIZE];//
typedef char InfoType;//邻接表存储结构类型
typedef char VertexType;//节点数据类型
typedef struct Arcnode//表结点
{
int adjvex;//存放结点的下表
Arcnode* nextarc;//指向下一条弧的指针域
InfoType* info;//该弧相关信息的指针
}Arcnode;
typedef struct VNode//头结点
{
VertexType data;
Arcnode* firstarc;
}VNode, AdjList[MAXSIZE];
typedef struct
{
AdjList vertices;
int vexnum;//顶点数
int arcnum;//边数
int kind;//0为无向图,1为有向图
}ALGraph;
int visited[MAXSIZE];//辅助数组,标志是否访问过
void Create_Graph(ALGraph& G)//
{
char ch1, ch2;
int k1, k2;
cout << "输入顶点数和边数" << endl;
cin >> G.vexnum >> G.arcnum;//
cout << "输入图的顶点" << endl;
for (int i = 1; i <= G.vexnum; i++)
{
getchar();
cin >> G.vertices[i].data;
G.vertices[i].firstarc = NULL;
}
cout << "请输入边" << endl;
for (int i = 1; i <= G.arcnum; i++)
{
getchar();
cin >> ch1 >> ch2;
for (int j = 1; j <= G.arcnum; j++)
if (G.vertices[j].data == ch1)
{
k1 = j;
break;
}
for (int j = 1; j <= G.arcnum; j++)
if (G.vertices[j].data == ch2)
{
k2 = j;
break;
}
Arcnode* p;//把新申请的表结点前插
p = new Arcnode();
p->adjvex = k2;
p->nextarc = G.vertices[k1].firstarc;
G.vertices[k1].firstarc = p;
}
}
void Output_Graph(ALGraph G)
{
for (int i = 1; i <= G.vexnum; i++)
{
cout << G.vertices[i].data << ' ';
Arcnode* p;
p = G.vertices[i].firstarc;
while (p)
{
cout << G.vertices[p->adjvex].data << ' ';
p = p->nextarc;
}
cout << endl;
}
}
void Degree_Query(ALGraph G)//询问入度和出度
{
Arcnode* p = NULL;
for (int i = 1; i <= G.vexnum; i++)
{
p = G.vertices[i].firstarc;
while (p)
{
//indegree[i]++;
indegree[p->adjvex]++;
outdegree[i]++;
p = p->nextarc;
}
}
}
void dfs(ALGraph G, VertexType x)
{
int k;
for (int i = 1; i <= G.vexnum; i++)//先找到结点X
{
if (G.vertices[i].data == x)
{
k = i;
break;
}
}
cout << G.vertices[k].data << ' ';
visited[k] = 1;
Arcnode* p;
p = G.vertices[k].firstarc;
while (p)//如果该结点的第一临接点存在
{
if (visited[p->adjvex] == 0)
{
dfs(G, G.vertices[p->adjvex].data);
}
p = p->nextarc;
}
}
void bfs(ALGraph G, VertexType x)
{
struct
{
Arcnode* Q[MAXSIZE];
int front, rear;
}QQ;
Arcnode* p;
QQ.front = QQ.rear = 0;//init
int k;
for (int i = 1; i <= G.vexnum; i++)
{
if (G.vertices[i].data == x)
{
k = i;
break;
}
}
visited[k] = 1;
cout << G.vertices[k].data << ' ';
QQ.rear = (QQ.rear + 1) % MAXSIZE;
QQ.Q[QQ.rear] = G.vertices[k].firstarc;
while (QQ.front != QQ.rear)
{
QQ.front = (QQ.front + 1) % MAXSIZE;
p = QQ.Q[QQ.front];
while (p)
{
if (!visited[p->adjvex])
{
visited[p->adjvex] = 1;
cout << G.vertices[p->adjvex].data << " ";
QQ.rear = (QQ.rear + 1) % MAXSIZE;
QQ.Q[QQ.rear] = G.vertices[p->adjvex].firstarc;
}
p = p->nextarc;
}
}
}
int Topological_Sort(ALGraph G)
{
int s[MAXSIZE];//stack
int top = 0;
for (int i = 1; i <= G.vexnum; i++)
{
if (indegree[i] == 0)
{
top++;
s[top] = i;
}
}
int ans = 0;
int i = 1;
Arcnode* p = NULL;
while (top)
{
i = s[top--];
cout << i << ' ' << G.vertices[i].data << endl;
ans++;
for (p = G.vertices[i].firstarc; p; p = p->nextarc)
{
int k = p->adjvex;
indegree[k]--;
if (!indegree[k])
{
s[++top] = k;
}
}
}
if (ans < G.vexnum)
return -1;
return 1;
}
void menu()
{
printf("*********有向图邻接表*********\n");
printf("1.输出邻接表\n");
printf("2.计算各顶点的度\n");
printf("3.输出拓扑排序序列\n");
printf("4.DFS遍历\n");
printf("5.BFS优先遍历\n");
printf("6.判断无向图任意两个顶点间是否有路径,若有则输出路径上的顶点序列\n");
printf("0.退出\n\n");
}
int main()
{
ALGraph G;
char chx;
Create_Graph(G);//
int choice;
int flag = 0;//拓扑排序
menu();
while (1)
{
printf("选择你的操作:");
scanf_s("%d", &choice);
switch (choice)
{
case 1:
cout << "邻接表为:" << endl;
Output_Graph(G);
break;
case 2:
memset(indegree, 0, sizeof(indegree));
memset(outdegree, 0, sizeof(outdegree));
Degree_Query(G);
cout << "邻接表的度为" << endl;
for (int i = 1; i <= G.vexnum; i++)//输出入度
cout << indegree[i] << ' ';
cout << endl;
for (int i = 1; i <= G.vexnum; i++)//输出出度
cout << outdegree[i] << ' ';
cout << endl;
break;
case 3:
memset(visited, 0, sizeof(visited));
cout << "请输入深搜开始的结点:(以0结束)" << endl;
cin >> chx;
cout << chx << "开始的深搜顺序为:";
dfs(G, chx);
cout << endl;
memset(visited, 0, sizeof(visited));
printf("\n");
break;
case 4:
cout << "请输入广搜开始的结点:(以0结束)" << endl;
cin >> chx;
cout << chx << "开始的广搜顺序为";
bfs(G, chx);
cout << endl;
memset(visited, 0, sizeof(visited));
printf("\n");
break;
case 5:
cout << "拓扑排序" << endl;
flag = Topological_Sort(G);
cout << endl;
if (flag == -1)
cout << "不能进行拓扑排序" << endl;
else
cout << "已经进行拓扑排序" << endl;
printf("\n");
break;
case 6:
//没实现
printf("\n");
break;
case 7:
break;
case 0:
return 0;
default:
printf("输入错误,请重新输入\n");
}
}
return 0;
}
运行结果与输出示例