前言
图的最小系统的操作
声明:因个人能力有限,本文仅是个人的学习记录笔记,有错误之处还望指出
主要函数
- 建立无向图的邻接存储表
- 无向图的数据输出
- 深度优先
- 广度优先
代码实现
#include <stdio.h>
#include <stdlib.h>
#define Max 100
#define True 1
#define False 0
typedef char VertexType;
int visited[Max];
//边信息
typedef struct node
{
int adjvex;
struct node *next;
}EdgeNode;
//顶点信息
typedef struct vexnode
{
VertexType data;
EdgeNode *firstedge;
}VheadNode;
typedef struct{
VheadNode adjlist[Max];
int vernum,arcnum;
}AdjList;
//邻接表创建图(flag=0 无向图,flag=1 有向图)
void CreateAdjGraph(AdjList *g,int flag){
int i,j,k;
EdgeNode *p;
if(flag==0)
printf("将建立一个无向图\n");
else
printf("建立一个有向图\n");
printf("请输入顶点数:");
scanf("%d",&g->vernum);
printf("请输入边数:");
scanf("%d",&g->arcnum);
printf("输入各个顶点信息(每个顶点以回车结束):\n");
for(i=0;i<g->vernum;i++){
getchar(); //清空缓冲区
printf("输入第%d顶点:\n",i+1);
scanf("%c",&(g->adjlist[i].data));
g->adjlist[i].firstedge=NULL; //点的边表头指针为空
}
printf("\b请输入边的信息,输入格式为:序号1,序号2(从0开始)\n");
for(k=0;k<g->arcnum;k++){
printf("请输入第%d条边\n",k);
//将编号为i的结点加入到邻接表中
scanf("%d,%d",&i,&j);
p=(EdgeNode *)malloc(sizeof(EdgeNode));//新建节点
p->adjvex=j; //邻接点序号为j
//尾插法实现
p->next=g->adjlist[i].firstedge; //将新节点p插到顶点vi边表头
g->adjlist[i].firstedge=p;
//将编号为j的结点添加到邻接表中,有向图不需要添加
if(flag==0){
p=(EdgeNode *)malloc(sizeof(EdgeNode));
p->adjvex=i; //邻接点序号为j
p->next=g->adjlist[j].firstedge; //将新节点p插到顶点vi边表头
g->adjlist[j].firstedge=p;
}
}
}
//显示邻接表
void DisplayAdjGraph(AdjList g){
int i;
EdgeNode *p;
printf("\n图的邻接表表示:\n");
for(i=0;i<g.vernum;i++){
printf("%2d[%c]",i,g.adjlist[i].data);
p=g.adjlist[i].firstedge;
while(p!=NULL){
printf("-->[%d]",p->adjvex);
p=p->next;
}
printf("\n");
}
}
//深度优先遍历函数
void DFS(AdjList *g,int v){
EdgeNode *p;
printf("(%d,",v);
printf("%c)",g->adjlist[v].data);
visited[v] = True;
p=g->adjlist[v].firstedge;
while(p!=NULL){
if (visited[p->adjvex] == False)
DFS(g,p->adjvex);
p=p->next;
}
}
//广度优先遍历
void BFS(AdjList *g,int vi){
int i,v,visited[Max];
//循环队列
int que[Max],front=0,rear=0;
EdgeNode *p;
//辅助队列初始化
for(i = 0; i < g->vernum; i++)
visited[i]=False;
printf("(%d,",vi); //输出访问起点
printf("%c)",g->adjlist[vi].data);
visited[vi]=True;
//队尾指针后移
rear=(rear+1) % Max;
//入队
que[rear]=vi;
//队列非空
while(front != rear){
front=(front+1) % Max;
v=que[front]; //队头元素出队,赋值给顶点
p=g->adjlist[v].firstedge; //将顶点v的下一条邻接边顶点指针赋值给p
while(p!=NULL){
if(visited[p->adjvex] == False) //未访问过
{
visited[p->adjvex]=True;
printf("(%d,",p->adjvex); //输出顶点编号
printf("%c)",g->adjlist[p->adjvex].data);
rear = (rear+1) % Max;
que[rear] = p->adjvex;
}
p=p->next;
}
}
}
void menu(){
printf("\n\t图子系统");
printf("\n===================================");
printf("\n 1------更新邻接表 |");
printf("\n 2------深度优先遍历 |");
printf("\n 3------广度优先遍历 |");
printf("\n 0------返回 |");
printf("\n===================================");
printf("\n输入菜单号(0~3):\n");
}
int main(){
int i,flag;
char ch1,ch2,a;
AdjList g;
ch1='y';
while(ch1=='y' || ch1=='Y'){
menu();
scanf("%c",&ch2);
getchar(); //清除缓冲
switch(ch2){
case '1':
printf("要建立的是有向图(1)还是无向图(0),请选择(1,0):");
scanf("%d",&flag);
CreateAdjGraph(&g,flag);
DisplayAdjGraph(g);
break;
case '2':
printf("输入要进行深度优先遍历的定点序号(序号从0开始):");
scanf("%d",&flag);
printf("\n从顶点%d开始的深度优先序列为:",flag);
for(i=0;i<g.vernum;i++)
visited[i]=False;
DFS(&g,flag);
break;
case '3':
printf("输入要进行广度优先遍历的定点序号(序号从0开始):");
scanf("%d",&i);
printf("\n从顶点%d开始的广度优先序列为:",i);
BFS(&g,i);
break;
case '0':
ch1='n';break;
default:
printf("输入有误,重新输入(0~3)");
}
//确保程序的循环执行
if(ch2 != '0'){
printf("\n\n按回车键继续,按任意键返回主菜单");
a=getchar();
if(a != '\n'){
getchar();
ch1='n';
}
}
}
}
结果图
图的模型
图的存储
深度遍历
广度遍历