第1关:创建无向图的邻接表表示,并求无向图(邻接表表示)中某个顶点的度。
相关知识
下面给出了一种基于链接表的实现方案:
#include <iostream>
#include <stdio.h>
using namespace std;
#define MVNum 100 /*预定义图的最大顶点数*/
typedef char VerTexType; /*顶点信息数据类型*/
typedef struct ArcNode /*边表结点*/
{
int adjvex; /*邻接点*/
struct ArcNode *nextarc; //指向下一条边的指针
} ArcNode;
typedef struct VNode /*头结点类型*/
{
VerTexType data; /*顶点信息*/
ArcNode *firstarc; /*邻接链表头指针*/
} VNode, AdjList[MVNum];
typedef struct /*邻接表类型*/
{
AdjList vertices; /*存放头结点的顺序表*/
int vexnum, arcnum; /*图的顶点数与边数*/
} ALGraph;
void Create(ALGraph &G); //建立无向图的邻接表,G是邻接表引用变量;
void Print(ALGraph G); //输出邻接表存储结构
int Degree(ALGraph G,VerTexType v); /* 返回以邻接表为存储结构的无向图G中顶点v的度,若该顶点不存在返回-1 */
void Destroy(ALGraph &G);//销毁图的邻接表
// 实现函数
int LocateVex(ALGraph G, VerTexType v) {
for (int i = 0; i < G.vexnum; ++i) {
if (G.vertices[i].data == v) {
return i;
}
}
return -1; // 顶点不存在
}
//完成以下两个函数的编写
/**************void Create(ALGraph &G) //建立无向图的邻接表********/
/******************begin **********/
void Create(ALGraph &G) {
cin >> G.vexnum >> G.arcnum;
for (int i = 0; i < G.vexnum; i++) {
cin >> G.vertices[i].data;
G.vertices[i].firstarc = NULL;
}
for (int k = 0; k < G.arcnum; k++) {
int i, j;
cin >> i >> j;
ArcNode *p = new ArcNode;
p->adjvex = j;
p->nextarc = G.vertices[i].firstarc;
G.vertices[i].firstarc = p;
// 因为是无向图,需要为j也添加一个指向i的边
ArcNode *q = new ArcNode;
q->adjvex = i;
q->nextarc = G.vertices[j].firstarc;
G.vertices[j].firstarc = q;
}
}
/******************end **********/
/**************int Degree(ALGraph G,VerTexType v)********/
/******************begin **********/
int Degree(ALGraph G, VerTexType v) {
int i = LocateVex(G, v);
if (i == -1) {
// cout << "the vertex " << v << " is not found!" << endl;
return -1;
}
int degree = 0;
ArcNode *p = G.vertices[i].firstarc;
while (p) {
degree++;
p = p->nextarc;
}
// cout << "the degree of vertex " << v << " is " << degree <<endl;
return degree;
}
/******************end **********/
int main()
{
ALGraph G;
VerTexType v;
int i,N,d;
Create(G);
Print(G);
cin>>N;
while(N--)
{
cin>>v;
d=Degree(G,v);
if (d==-1) printf("the vertex is not found!\n");
else printf("the degree of vertex is %d\n",d);
}
getchar();
Destroy(G);
return 0;
}
void Print(ALGraph G)
{
ArcNode *p;
int i;
for (i=0; i<G.vexnum; i++)
{
cout<<G.vertices[i].data;
p=G.vertices[i].firstarc; //指向邻接表的首节点
while (p)
{
cout<<"-->"<<p->adjvex;
p=p->nextarc;
}
cout<<endl;
}
}
void Destroy(ALGraph &G)//销毁图的邻接表
{
ArcNode *p,*q;
int i;
for(i=0; i<G.vexnum; i++)
{
p=G.vertices[i].firstarc;
while (p)
{
q=p;
p=p->nextarc;
delete q;
}
G.vertices[i].firstarc=NULL;
}
}
第2关:无向图(邻接表表示)的基本运算(BFS 和 DFS)
#include <iostream>
using namespace std;
#define MVNum 100 /*预定义图的最大顶点数*/
typedef char VerTexType; /*顶点信息数据类型*/
typedef struct ArcNode /*边表结点*/
{
int adjvex; /*邻接点*/
struct ArcNode *nextarc; //指向下一条边的指针
} ArcNode;
typedef struct VNode /*头结点类型*/
{
VerTexType data; /*顶点信息*/
ArcNode *firstarc; /*邻接链表头指针*/
} VNode, AdjList[MVNum];
typedef struct /*邻接表类型*/
{
AdjList vertices; /*存放头结点的顺序表*/
int vexnum, arcnum; /*图的顶点数与边数*/
} ALGraph;
int visited[MVNum]; /*全局标志向量,标记第i个顶点是否被访问*/
void Create(ALGraph &G); //建立无向图的邻接表,G是邻接表引用变量;
void Print(ALGraph G); //输出邻接表存储结构
void BFS(ALGraph G, int i); /*从顶点i出发广度优先遍历图G的连通分量*/
int BFSTraverse(ALGraph G); //对图G进行广度优先遍历,并返回连通分量个数
void DFS(ALGraph G,int i);/*从顶点i出发深度优先遍历图G的连通分量*/
int DFSTraverse(ALGraph G);//对图G进行深度优先遍历,并返回连通分量个数
void Destroy(ALGraph &G);//销毁图的邻接表
//补充完成以下函数
//对图G进行广度优先遍历,要求从第0号结点开始,并返回连通分量个数
#include <queue>
// BFS辅助函数
void BFS(ALGraph G, int i) {
queue<int> q;
visited[i] = 1;
cout << G.vertices[i].data << ",";
q.push(i);
while (!q.empty()) {
int u = q.front();
q.pop();
for (ArcNode *p = G.vertices[u].firstarc; p; p = p->nextarc) {
int v = p->adjvex;
if (!visited[v]) {
visited[v] = 1;
cout << G.vertices[v].data << ",";
q.push(v);
}
}
}
}
// BFS遍历
int BFSTraverse(ALGraph G) {
int i, cnt = 0;
for (i = 0; i < G.vexnum; i++)
visited[i] = 0;
for (i = 0; i < G.vexnum; i++) {
if (!visited[i]) {
cout<<endl;
BFS(G, i);
cnt++;
}
}
return cnt;
}
// DFS辅助函数
void DFS(ALGraph G, int i) {
visited[i] = 1;
cout << G.vertices[i].data << ",";
for (ArcNode *p = G.vertices[i].firstarc; p; p = p->nextarc) {
int v = p->adjvex;
if (!visited[v]) {
DFS(G, v);
}
}
}
// DFS遍历
int DFSTraverse(ALGraph G) {
int i, cnt = 0;
for (i = 0; i < G.vexnum; i++)
visited[i] = 0;
for (i = 0; i < G.vexnum; i++) {
if (!visited[i]) {
cout<<endl;
DFS(G, i);
cnt++;
}
}
return cnt;
}
int main()
{
ALGraph G;
int N;
Create(G);
Print(G);
//广度优先遍历图G
cout<<"\nBFS sequence :";
N=BFSTraverse(G);
cout<<"\nConnected Component :"<<N;
//深度优先遍历图G
cout<<"\nDFS sequence :";
N=DFSTraverse(G);
cout<<"\nConnected Component :"<<N<<endl;
Destroy(G);
return 0;
}
void Print(ALGraph G)
{
ArcNode *p;
int i;
for (i=0; i<G.vexnum; i++)
{
cout<<G.vertices[i].data;
p=G.vertices[i].firstarc; //指向邻接表的首节点
while (p)
{
cout<<"-->"<<p->adjvex;
p=p->nextarc;
}
cout<<endl;
}
}
void Create(ALGraph &G) //建立无向图的邻接表
{
// 该部分代码由于涉及第一关,故省略
}
void Destroy(ALGraph &G)//销毁图的邻接表
{
ArcNode *p,*q;
int i;
for(i=0; i<G.vexnum; i++)
{
p=G.vertices[i].firstarc;
while (p)
{
q=p;
p=p->nextarc;
delete q;
}
G.vertices[i].firstarc=NULL;
}
}
第3关:编程题:求解两个动物之间通信最少翻译问题(广度优先遍历算法应用)
题目内容:
据美国动物分类学家欧内斯特-迈尔推算,世界上有超过100万种动物,各种动物有自己的语言。假设动物 A 只能与动物 B 通信,所以,动物 A、C 之间通信需要动物 B 来当翻译。问两个动物之间项目通信至少需要多少个翻译。
#include <iostream>
#include <vector>
using namespace std;
struct Node {
int num;
int length;
};
struct QueueNode {
Node item;
QueueNode* next;
};
struct Queue {
QueueNode* front;
QueueNode* rear;
};
bool is_queue_empty(Queue* Q) {
return Q->front == NULL;
}
void enQueue(Queue* &Q, Node item) {
QueueNode* p = new QueueNode;
p->item = item;
p->next = NULL;
if (is_queue_empty(Q)) {
Q->front = Q->rear = p;
} else {
Q->rear->next = p;
Q->rear = p;
}
}
bool deQueue(Queue* &Q, Node &item) {
if (is_queue_empty(Q))
return false;
QueueNode* p = Q->front;
item = p->item;
Q->front = Q->front->next;
if (Q->front == NULL) {
Q->rear = NULL;
}
delete p;
return true;
}
void init_queue(Queue* &Q) {
Q = new Queue;
Q->front = Q->rear = NULL;
}
void destroy_queue(Queue* &Q) {
while (!is_queue_empty(Q)) {
Node item;
deQueue(Q, item);
}
delete Q;
}
int bfs(bool** graph, int n, int animal_1, int animal_2) {
int best = -1;
Queue* Q = NULL;
init_queue(Q);
Node e, item;
e.num = animal_1;
e.length = 0;
enQueue(Q, e);
vector<bool> visited(n, false);
visited[animal_1] = true;
while (!is_queue_empty(Q)) {
deQueue(Q, item);
if (item.num == animal_2) {
if (best == -1 || item.length < best) {
best = item.length;
}
}
for (int i = 0; i < n; i++) {
if (graph[item.num][i] == 1 && !visited[i]) {
e.num = i;
e.length = item.length + 1;
enQueue(Q, e);
visited[i] = true;
}
}
}
destroy_queue(Q);
if (best == 0 || best == 1) {
return 0;
} else if (best != -1) {
return best - 1;
} else {
return -1;
}
}
int main() {
int n, e, animal1, animal2, k, a, b;
cin >> n >> e;
bool** graph = new bool*[n];
for (int i = 0; i < n; i++) {
graph[i] = new bool[n]();
}
for (int i = 0; i < e; i++) {
cin >> animal1 >> animal2;
graph[animal1][animal2] = true;
graph[animal2][animal1] = true;
}
cin >> k;
int* result = new int[k];
for (int i = 0; i < k; i++) {
cin >> a >> b;
result[i] = bfs(graph, n, a, b);
}
for (int i = 0; i < k; i++) {
cout << result[i] << endl;
}
for (int i = 0; i < n; i++) {
delete[] graph[i];
}
delete[] graph;
delete[] result;
return 0;
}