一、实验内容:
假设有一张城市地图,图中的顶点为城市,无向边代表两个城市间的连通关系,边上的权为在这两个城市之间修建高速公路的造价,研究后发现,这个地图有一个特点,即任一对城市都是连通的。现在的问题是,要修建若干高速公路把所有城市联系起来,问如何设计可使得工程的总造价最少。
要求:
1、 创建带有n(顶点个数由用户输入)个顶点的带权无向图。可以是邻接矩阵或者邻接表存储。
2、 使用深度或广度优先搜索对图中顶点进行遍历输出。
3、 采用普里姆算法或克鲁斯卡尔算法求出使总造价最少的子图,即最小生成树。(选做题)
二、实验代码
//(1)图.h文件
#pragma once
#include <stdio.h>
#include<stdlib.h>
#define OK 1
#define TRUE 1
#define ERROR -1
#define FALSE 0
#define Status int
#define QElemType int
#define MAX_VERTEX_NUM 8 /*顶点最大个数*/
#define VertexType char /*顶点元素类型*/
//202056228杨丽花
typedef struct ArcNode
{
int adjvex; //顶点编号
struct ArcNode* nextarc;
int weight; /*边的权*/
}ArcNode; /*表结点*/
typedef struct VNode
{
VertexType data;
ArcNode* firstarc;
}VNode/*头结点*/, AdjList[MAX_VERTEX_NUM];
typedef struct
{
AdjList vertices;
int vexnum, arcnum;/*顶点的实际数,边的实际数*/
}ALGraph;
void create_link(ALGraph* G);//建立图的邻接表
void visit(ALGraph G);// 输出邻接表
int FirstAdjVex(ALGraph G, int v);//在图G中寻找第v个顶点的第一个邻接顶点
int NextAdjVex(ALGraph G, int v, int u);//在图G中寻找第v个顶点的相对于u的下一个邻接顶点
void DFS(ALGraph G, int i);// 采用邻接表存储实现无向图的深度优先递归遍历
void DFSTraverse(ALGraph G);
void BFSTraverse(ALGraph G);
//后序会用到队列,定义队列及相关操作
typedef struct QNode {
QElemType data;
struct QNode* next;
}QNode,*QueuePtr;
typedef struct {
QueuePtr front;//队头指针
QueuePtr rear;//队尾指针
}LinkQueue;
//(2)图.cpp源文件
#include"图.h"
#include<iostream>
using namespace std;
//202056228杨丽花
enum BOOlean { False, True };
BOOlean visited[MAX_VERTEX_NUM]; //全局变量——访问标志数组
Status InitQueue(LinkQueue& Q) {
//构造一个空队列
Q.front = Q.rear = new QNode;//生成新结点作为头结点,队头和队尾指针指向此指针
Q.front->next = NULL;
return OK;
}
Status EnQueue(LinkQueue& Q, QElemType e) {
//插入元素e为Q的新的队尾元素
QNode *p;
p = new QNode;
p->data = e;
p->next = NULL;
Q.rear->next = p;//将新结点插入到队尾
Q.rear = p;//修改队尾指针
return OK;
}
Status DeQueue(LinkQueue& Q, QElemType &e) {
//删除队头元素,用e返回ERROR
if (Q.front == Q.rear) return ERROR;
QNode *p;
p = Q.front->next;
/*e = p->next;*/
Q.front->next = p->next;
if (Q.rear == p) Q.rear = Q.front;
delete p;//释放原来队头元素的空间
return OK;
}
//建立图的邻接表
void create_link(ALGraph* G)
{
int i, j;
ArcNode* s;
cout<<"请依次输入顶点数、边数:"<<endl;
cin>> G->vexnum>>G->arcnum;
for (i = 0;i < G->vexnum;i++)
{
G->vertices[i].data = 'A' + i;
G->vertices[i].firstarc = NULL;
}
for (i = 0;i < G->vexnum;)
{
cout<<"请输入顶点的数组坐标(若退出,请输入-1):"<<endl;
cin>>i;
if (i == -1) break;
cout << "请输入顶点所指向下一个顶点的数组坐标:" << endl;
cin >> j;
s = (ArcNode*)malloc(sizeof(ArcNode));
s->adjvex = j;
s->nextarc = G->vertices[i].firstarc;
G->vertices[i].firstarc = s;
}
}
// 输出邻接表
void visit(ALGraph G)
{
int i;
ArcNode* p;
cout<< "NO"<<"\t"<<"data" << "\t" << "adjvexs of arcs"<<endl;
for (i = 0;i < G.vexnum;i++)
{
cout<< i << "\t" << G.vertices[i].data << "\t";
for (p = G.vertices[i].firstarc;p;p = p->nextarc)
cout<< p->adjvex<<"\t";
cout<<endl;
}
}
//在图G中寻找第v个顶点的第一个邻接顶点
int FirstAdjVex(ALGraph G, int v)
{
if (!G.vertices[v].firstarc) return 0;
else return(G.vertices[v].firstarc->adjvex);
}
//在图G中寻找第v个顶点的相对于u的下一个邻接顶点
int NextAdjVex(ALGraph G, int v, int u)
{
ArcNode* p;
p = G.vertices[v].firstarc;
while (p->adjvex != u) p = p->nextarc; //在顶点v的弧链中找到顶点u
if (p->nextarc == NULL) return 0; //若已是最后一个顶点,返回0
else return(p->nextarc->adjvex); //返回下一个邻接顶点的序号
}
//采用邻接表存储实现无向图的深度优先递归遍历
void DFS(ALGraph G, int i)
{
int w;
visited[i] = True; //访问第i个顶点
cout<<i<<"\t";
for (w = FirstAdjVex(G, i);w;w = NextAdjVex(G, i, w))
if (!visited[w]) DFS(G, w); //对尚未访问的邻接顶点w调用DFS
}
void DFSTraverse(ALGraph G)
{
int i=0;
cout << "DFSTraverse:" << endl;
for (i = 0;i < G.vexnum;i++) visited[i] = False; //访问标志数组初始化
for (i = 0;i < G.vexnum;i++)
if (!visited[i]) DFS(G, i); //对尚未访问的顶点调用DFS
}
//按广度优先非递归的遍历图G,使用辅助队列Q和访问标志数组visited
void BFSTraverse(ALGraph G)
{
int i, u=0, w;
LinkQueue Q;
cout<<"BFSTreverse:"<<endl;
for (i = 0;i < G.vexnum;i++) visited[i] = False; //访问标志数组初始化
InitQueue(Q); //初始化队列
for (i = 0;i < G.vexnum;i++)
if (!visited[i])
{
visited[i] = True; //访问顶点i
cout << i<<"\t";
EnQueue(Q, i); //将序号i入队列
while (!(Q.front == Q.rear)) //若队列不空,继续
{
DeQueue(Q, u); //将队头元素出队列并置为u
for (w = FirstAdjVex(G, u);w;w = NextAdjVex(G, u, w))
if (!visited[w]) //对u的尚未访问的邻接顶点w进行访问并入队列
{
visited[w] = True;
cout<<w;
EnQueue(Q, w);
}
}
}
}
//(3)main.cpp文件
// 实验四.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include"图.h"
#include<iostream>
using namespace std;
//202056228杨丽花
/*
1、 创建带有n(顶点个数由用户输入)个顶点的带权无向图。可以是邻接矩阵或者邻接表存储。
2、 使用深度或广度优先搜索对图中顶点进行遍历输出。
3、 采用普里姆算法或克鲁斯卡尔算法求出使总造价最少的子图,即最小生成树。(选做题)
*/
int main()
{
ALGraph *G = (ALGraph*)malloc(sizeof(ALGraph));
create_link(G);
visit(*G);
cout << "深度遍历:" << endl;
DFSTraverse(*G);
cout << endl<< "广度遍历:" << endl;
BFSTraverse(*G);
system("pause");
}