数据结构 实验四

实验四 图的基本操作及应用

一、实验目的

1、使学生可以巩固所学的有关图的基本知识。

2、熟练掌握图的存储结构。

3、熟练掌握图的两种遍历算法。

4、掌握如何应用图解决各种实际问题。

二、实验内容

  本次实验需完成两个题目,题目一必做,题目二或三选择其中一道。

三、实验准备知识

CreatGraph(&G, V, VR);// 按定义(V, VR) 构造图

DestroyGraph(&G);// 销毁图

LocateVex(G, u);  // 若G中存在顶点u,则返回该顶点在图中“位置”;否则返回其它信息。

GetVex(G, v);       // 返回 v 的值

PutVex(&G, v, value);// 对 v 赋值value。

FirstAdjVex(G, v); // 返回 v 的“第一个邻接点” 。若该顶点在 G 中没有邻接点,则返回“空”

NextAdjVex(G, v, w); // 返回 v 的(相对于 w 的) “下一个邻接点”。若 w 是 v 的最后一个邻接点,则返回“空”。

InsertVex(&G, v); //在图G中增添新顶点v。

DeleteVex(&G, v);// 删除G中顶点v及其相关的弧

DFSTraverse(G, v, Visit()); //从顶点v起深度优先遍历图G,并对每个顶点调用函数Visit一次且仅一次。

BFSTraverse(G, v, Visit()); //从顶点v起广度优先遍历图G,并对每个顶点调用函数Visit一次且仅一次。

四、实验内容

题目一: 图的遍历

[问题描述]

  对给定图,实现图的深度优先遍历和广度优先遍历。

[基本要求]

   以邻接表为存储结构,实现连通无向图的深度优先和广度优先遍历。以用户指定的结点为起点,分别输出每种遍历下的结点访问序列。

【测试数据】
  由学生依据软件工程的测试技术自己确定。

 [源代码](加注释)

#include<stdio.h>
#include<malloc.h>
#include <stdlib.h>
#include<iostream>
using namespace std;
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef int Status;
typedef int Boolean;
typedef char TElemType;
#define MVNum 100     //最大顶点数 
typedef char VerTexType;  //顶点类型
typedef int Bool;
bool visited[MVNum];
typedef char OtherInfo;

typedef struct ArcNode  //边结点 
{
	int adjvex;   //该边所指向的顶点的位置 
	struct ArcNode *nextarc;  //指向下一条边的指针 
	OtherInfo info;   //和边相关的信息 
}ArcNode; 
typedef struct VNode    //顶点信息 
{
	VerTexType data;
	ArcNode *firstarc;    //指向第一条依附该顶点的边的指针 
}VNode,AdjList[MVNum];    //AdjList表示邻接表类型 
typedef struct      //邻接表 
{
	AdjList vertices;
	int vexnum,arcnum;   //图的当前顶点数和边数 
}ALGraph;

typedef struct QNode
{
	int data;
	struct QNode *next;
 } QNode,*QueuePtr;
 typedef struct
 {
 	QueuePtr front;  //队头指针 
 	QueuePtr rear;   //队尾指针 
 }LinkQueue;
 
int InitQueue (LinkQueue &Q)//构造一个空队列 
{    
    Q.front=Q.rear=new QNode;  //生成新结点作为头结点,队头和队尾指针指向此结点 
  	Q.front->next==NULL;      //头结点的指针域置空 
 	return OK;
}
 int EnQueue (LinkQueue &Q,int e)//插入元素为e为Q的新的队尾元素 
{
	QueuePtr p=new QNode;   
 	p->data=e;
 	Q.rear->next=p;
 	Q.rear=p;
 	p->next=NULL;
 	return OK;
}
 int DeQueue(LinkQueue &Q,int &e)//删除Q的队头元素,用e返回其值 
{
	if(Q.front==Q.rear)
		return -1;
	if(Q.front->next==Q.rear)
	{
		e=Q.front->next->data;
		free(Q.front->next);
		Q.front->next=NULL;
		Q.rear=Q.front;
	}
	else{
        QNode *p=Q.front->next;
		e=p->data;
		Q.front->next=p->next;	
	}
	return 0; 
}

int LocateVex(ALGraph &G,VerTexType u)
 {//存在则返回u在顶点表中的下标;否则返回-1
   int i;
   for(i=0;i<G.vexnum;++i)
     if(u==G.vertices[i].data)
       return i;
   //return -1;
 }

Status CreateUDG(ALGraph &G)  //采用邻接表表示法,创建无向图G
{  
	printf("请输入顶点和边数:");//输入总顶点数,总边数
    cin>>G.vexnum>>G.arcnum;  
	printf("请输入顶点的值:");             	 
    for(int i = 0; i<G.vexnum; ++i){          	//输入各点,构造表头结点表 
       cin>> G.vertices[i].data;           	//输入顶点值 
       G.vertices[i].firstarc=NULL;       	//初始化表头结点的指针域为NULL 
    }
    for(int k = 0; k<G.arcnum;++k){        		//输入各边,构造邻接表 
       int i,j;
	   char v1,v2;
       ArcNode *p1 ;
       ArcNode *p2 ;
	   printf("请输入(Vi,Vj)对应的顶点:");
	   cin>>v1>>v2;                 			//输入一条边依附的两个顶点 
	   i = LocateVex(G,v1);  j = LocateVex(G,v2);    
       p1=new ArcNode;			//生成一个新结点new ArcNode并把p1指向新结点 
	   p1->adjvex=j;			//p1所指向的顶点v2的位置 
	   p1->nextarc=G.vertices[i].firstarc;			//将新结点p1指向v1的邻接点 
       G.vertices[i].firstarc=p1;					//将v1指向p1 
	   p2=new ArcNode; 		//生成一个新结点new ArcNode并把p2指向新结点 
	   p2->adjvex=i;			//把新结点的adjvex赋值为v1顶点的位置 
	   p2->nextarc=G.vertices[j].firstarc;		
       G.vertices[j].firstarc=p2;
    } 
    return OK; 
}

void DFS_AL(ALGraph G, char v)	//图G为邻接表类型
{        	 
    cout<<v;      		//访问第v个顶点
    int x=LocateVex(G,v); 
	visited[x] = true;        
    ArcNode *p= G.vertices[x].firstarc;     //p指向v的边链表的第一个边结点 
    int w; 
	while(p!=NULL){              	//边结点非空 
        w=p->adjvex;
		if(!visited[w])  DFS_AL(G,G.vertices[w].data); 	//如果w未访问,则递归调用DFS 
        p=p->nextarc;                	//p指向下一个边结点 
    }
} 

void BFS(ALGraph G,char v)
{
    int x=LocateVex(G,v); 
	LinkQueue Q;
	InitQueue(Q);         //辅助队列Q初始化,置空 
	EnQueue(Q,x);         //v进队 
	while(Q.front!=Q.rear)
	{
		 DeQueue(Q,x);    //对头元素出队 
		 if(!visited[x])  //x为未访问的邻接顶点 
		 {
		 	visited[x]=true;//访问x,并标记已被访问 
		 	cout<<G.vertices[x].data;
		 	ArcNode *p=G.vertices[x].firstarc;
            while(p!=NULL)
    		{
		        if(!visited[p->adjvex])
		        EnQueue(Q,p->adjvex);
		        p=p->nextarc; 
		    }	 
        }   
	}
 } 

int main(){
    ALGraph G ;  
    char v;
    CreateUDG(G); 
    printf("请输入出发顶点:");
 	cin>>v;
 	for(int i=0;i<G.vexnum;i++)
    visited[i]=false;
    printf("图的深度优先遍历为: ");
    DFS_AL(G,v); 
    printf("\n");
    for(int i=0;i<G.vexnum;i++)
    visited[i]=false;
    printf("图的广度优先遍历为: ");
    BFS(G,v); 
    printf("\n");
    return 0;
}

 [测试数据] 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值