【C++】图的实现及应用

程序实现的功能:

1、编写为从键盘输入的数据建立图的邻接表存储

2、编写图的深度优先遍历程序

3、编写图的广度优先遍历程序

4、设计选择菜单,以选择菜单方式进行操作。

 queue.h:

#define MAXQSIZE 31 
#define qelemtype int
#define OVERFLOW -1
#define OK 1
#define ERROR 0
typedef struct{
	qelemtype *base;//队列基准地址 
	int front;//头部 
	int rear;//尾部 
}sqqueue;
void initqueue(sqqueue *q){       //创建队列
	q->base = (qelemtype *)malloc(MAXQSIZE*sizeof(qelemtype));
	if(!q->base){
		exit(OVERFLOW);
	} 
	q->front = q->rear = 0;
}
int enqueue(sqqueue *q,qelemtype e){  //添加队列节点
	if((q->rear + 1) % MAXQSIZE == q->front){
		return(ERROR);
	}
	q->base[q->rear] = e;
	q->rear = (q->rear + 1) % MAXQSIZE;
	return OK;
}
int dequeue(sqqueue *q,qelemtype *e){   //移出队列节点
	if(q->front == q->rear)
	{
		return ERROR;
	}
	*e = q->base[q->front];
	q->front = (q->front + 1) % MAXQSIZE;
	return OK;
}
int queueempty(sqqueue q){  //判断队列是否为空
	if(q.front == q.rear)
	{
		return OK;
	}
	else 
	{
		return ERROR;
	}
}

 main.cpp

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"queue.h" 
#define VertexType char
#define GraphKind char
//DG,DN,UDG,UDN分别表示 有向图,有向网,无向图,无向网 
typedef struct ArcNode{
	int adjvex;//边节点 
	struct ArcNode *nextarc;//下一个边节点 
}ArcNode;      //邻接表节点 
typedef struct VNode{
	VertexType vexdata;//顶点 
	ArcNode *firstarc;//边 
}VNode;     //邻接表结结构 
typedef struct{
	VNode *vertices;//vertices为vertex的复数,指向顶点【但由于是指针形式,所以可以当作数组基准地址】 
	int vexnum;//定点数 
	int arcnum;//边数 
	GraphKind kind[4];//图的种类 
}ALGraph;     //图结构 

void visit(VNode v){   //打印图节点 
	printf("%c ",v.vexdata);
}
int LocateVex(ALGraph *a,char ch){    //查找图节点 
	int i = 0;//用于for循环 
	for(;i < a->vexnum;++i){//遍历所有节点 
		if(a->vertices[i].vexdata == ch){//如果某个节点数值等于查找值 
			return i;//返回节点序号i 
		}
	}
	exit(-1);//否则返回错误 
}
void CreateGraph(ALGraph *a){        //建图 
	printf("请输入图类,顶点数和边数:");
    scanf("%s",&a->kind[0]);//%[^ ]s表示输入非空字符串,存在kind数组中【4位长度】 
//	getchar();
	scanf("%d%d",&a->vexnum,&a->arcnum);//定点数和边数 
	getchar();
	a->vertices = (VNode*)malloc(a->vexnum * sizeof(VNode));//足够的节点分配空间 
	printf("请输入顶点:");
	int i = 0;//用于for循环 
	for(;i < a->vexnum;++i){//遍历所有节点 来做初始化 
		scanf("%c",&(a->vertices[i].vexdata));
		getchar();
		a->vertices[i].firstarc = NULL;//边先全部设置为null 
	}
	printf("请输入各边:");
	i = 0;//用于for循环 
	for(;i < a->arcnum;++i){//遍历所有边 
		char sv,tv;//两个字符用于接收边 
		scanf("%c%c",&sv,&tv);
		getchar();
		int j = LocateVex(a,sv);//用查找定位到sv节点位置 
		int k = LocateVex(a,tv);//用查找定位到tv节点位置 
		ArcNode *p = (ArcNode*)malloc(sizeof(ArcNode));//创建一个边节点并且分配内存空间 
		//使用头插法 
		p->adjvex = k;//先把边取成k 
		p->nextarc = a->vertices[j].firstarc;//指向首个边节点 
		a->vertices[j].firstarc = p;//再将首个边节点指向p 
		if(a->kind[0] == 'U'&&a->kind[1] == 'D'){//如果是无向图 
			ArcNode *q = (ArcNode*)malloc(sizeof(ArcNode));//创建新节点q,对另一部分做类似操作 
			q->adjvex = j;
			q->nextarc = a->vertices[k].firstarc;
			a->vertices[k].firstarc = q;
		} 
	}
}
void DFS(ALGraph a,int *sign,int v,void (*visit)(VNode v)){   //连通图深度优先遍历 
	sign[v] = 1;//先把当前节点访问成功 
	visit(a.vertices[v]);//访问当前节点 
	ArcNode *p = a.vertices[v].firstarc;//用于for循环 
	for(;p != NULL;p = p->nextarc){//遍历p的所有相连的节点 
		if(!sign[p->adjvex]){//只要未被访问则被重新访问 
			DFS(a,sign,p->adjvex,visit);//传入下一个节点 p->adjvex
		}
	}
} 
void DFSTraverse(ALGraph a,void (*visit)(VNode v)){   //非连通图深度优先遍历
	int sign[a.vexnum];//定义标记数组 
	memset(sign,0,sizeof(sign)); //清空数组 
	int v = 0;
	for(;v < a.vexnum;++v){//遍历全部的节点 
		if(!sign[v]){//如果这个节点还没被标记,则对其进行DFS 
			DFS(a,sign,v,visit);
		}
	}
}
void BFS(ALGraph a,int *sign,int v,sqqueue *q,void (*visit)(VNode v)){   //连通图广度优先遍历 
	sign[v] = 1;//先把当前节点访问成功 
	visit(a.vertices[v]);//访问当前节点 
	enqueue(q,v);//当前节点入队 
	for(;queueempty(*q) != 1;){//只要队列不空 
		int w;//定义w用来储存出队的元素 
		dequeue(q,&w);//出队 
		ArcNode *p = a.vertices[w].firstarc;//定义p指向w的邻接节点 的首节点 
		for(;p != NULL;p = p->nextarc){  //遍历w邻接节点 
			if(sign[p->adjvex] == 0){//只要未被访问 
				sign[p->adjvex] = 1;//标记访问 
				enqueue(q,p->adjvex);//入队 
				visit(a.vertices[p->adjvex]);//访问 
			}
		}
	}
} 
void BFSTraverse(ALGraph a,void (*visit)(VNode v)){     //非连通图广度优先遍历 
	int sign[a.vexnum];//定义标记数组 
	memset(sign,0,sizeof(sign)); //清空数组 
	sqqueue q;//创建一个辅助队列,用于广度优先 
	initqueue(&q); //队列初始化 
	int v = 0;
	for(;v < a.vexnum;++v){//遍历全部的节点 
		if(!sign[v]){
			BFS(a,sign,v,&q,visit);//如果这个节点还没被标记,则对其进行BFS 
		}
	}
}
int main(){
	ALGraph UDG;//先创建无向图 
	for(;;){
		printf("\n请选择 1.建立图  2.深度优先遍历图  3.广度优先遍历图  0.结束:\n");
		int n;//用于接收输入 
		scanf("%d",&n);
//		getchar();
		switch(n){
			case 1:{
					CreateGraph(&UDG);//创建无向图 
					printf("建立成功。\n");
					break;
				}
			case 2:{
					DFSTraverse(UDG,visit);//深度优先遍历 
					printf("\n深度优先遍历成功。\n");
					break;
				}	
			case 3:{
			    	BFSTraverse(UDG,visit);
			    	printf("\n广度优先遍历成功。\n");
			    	break;	
				}
			case 0:
				return 0;
				break;
			default:{
				printf("你输入的请求不符合规范,请重新输入!\n");
				break;
			}
		}
	}
}

运行结果截图:

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值