一. 实验目的和要求
1、掌握图的存储结构:邻接矩阵、邻接表。
2、掌握图的深度优先与广度优先两个搜素算法。
3、学会对图的存储结构进行基本操作。
4、加强综合程序的分析、设计能力。
二. 实验内容
1、现有14个人(分别用字母A、B、… N表示),他们相互之间的朋友关系如图所示(有线相连表示是朋友关系),请分别用邻接矩阵与邻接表表示该关系图,并完成以下功能。
① 以邻接矩阵表示,在此结构上完成:
创建此图;
输出此图的邻接矩阵;
输出从A出发的深度优先搜索序列;
输出从A出发的广度优先搜索序列;
输入两个人p1、p2,判断此两人是否为朋友关系,若不是,给出一种从p1能找到p2的路径;(如输入p1=‘A’、p2=‘N’,则A与N不是直接朋友关系,但可以(不唯一)通过A-B-F-K-N方式联系到N。)
② 以邻接表表示,在此结构上完成:
创建此图;
输出此图的邻接表;
输出从A出发的深度优先搜索序列;
输出从A出发的广度优先搜索序列;
输入两个人p1、p2,判断此两人是否为朋友关系,若不是,给出一种从p1能找到p2的路径;(如输入p1=‘A’、p2=‘N’,则A与N不是直接朋友关系,但可以(不唯一)通过A-B-F-K-N方式联系到N。)
③ 建立头文件AdjMatrix.h和AdjLink.h,分别包含邻接矩阵结构和邻接表结构的操作实现函数,建立主程序文件test6.cpp,在主函数中通过调用来实现上述功能。
④ 自行增加合适的功能,可作为额外的实验成绩进行加分(例如考虑添加或删除一对朋友关系;找出朋友最多的那个人;上面找到A到N的联系路径,若要求找到一条最短的路线怎么找等等)。**
// 主函数
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX_VERTEX_NUM 20 //最大顶点个数
#define TRUE 1
#define FALSE 0
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
typedef int Status;
typedef int QElemtype; //队列
typedef struct QNode{
QElemtype data;
struct QNode *next;
}QNode,*QueuePtr;
typedef struct{
QueuePtr front;
QueuePtr rear;
QueuePtr p;
}LinkQueue;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
typedef int SElemtype;
typedef struct{ //栈
SElemtype *base;
SElemtype *top;
int stacksize;
}SqStack;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
typedef char VertexType;
typedef int VRType; //图 (邻接矩阵声明)
typedef struct{
VertexType Vexs[MAX_VERTEX_NUM]; //顶点向量
VRType edges[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵
int vexnum,arcnum; //图的当前顶点数和弧数
}MGraph;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
typedef char Vertextype;
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; //图的当前顶点数,边数
}ALGraph;
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
bool visited[MAX_VERTEX_NUM]; //全局变量布尔数组:访问
#include"AdjMatrix.h"
#include"AdjLink.h"
int main()
{
printf("~~~~~~~~~~~~邻接矩阵~~~~~~~~~~~~\n");
MGraph G;
CreateGraph(G);
SqStack S,S1;
InitStack(S);
FILE *fp,*fp1; //用文件输入更省时省力;
fp=fopen("INPUT2.txt","r");
CreateUDG(G,fp);
printf("邻接矩阵为:\n");
PRINT(G); //输出邻接矩阵
printf("深度优先搜索顺序为:"); //深度遍历
DFSTraverse(G);
putchar(10);
getchar();
printf("广度优先搜索顺序为:");
BFSTraverse(G);
putchar(10);
char ch1,ch2;
printf("请输入任意不相同的两个大写字母:");
scanf("%c %c",&ch1,&ch2);
LinkQueue Q;
Init(Q);
panding(G,S,Q,ch1,ch2);
friendsnum(G); //找出朋友最多的人
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
printf("\n~~~~~~~~~~~邻接表~~~~~~~~~~~~~:");
ALGraph* G1 =(ALGraph*)malloc(sizeof(ALGraph)) ;
fp1=fopen("INPUT2.txt","r");
CreateALGraph(G1,fp1);
PRINTL(G1);
printf("深度优先搜索顺序为:");
DFSTraverseL(G1);
putchar(10);
printf("广度优先搜索顺序为:");
BFSTraverseL(G1);
putchar(10);
printf("请输入任意不相同的两个大写字母:");
getchar();
char ch3,ch4;
scanf("%c %c",&ch3,&ch4);
LinkQueue Q1;
InitStack(S1);
Init(Q1);
pandingL(G1,S1,Q1,ch3,ch4);
friendsnumL(G1); //找出朋友最多的人
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
}
//头文件
//邻接矩阵方式
void CreateGraph(MGraph &G)
{
printf("请输入顶点数和边数:");
scanf("%d",&G.vexnum);
scanf("%d",&G.arcnum);
getchar();
printf("请输入结点信息:");
for(int i=0;i<G.vexnum;i++)
scanf("%c",&G.Vexs[i]);
//邻接矩阵初始化
for(int j=0;j<G.vexnum;j++)
for(int k=0;k<G.vexnum;k++)
G.edges[j][k]=0;
}
void CreateUDG(MGraph &G,FILE *fp)
{
for(int t=0;t<G.arcnum;t++)
{ char ch1,ch2;int o;int p;
fscanf(fp,"%c,%c",&ch1,&ch2);
for(int i=0;i<G.vexnum;i++) //定位功能
{
if(ch1==G.Vexs[i])
o=i;
}
for(int i=0;i<G.vexnum;i++) //定位功能
{
if(ch2==G.Vexs[i])
p=i;
}
G.edges[o][p]=1;
G.edges[p][o]=1;
}
}
void PRINT(MGraph &G)
{
for(int i=0;i<G.vexnum;i++)
{
for(int j=0;j<G.vexnum;j++)
printf("|%d| ",G.edges[i][j]);
putchar(10);
}
}
void DFS(MGraph &G,int i)
{
int k;
visited[i]=TRUE;
putchar(G.Vexs[i]);
for(k=0;k<G.vexnum;k++)
{
if(G.edges[i][k]==1&&visited[k]==0){
DFS(G,k);
}
}
}
void DFSTraverse(MGraph &G)
{
int i;
for(i=0;i<G.vexnum;i++) // visited数组的初始化
visited[i]=FALSE;
for(i=0;i<G.vexnum;i++){
if(visited[i]==0)
DFS(G,i);
}
}
void BFSTraverse(MGraph &G)
{
for(int i=0;i<G.vexnum;i++)
visited[i]=0;
putchar(G.Vexs[0]);
visited[0]=1;
for(int i=0;i<G.vexnum;i++)
{
for(int j=0;j<G.vexnum;j++)
{
if(G.edges[i][j]==1&&visited[j]==0)
{
putchar(G.Vexs[j]);
visited[j]=1;
}
}
}
}
void InitStack(SqStack &S){
S.base=(SElemtype *)malloc(STACK_INIT_SIZE*sizeof(SElemtype));
if(!S.base)exit(-2);
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
}
void Push(SqStack &S,SElemtype e)
{
if(S.top-S.base>=S.stacksize)
{S.base=(SElemtype *)realloc(S.base,
(S.stacksize+STACKINCREMENT)*sizeof(SElemtype));
if(!S.base)exit(-2);
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}
*S.top++=e;
}
int Pop(SqStack &S)
{
if(S.top==S.base)return 0;
S.top--;
int e=*S.top;
return e;
}
int GetTop(SqStack &S)
{
if(S.top==S.base)return 0;
int e=*(S.top-1);
return e;
}
void Init(LinkQueue &Q)
{
Q.front=Q.rear=Q.p=(QueuePtr)malloc(sizeof(QNode));
if(!Q.front)exit(-2);
Q.front->next=NULL;
}
void EnQueue(LinkQueue &Q,int e)
{
QueuePtr p=(QueuePtr)malloc(sizeof(QNode));
if(!p)exit(-2);
p->data=e;p->next=NULL;
Q.rear->next=p;
Q.rear=p;
}
int DeQueue(LinkQueue &Q)
{
if(Q.front==Q.rear)return 0;
QueuePtr p=Q.front->next;
int e=p->data;
Q.front->next=p->next;
if(Q.rear==p)Q.rear=Q.front;
free(p);
return e;
}
void relationship(MGraph &G,SqStack &S,LinkQueue &Q,int s,int m)//实现两点间最短距离 函数
{
int dist[G.vexnum],path[G.vexnum];
for(int i=0;i<G.vexnum;i++){
dist[i]=-1;
path[i]=-1;
}
EnQueue(Q,s);
dist[s]=0;
while(Q.front!=Q.rear)
{
int w=DeQueue(Q);
for(int j=0;j<G.vexnum;j++)
if(G.edges[w][j]==1&&dist[j]==-1){
dist[j]=dist[w]+1;
path[j]=w;
EnQueue(Q,j);
}
}
while(m!=-1)
{
Push(S,m);
m=path[m];
}
int dz;
printf("最短路径为:");
while(S.base!=S.top-1)
{
dz=Pop(S);
printf("%c->",G.Vexs[dz]);
}
dz=Pop(S);
printf("%c",G.Vexs[dz]);
}
void panding(MGraph &G,SqStack &S,LinkQueue &Q,char ch1,char ch2)
{
int start,end;
for(int i=0;i<G.vexnum;i++){
if(ch1==G.Vexs[i])
{
start=i;
break;
}
}
for(int i=0;i<G.vexnum;i++){
if(ch2==G.Vexs[i])
{end=i;
break;
}
}
if(G.edges[start][end]==1) printf("%c和%c是朋友",ch1,ch2);
else{
relationship(G,S,Q,start,end);
}
}
void friendsnum(MGraph &G)
{ int max=0,sum=0,l=0;int i=0;
for(i=0;i<G.vexnum;i++){
for(int j=0;j<G.vexnum;j++)
{
sum+=G.edges[i][j];
}
if(max<sum)
{
max=sum;
l=i;
}
sum=0;
}
printf("\n朋友最多的是%c,共有%d个",G.Vexs[l],max);
}
//邻接表方式
void CreateALGraph(ALGraph* G1,FILE *fp1)
{
ArcNode *L;
putchar(10);
printf("请输入顶点数和边数:");
scanf("%d %d",&G1->vexnum,&G1->arcnum);
getchar();
printf("请输入结点信息:");
for(int i=0;i<G1->vexnum;i++)
{
scanf("%c",&G1->vertices[i].data);//G1->vertices[i].data存放顶点信息
G1->vertices[i].firstarc=NULL;
}
char ch1,ch2;int h,q;
for(int i=0;i<G1->arcnum;i++)
{
fscanf(fp1,"%c,%c",&ch1,&ch2);
for(int i=0;i<G1->vexnum;i++){
if(ch1==G1->vertices[i].data){
q=i;break;
}
}
for(int i=0;i<G1->vexnum;i++){
if(ch2==G1->vertices[i].data){
h=i;break;
}
}
L=(ArcNode*)malloc(sizeof(ArcNode));
L->adjvex=h;
L->nextarc=G1->vertices[q].firstarc;
G1->vertices[q].firstarc=L;
L=(ArcNode*)malloc(sizeof(ArcNode));
L->adjvex=q;
L->nextarc=G1->vertices[h].firstarc;
G1->vertices[h].firstarc=L;
}
}
void PRINTL(ALGraph* G1)
{
for (int i=0;i<G1->vexnum;i++)
{
printf("%d:",i);
ArcNode *L=G1->vertices[i].firstarc;
while(L!=NULL)
{
printf("%d->",L->adjvex);
L=L->nextarc;
}
printf("NULL");
printf("\n");
}
}
void BFSTraverseL(ALGraph* G1)
{
for(int i=0;i<G1->vexnum;i++)
visited[i]=0;
int a[G1->vexnum];
a[0]=0;
visited[0]=1;
int j=1; //初始化
for (int i=0;i<G1->vexnum;i++)
{ ArcNode *L=G1->vertices[i].firstarc;
while(L!=NULL)
{
int t=L->adjvex;
if(visited[t]==0)
{
a[j]=L->adjvex;
visited[t]=1;
j++;
}
L=L->nextarc;
}
}
int t;
for(int i=0;i<G1->vexnum;i++)
{
t=a[i];
printf("%c",G1->vertices[t].data);
}
}
void DFS(ALGraph* G1,int i)
{
int k;
visited[i]=1;
printf("%c",G1->vertices[i].data);
ArcNode *L=G1->vertices[i].firstarc;
while(L)
{
if(!visited[L->adjvex]){
DFS(G1,L->adjvex);
}
return;
}
L=L->nextarc;
}
void DFSTraverseL(ALGraph* G1)
{
for(int i=0;i<G1->vexnum;i++) // visited数组的初始化
visited[i]=0;
for(int i=0;i<G1->vexnum;i++){
if(visited[i]==0)
DFS(G1,i);
}
}
void relationshipL(ALGraph*G1,SqStack &S1,LinkQueue &Q1,int s,int m) //实现两点间最短距离 函数
{
int dist[G1->vexnum],path[G1->vexnum];
for(int i=0;i<G1->vexnum;i++){
dist[i]=-1;
path[i]=-1;
}
EnQueue(Q1,s);
dist[s]=0;
while(Q1.front!=Q1.rear)
{
int w=DeQueue(Q1);
ArcNode *L=G1->vertices[w].firstarc;
while(L){
if(dist[L->adjvex]==-1){
dist[L->adjvex]=dist[w]+1;
path[L->adjvex]=w;
EnQueue(Q1,L->adjvex);
}
L=L->nextarc;
}
}
while(m!=-1)
{
Push(S1,m);
m=path[m];
}
int dz;
printf("最短路径为:");
while(S1.base!=S1.top-1)
{
dz=Pop(S1);
printf("%c->",G1->vertices[dz].data);
}
dz=Pop(S1);
printf("%c",G1->vertices[dz].data);
}
void pandingL(ALGraph* G1,SqStack &S1,LinkQueue &Q1,char ch3,char ch4)
{
int start,end;
for(int i=0;i<G1->vexnum;i++){
if(ch3==G1->vertices[i].data)
{
start=i;
break;
}
}
for(int i=0;i<G1->vexnum;i++){
if(ch4==G1->vertices[i].data)
{
end=i;
break;
}
}
ArcNode *L=G1->vertices[start].firstarc;
int flag=0;
while(L){
if(L->adjvex==end){
flag=1;
break;
}
L=L->nextarc;
}
if(flag==1)
printf("%c和%c是朋友",ch3,ch4);
else
{
relationshipL(G1,S1,Q1,start,end);
}
}
void friendsnumL(ALGraph* G1)
{
int max=0,sum=0,l=0;
for(int i=0;i<G1->vexnum;i++){
ArcNode *L=G1->vertices[i].firstarc;
while(L){
L=L->nextarc;
sum++;
}
if(max<sum){
max=sum;
l=i;
}
sum=0;
}
printf("\n朋友最多的是%c,共有%d个",G1->vertices[l].data,max);
}