数据结构实验–图及其应用
(代码有一些纰漏 仅供自己后期修改保存用)
数据结构上机实验
题目:设计并验证如下算法:
带权图采用邻接表表示,实现无向图的广度优先搜索BFS与有向图的深度优先搜索DFS。
#define MAX_VERTEX_NUM 20 //图的邻接表存储表示
typedef struct ArcNode{
int adjvex; //该弧所指向的顶点的位置
struct ArcNode *nextarc; //指向下一条弧的指针
InfoType *info; //该弧相关信息的指针
}ArcNode;
typedef struct VNode {
VertexType data; //顶点信息
ArcNode *firstarc; //指向第一条依附该顶点弧的指针
}VNode,AdjList[MAX_VERTEX_NUM]
Typedef struct {
AdjList vertices;
int vexnum,arcnum; //图的当前顶点数和弧数
int kind; //图的种类标志
}ALGraph;
实现代码如下
//Queue.h头文件
#define QUEUE_INIT_SIZE 100
#define QUEUE_INCREASE_SIZE 10
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW 0
typedef struct SqQueue{
QElemType *base; //空间基指针
int front;//队头元素数组下标
int tail;//队尾元素数组下标
}*Queue;
Status InitQueue(Queue); //初始化结构体指针S 返回一个空队列 Q
Status DestroyQueue(Queue ); //销毁非空队列 Q
Status ClearQueue(Queue ); //把非空队列 Q置为空队列
Status QueueEmpty(SqQueue Q); //判断Q是否为空队列
Status FullQueue(SqQueue ) ; //判断是否是满队列
Status QueueLength(SqQueue , int *) ; //返回队列Q的元素个数
Status DeQueue(Queue , QElemType *); //删除Q中队首元素
Status EnQueue(Queue , QElemType ); //队尾 将元素E排入队Q中
Status QueueTraverse(SqQueue ); //从队首到队尾依次输出队列中每个元素
Status InitQueue(Queue Q){ //初始化结构体指针Q 返回一个空队列Q
Q->base = (QElemType *)malloc( sizeof(QElemType )* QUEUE_INIT_SIZE );
if(!Q->base ) exit(OVERFLOW);
Q->front = Q->tail = 0;
return OK;
}
Status DestroyQueue(Queue Q){ //销毁非空队列Q
free(Q->base);
Q->base = NULL;
return OK;
}
Status ClearQueue(Queue Q){ //把非空队列 Q置为空队列
while(Q->front != Q->tail)
Q->front = (Q->front+1)%QUEUE_INIT_SIZE;
return OK;
}
Status QueueEmpty(SqQueue Q){
if(Q.front == Q.tail ) return TRUE;
else return FALSE;
}
Status FullQueue(SqQueue Q){
if( Q.front == (Q.tail + 1) % QUEUE_INIT_SIZE )
return TRUE;
else return FALSE;
}
Status QueueLength(SqQueue Q, int *length){
*length = 0;//设置为0
while(Q.base[Q.front] != Q.base[Q.tail] ) {
Q.front = (Q.front + 1)% QUEUE_INIT_SIZE;
(*length) ++;
}
return OK;
}
Status EnQueue(Queue Q, QElemType e){
if( (Q->tail+1)%QUEUE_INIT_SIZE ==Q->front)return ERROR;//队列满
Q->base[Q->tail ] = e;
Q->tail =(Q->tail+1)%QUEUE_INIT_SIZE;
return OK;
}
Status DeQueue(Queue Q, QElemType *e){
if(QueueEmpty(*Q) ) return ERROR;
else{
*e = Q->base[Q->front];
Q->front = (Q->front + 1)% QUEUE_INIT_SIZE;
return OK;
}
}
Status QueueTraverse(SqQueue Q){
if(Q.front == Q.tail){
printf("Empty Queue");
return ERROR;
}//队列空
while(Q.front!= Q.tail ){
printf("%5d",Q.base[Q.front]) ;
Q.front = (Q.front+1)% QUEUE_INIT_SIZE;
}
return OK;
}
Graph.h头文件(为方便起见将Graph.cpp文件写在.h文件中)
#ifndef STDIO_H
#define STDIO_H
#include "stdio.h"
#endif
#ifndef STDLIB_H
#define STDLIB_H
#include "stdlib.h"
#endif
#ifndef QUEUE_H
#define QUEUE_H
typedef int QElemType;
#include "Queue.h"
#endif
#ifndef GRAPH_STRUCT_H
#define GRAPH_STRUCT_H
#define MAX_VERTEX_NUM 20 //图的邻接表存储表示
//弧
typedef struct ArcNode{
int adjvex; //该弧所指向的顶点的位置(数组下标)
struct ArcNode *nextarc; //指向下一条弧的指针
InfoType info; //权重
}ArcNode;
//顶点
typedef struct VNode {
VertexType data; //顶点信息
ArcNode *firstarc; //指向第一条依附该顶点的弧 的指针(对有向图而言 是以该顶点为尾的弧)
}AdjList[MAX_VERTEX_NUM];
//总图
typedef struct ALGraph{
AdjList vertices;
int vexnum; //图的当前顶点数
int arcnum; //图的当前弧数
int kind; //图标志
}ALGraph;
#endif
#define TRUE 1
#define FALSE 0
#define ERROR 0
#define OVERFLOW 0
/*基本操作*/
void CreateGraph(ALGraph *G);//创建图 其中V是图的顶点集 VR是顶点间的关系
void DestroyGraph(ALGraph *G); //销毁图G
int LocateVex(ALGraph G,VNode u); //G中存在顶点u则返回其在图中位置 否则返回其他信息
int FirstAdjVex(ALGraph G, int v,ArcNode **w) ;//返回顶点v的第一个邻接顶点 若无临接顶点 则返回"空"
int NextAdjVex(ALGraph G, int v, ArcNode **p);//返回v相对于w的下一个邻接顶点 若是w已经是最后一个邻接顶点 则返回"空"
void DFSTraverse(ALGraph G); //深度优先遍历图
void DFS(ALGraph G,int v, int *visited);
void BFSTraverse(ALGraph G); //广度优先遍历图
/*各基本操作实现*/
/*图创建*/
void CreateGraph(ALGraph *G){
int i, k, v, w;
ArcNode *p=NULL, *q = NULL;
printf("\n依次输入图的结点个数,边的个数:");
scanf("%d%d",& G->vexnum, & G->arcnum);
for(i = 1; i<=G->vexnum; i++){//创建顶点
printf("\n请输入%d号顶点信息:",i);
rewind(stdin);
scanf("%c",& G->vertices[i].data);
G->vertices[i].firstarc = NULL;
}
for(k=1; k<=G->arcnum; k++){
p = (ArcNode*)malloc(sizeof(ArcNode));
scanf("%d%d", &v, &w);
p->adjvex = w;
scanf("%d", & p->info);
p->nextarc = NULL;
q = G->vertices[v].firstarc;
G->vertices[v].firstarc = p;
p->nextarc = q;//头插法
}//for
G->kind = 0;//默认
}//CreateGraph()
/*图销毁*/
void DestroyGraph(ALGraph *G){
int i;
ArcNode *p= NULL, *q = NULL;
//释放所有边结点
for(i =1 ; i<=G->vexnum; i++){
while( G->vertices[i].firstarc){
p = G->vertices[i].firstarc;
q = p->nextarc;
free(p);
G->vertices[i].firstarc = q;
}//释放一个结点发出的所有边
}//for
G->arcnum = 0;
G->vexnum = 0;
}
/*图的遍历DFS(递归)*/
void DFSTraverse(ALGraph G){
int v;
int visited[MAX_VERTEX_NUM]={0};
for(v=1; v<=G.vexnum; v++){
if(!visited[v]) DFS(G, v, visited);//对未访问的顶点调用DFS
}
}
void DFS(ALGraph G,int v, int *visited){
int w;
ArcNode *p=NULL;
visited[v] = 1;
printf(" %c ",G.vertices[v].data);
for(w = FirstAdjVex(G,v,&p); w>0; w=NextAdjVex(G, v, &p))
if(!visited[w]) DFS(G, w, visited);
}
/*图的遍历BFS*/
void BFSTraverse(ALGraph G){
int visited[MAX_VERTEX_NUM] = {0};
int v, w, u;
SqQueue Q;
ArcNode *p =NULL;
InitQueue(&Q);
for(v = 1; v<=G.vexnum; v++ ){
if(!visited[v]){
visited[v] = 1;//标志已访问过
printf(" %c ",G.vertices[v].data);
EnQueue(&Q, v);
while(!QueueEmpty(Q)){
DeQueue(&Q, &u);
for(w=FirstAdjVex(G, u, &p); w>0; w = NextAdjVex(G, u , &p) ){
if(!visited[w]){
visited[w] = 1;
printf(" %c ",G.vertices[w].data);
EnQueue(&Q, w);
}
}//for
}//while
}//if
}//for
}//BFSTraverse()
int LocateVex(ALGraph G,VNode u){
int i = 1;
for(i =G.vexnum ; i ; i--){
if(G.vertices[i].data == u.data)
break;
}
return i; //若为0则没找到
}
int FirstAdjVex(ALGraph G, int v,ArcNode **w){
if (!(*w=G.vertices[v].firstarc ) ) return 0;
return (*w)->adjvex;
}
int NextAdjVex(ALGraph G, int v,ArcNode **p)//返回v相对于w的下一个邻接顶点 若是w已经是最后一个邻接顶点 则返回"空"
{
if(!(*p)->nextarc) return 0;
int t=(*p)->nextarc->adjvex;
*p=(*p)->nextarc;
return t;
}