/*图的邻接表表示法 代码直接提用!*/
//真的要十分小心,本代码出现了少加上&,就查了我许久的bug!!!
/*一个顶点数组 这个数组不仅要存储顶点的信息,还需要存储指向第一个邻接点的指针(单链表)*/
/*分顶点表顶点,和边表结点 */
/*没事千万不要重复给一个申请动态空间 我可以差不多查了一小时的bug*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>//Sleep()函数,system()函数;等
#define MaxVertices 100
typedef int Boolean;
Boolean visited[MaxVertices];
typedef char DataType;//注意是char类型 队列
typedef struct cirQueue{
DataType data[MaxVertices];
int rear;
int front;
int count;//记录个数的
}CirQueue;
CirQueue *Q;
typedef struct node{ //边表
int adjvex; //记录下标
node *next;
int weight;//做为权值
}EdgeNode;
typedef struct{ //顶点表
char vertex; //顶点内储存数值
EdgeNode *edgenext; //边表头指针(其实还是当前的位置)
}VertexNode,AdjList[MaxVertices];
typedef struct{
AdjList adjlist;
int n; //当前顶点数
int e; //当前边数
}AdjMatrix;
void CreateGraph(AdjMatrix *G);
void DispGraph(AdjMatrix *G);
void menu(void);
void InitQueue(CirQueue);
int EnQueue(CirQueue *Q,DataType x);
DataType DeQueue(CirQueue *Q);
void BFSTraverse(AdjMatrix *G);
void DFS(AdjMatrix *G,int i);
void DFSTraverse(AdjMatrix *G);
int QueueEmpty(CirQueue *Q);
int QueueFull(CirQueue *Q);
int main(void)
{
int choose=-1, i1;
system("color F1");
system("pause");
AdjMatrix *G;
Q=(CirQueue *)malloc(sizeof(CirQueue));
G=(AdjMatrix *)malloc(sizeof(AdjMatrix));
menu();
while(choose!=4)
{
printf("\n请选择功能:");
scanf("%d",&choose);
switch(choose)
{
case 1:
CreateGraph(G);
printf("\n建立完成\n");
break;
case 2:
DispGraph(G);
break;
case 3:
printf("\n请输入(Vi,Vj)的下标:Vi:");
scanf("%d",&i1);
printf("->");
while(1)
{
if(G->adjlist[i1].edgenext == NULL)//跳出跳出条件是到了无数据读取的地方
{
printf("\n^^^^^于此处结束^^^^^\n");
break;
}
printf("%d(权值:%d)->",G->adjlist[i1].edgenext->adjvex,G->adjlist[i1].edgenext->weight); //->就做中间的一个连接符号
G->adjlist[i1].edgenext=G->adjlist[i1].edgenext->next; //此行代码就像以前的P=P->next; 跳到下一条
}
printf("\n");
break;
case 4:
printf("\n程序结束,祝您生活愉快!\n");
exit(0);
case 5:
printf("\n即将清屏\n");
Sleep(1000);
system("cls");
menu();
break;
case 6:
puts("深度遍历为:");
DFSTraverse(G);
break;
case 7:
puts("广度遍历为:");
BFSTraverse(G);
break;
default :
printf("\n输入有误!请重新输入!\n");
}
}
return 0;
}
void CreateGraph(AdjMatrix *G)
{
int i,j,k;
EdgeNode *s;
printf("输入顶点数和边数(中间以空格分开):");
scanf("%d %d",&G->n,&G->e);
printf("建立顶点表\n");
//此时已经知道了顶点数和边数
for (i=0; i<G->n; i++)
{
printf("请输入第%d个顶点的信息,它的下标为%d :",i+1,i);
//G->adjlist[i].vertex=getchar();//等价于scanf("%d",&G->adjlist[i].vertex);
getchar();//读取回车
scanf("%c",&G->adjlist[i].vertex);
G->adjlist[i].edgenext=NULL; //表在还没有使用的时候一般都是置空化
}
//前插法 (先后再前)
printf("建立边表\n");
for (k=0;k<G->e;k++) //此时还需加入输入权值的weight,拥有几条边就会要求输入几次
{
//此处其实流了两种方法,前面直接的就需要反着输入,1输0,0输1,而后面的间接的就可以直接
//因为前面的将本该处于后面的j放在了前面
printf("输入有连接的顶点序号(以做下标)(用空格隔开):");
scanf("%d %d",&i,&j);
s=(EdgeNode*)malloc(sizeof(EdgeNode));
s->adjvex=j;//边表赋值
printf("\n请输入权值:");
scanf("%d",&s->weight);//就是忘记加上&了!!
s->next=G->adjlist[i].edgenext;
G->adjlist[i].edgenext=s;
/*s=(EdgeNode *)malloc(sizeof(EdgeNode));
s->adjvex=i;
printf("\n请输入权值:");
scanf("%d",&s->weight);//就是忘记加上&了!!!
s->next=G->adjlist[j].edgenext;//这一行代码到底有没有实现自己该实现的功能
G->adjlist[j].edgenext=s;*/
}
}
void DispGraph(AdjMatrix *G)
{
AdjMatrix *G1;
G1=(AdjMatrix *)malloc(sizeof(AdjMatrix));
int i;
for (i=0;i<G->n;i++)
{
printf("%d->",i); //表示第几个
//此行代码等价于上面一行的代码 printf("\n第%d个是:",i+1);
G1->adjlist[i].edgenext=G->adjlist[i].edgenext;//用G1来储存初始值
while(1)
{
if(G->adjlist[i].edgenext==NULL)//跳出跳出条件是到了无数据读取的地方
{
//此行代码的bug:每次都是以G->adjlist[i].edgenext=NULL才停止,导致下次不好使用,得改
printf("\n^^^^^于此处结束^^^^^\n");
break;
}
printf("%d(权值:%d)->",G->adjlist[i].edgenext->adjvex,G->adjlist[i].edgenext->weight); //->就做中间的一个连接符号
G->adjlist[i].edgenext=G->adjlist[i].edgenext->next; //此行代码就像以前的P=P->next; 跳到下一条
}
G->adjlist[i].edgenext=G1->adjlist[i].edgenext;//变回
printf("\n");
}
}
void menu(void)//菜单
{
printf("\n 1.建立图 2.输出图内关系 \n");
printf("\n 3.特意查询 4.退出 \n");
printf("\n 5.清屏 6.深度优先递归算法 \n");
printf("\n 7.广度优先遍历 \n");
}
void InitQueue(CirQueue *Q)//置队空
{
Q->front=Q->rear=0;
Q->count=0;
}
int QueueFull(CirQueue *Q)//判断队列是否已经满了
{
return Q->count==MaxVertices;
}
int QueueEmpty(CirQueue *Q)//判断队列是否为空
{
return Q->count==0;
}
int EnQueue(CirQueue *Q,DataType x)//入队
{
//首先判断队列是否已满
if(QueueFull(Q))
{
printf("\n不好意思,队列已经满了,无法进行入队操作\n");
return 0;
}
Q->count++;
Q->data[Q->rear]=x;
Q->rear=(Q->rear+1)%MaxVertices;
return 1;
}
DataType DeQueue(CirQueue *Q)//出队
{
//首先需要判断队列是否为空
DataType temp;
if(QueueEmpty(Q))
{
printf("\n不好意思,队列为空,无法进行出队操作\n");
return 0;
}
Q->count--;
temp=Q->data[Q->front];
Q->front=(Q->front+1)%MaxVertices;
return temp;
}
void BFSTraverse(AdjMatrix *G) //广度遍历
{
int i=0, j=0;
EdgeNode *p;
AdjMatrix *G2;
G2=(AdjMatrix *)malloc(sizeof(AdjMatrix));
//printf("第一个G->n=%d\n",G->n);//发现此处G->n的存储出现了问题
for(j=0; j<G->n; ++j)
visited[j]=FALSE;
InitQueue(Q);
//此处的初始化已经过了,是for循环出现了问题
for(i=0; i<G->n; ++i)
{
G2->adjlist[i].edgenext=G->adjlist[i].edgenext;//保留初始值
if(!visited[i])
{
visited[i]=TRUE;
printf("%c\t",G->adjlist[i].vertex);
EnQueue(Q,i);
while(!QueueEmpty(Q))
{
DeQueue(Q);
p=G->adjlist[i].edgenext;
while(p)
{
if(!visited[p->adjvex])
{
visited[p->adjvex]=TRUE;
printf("%c\t",G->adjlist[p->adjvex].vertex);
EnQueue(Q,p->adjvex);
}
p=p->next;
}
}
}
G->adjlist[i].edgenext=G2->adjlist[i].edgenext;//变回
}
}
void DFS(AdjMatrix *G,int i) //深度遍历
{
AdjMatrix *G1;
G1=(AdjMatrix *)malloc(sizeof(AdjMatrix));
EdgeNode *p;
p=(EdgeNode *)malloc(sizeof(EdgeNode));
visited[i]=TRUE;
printf("%c\t",G->adjlist[i].vertex);
p=G->adjlist[i].edgenext;
G1->adjlist[i].edgenext=G->adjlist[i].edgenext;//保存初始值
while(p)
{
if(!visited[p->adjvex])
DFS(G,p->adjvex);
p=p->next;
}
G->adjlist[i].edgenext=G1->adjlist[i].edgenext;//变回
}
void DFSTraverse(AdjMatrix *G) //深度遍历
{
int i;
for(i=0; i<G->n; ++i)
visited[i]=FALSE;//先全为未访问状态
for(i=0; i<G->n; ++i)
if(!visited[i]) //找遍即是
DFS(G,i);
}
图、邻接表表示法、深度遍历,广度遍历
最新推荐文章于 2022-04-30 19:10:59 发布