数据结构 实验四 图 邻接矩阵 邻接表 深度或广度优先搜索

一、实验内容:

假设有一张城市地图,图中的顶点为城市,无向边代表两个城市间的连通关系,边上的权为在这两个城市之间修建高速公路的造价,研究后发现,这个地图有一个特点,即任一对城市都是连通的。现在的问题是,要修建若干高速公路把所有城市联系起来,问如何设计可使得工程的总造价最少。
要求:
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");
}

 

三、运行结果:

在这里插入图片描述

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

华不在意

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值