实验六 图的邻接矩阵和邻接表存储实现
一、实验目的
1、理解并掌握图的邻接矩阵存储;
2、理解并掌握图的邻接表存储;
3、实现两种存储结构。
二、实验内容
编写程序实现下图的邻接矩阵与邻接表的创建和输出。
三、实验步骤和设计思想
1、创建邻接矩阵,按照顶点与顶点之间有无边(有边即为1)输入数据,无边不输入,默认为0
2、根据之前输入数据形成的邻接矩阵创建邻接表,并将邻接表输出
四、程序清单
#include <stdio.h>
#include <stdlib.h>
#define Vmax 100
typedef char VType;//顶点字符型
typedef int EType;//边,矩阵元素int型
typedef struct {
VType vexs[Vmax]; //顶点表:存图的所有顶点,比如abcd四个顶点,放入数组中
EType edges[Vmax][Vmax]; //邻接矩阵—边表 值为0 1整数
int Vnum, Enum; // 图的顶点数和边数
}MGraph;
typedef char VType; //顶点字符型
typedef int EType;// 边:对应顶点数组的数组下标,int型
typedef struct node
{
EType adjvex;
struct node *next;
}EdgeNode;//边结点
typedef struct
{
VType vertex;
EdgeNode *firstedge;
}VertexNode;//顶点结点
typedef struct
{
VertexNode vexlist[Vmax];//顶点结点数组
int vexnum,arcnum;//顶点数、边数
}AdjGraph;//图的邻接表
typedef int elemtype;
typedef struct{
elemtype data[Vmax]; //将栈中元素定义为elemtype类型
int top; //:指向栈顶位置的指针(即数组下标)
}SqStack;
typedef char ElemType;
typedef struct
{
ElemType data[Vmax]; /*保存队中元素*/
int front,rear; /*队头和队尾指针,队头指向队列首元素的前一个位置,队尾指向队尾元素。*/
} SqQueue;
void InitQueue(SqQueue *&q)//初始化
{
q=(SqQueue*)malloc(sizeof(SqQueue));
q->front=q->rear=0;
}
bool enQueue(SqQueue *&q,ElemType e)//进队列
{
if((q->rear+1)%Vmax==q->front){ //队满上溢出
printf("队满\n");
return false;
}
q->rear=(q->rear+1)%Vmax;
q->data[q->rear]=e;
return true;
}
bool deQueue(SqQueue *&q,ElemType e)//出队列
{
if(q->front==q->rear){ //队空下溢出
printf("队空\n");
return false;
}
q->front=(q->front+1)%Vmax;
e=q->data[q->front];
return true;
}
bool QueueEmpty(SqQueue *q)//判断队列是否为空
{
return (q->rear==q->front);
}
void DestroyQueue(SqQueue *&q)//销毁队列
{
free(q);
}
void CreateUDN(MGraph *&G)
{
int i,j,vi,vj,w;
G=(MGraph *)malloc(sizeof(MGraph));
printf("请输入邻接矩阵的顶点数和边数:\n");
scanf("%d %d",&G->Vnum,&G->Enum); //输入总顶点数,总边数
printf("请输入每个顶点的信息:\n");
getchar();
for( i=0; i<G->Vnum; i++) //将顶点存入数组中
{
scanf("%c",&G->vexs[i]); //依次输入点的信息
}
for( i=0; i<G->Vnum; i++) //图的初始化
{
for( j=0; j<G->Vnum; j++)
{
G->edges[i][j] = 0; //初始化为0
}
}
printf("\n");
for(i=0; i<G->Enum; i++)
{
printf("请输入边的信息:\n");
scanf("%d %d %d",&vi,&vj,&w);
G->edges[vi-1][vj-1] = w; //因为无向图是对称的,a[i][j] = a[j][i]
G->edges[vj-1][vi-1] = w;
}
}
void PrintfGraph(MGraph *&G) //输出邻接矩阵的信息
{
int i,j;
printf("\n邻接矩阵为:\n");
for(i=0;i<G->Vnum;i++)
{
printf("\t%c",G->vexs[i]);
}
printf("\n");
for(i=0; i<G->Vnum; i++)
{
printf("\n%c\t",G->vexs[i]);
for(j=0; j<G->Vnum; j++)
{
printf("%d\t",G->edges[i][j]);
}
}
}
void CreateAdj(AdjGraph *&F,MGraph *&G){
int i,j;
EdgeNode *p;
F=(AdjGraph *)malloc(sizeof(AdjGraph));
for(i=0;i<G->Vnum;i++){
F->vexlist[i].firstedge=NULL;
}
for(i=0;i<G->Vnum;i++){
for(j=0;j<G->Vnum;j++)
if(G->edges[i][j]!=0&&G->edges[i][j]!=32767){
p=(EdgeNode *)malloc(sizeof(EdgeNode));
p->adjvex=j;
p->next=F->vexlist[i].firstedge;
F->vexlist[i].firstedge=p;
}
}
F->vexnum=G->Vnum;
F->arcnum=G->Enum;
}
void DispAdj(AdjGraph *&F,MGraph *&G){
int i;EdgeNode *p;
printf("\n图的邻接表为\n");
for(i=0;i<F->vexnum;i++){
p=F->vexlist[i].firstedge;
printf("%c->",G->vexs[i]);
while(p!=NULL){
printf("%d->",p->adjvex);
p=p->next;
}
printf("NULL\n");
}
}
void DestroyAdj(AdjGraph*& G) { //销毁邻接表
int i; EdgeNode * pre, * p;
for (i = 0; i < G->vexnum; i++) { //扫描所有的单链表
pre = G->vexlist[i].firstedge; //p指向第i个单链表的头结点
if (pre != NULL) {
p = pre->next;
while (p != NULL)
{
free(pre); //释放pre
pre = p; p = p->next;
}
free(pre); //最后循环结束,释放pre
}
}
free(G); //释放邻接表指针
}
//int visited[Vmax]={0};//全局数组
//void DFS(AdjGraph *&g,MGraph *&G ,int v);//函数声明
//void BFS(AdjGraph *g,MGraph *&G,int v);//函数声明
int main()
{
MGraph *G;
CreateUDN(G);
PrintfGraph(G);
printf("\n");
AdjGraph *F;
CreateAdj(F,G); //创建图的邻接表
DispAdj(F,G); //输出图的邻接表
int v;
// DFS(F,G,v);
printf("\n");
// BFS(F,G,v);
DestroyAdj(F); //释放图的邻接表=0
}
/*void DFS(AdjGraph *&g,MGraph *&G,int v) //深度优先遍历算法
{
EdgeNode *p=g->vexlist[v].firstedge;//p指向顶点v的第一个邻接点
visited[v]=1; //置已访问标记
printf("%c->",G->vexs[v]); //输出被访问的顶点
while (p!=NULL){
if(visited[p->adjvex]==0)//若p->adjvex顶点未被访问,递归访问
DFS(g,G,p->adjvex);
p=p->next;//p指向顶点v的下一个邻接点
}
}
void BFS(AdjGraph *g,MGraph *&G,int v)//广度优先遍历
{
EdgeNode *p ;
int w,i;
SqQueue * qu; //定义队列指针
InitQueue(qu); //初始化队列
for(i=0;i<g->vexnum;i++)//访问标记数组初始化
visited[i]=0;
printf("%c->",G->vexs[v]);//输出被访问的顶点
visited[v]=1; //标记已访问位置
enQueue(qu,v); //入队
while(!QueueEmpty(qu)){ //队不空
deQueue(qu,w); //出队一个顶点w
p=g->vexlist[w].firstedge;//指向w的第一个邻接点
while(p!=NULL){ //查找w的所有邻接点
if(visited[p->adjvex]==0){//若该邻接点未被访问
printf("%c->",G->vexs[p->adjvex]);//输出该邻接点
visited[p->adjvex]=1;//标记已访问位置
enQueue(qu,p->adjvex);//该顶点进队
}
p=p->next; //找下一个邻接点
}
}
printf("\n");
}*/