《数据结构》实验报告
学号: 2018329621200 | 机器号 10-414-28 | 姓名: 申屠志刚 |
日期: 2019/12/9 | 程序名: main.cpp | |
实验内容: 无向图邻接表的构造 |
一、目的和要求(需求分析):
1、掌握邻接表的存储结构以及邻接表的建立和操作。
2、 构造一个无向图的邻接表,要求从键盘输入图的顶点数和图的边数,并显示所构造的邻接表)
实验拓展:
1. 构建有向图的邻接表
2. 判断边是否存在
3. 求顶点的度数
二、程序设计的基本思想,原理和算法描述:
邻接表是数组与链表相结合的存储方法,相比于顺序存储结构(邻接矩阵),节省空间。
三、调试和运行程序过程中产生的问题及采取的措施:
1、度数求法;
措施:添加边时即记录度数。
2、对应节点和节点编号;
措施:历遍查找。
3、区分有向图和无向图;
措施:添加标记,以判断是否添加反向边。
四、源程序及注释:
/*
*@Author: STZG
*@Language: C++
*/
#include <bits/stdc++.h>
#define MAXVEX 30
using namespace std;
int visited[MAXVEX];
int n,m;
typedef char VertexType;
typedef struct ArcNode {
int adjvex; /*邻接点序号*/
VertexType data; /*邻接点信息*/
struct ArcNode *nextarc;
char *info;
} ArcNode;
typedef struct VNode {
VertexType data; /*结点信息*/
ArcNode *firstarc; /*指向下一个边结点*/
}VNode,AdjList[MAXVEX];
typedef struct //图结构
{
AdjList vertices;
int vexnum,arcnum; //图的当前顶点数与弧数
int in[MAXVEX],out[MAXVEX];
}ALGraph;
int LocateVex(ALGraph G,char v) //查找值为v的顶点在顶点向量G.vexs[]中的位置
{
int i;
for(i=0;i<G.vexnum;i++)
if(v==G.vertices[i].data)
return i;
return -1;
}
int FirstAdjVex(ALGraph G,char v)//返回v的第一个邻接顶点的序号
{
int i;
ArcNode *p;
i=LocateVex(G,v); //i为顶点v在图G中的序号
if(i==-1)
return -1;
p=G.vertices[i].firstarc;
if(p)
return p->adjvex;
else
return -1;
}
int NextAdjVex(ALGraph G,char v,char w)//返回v的(相对于w)的下一个邻接顶点的序号
{
int i,j;
ArcNode *p,*q;
i=LocateVex(G,v);
j=LocateVex(G,w);
if(i==-1||j==-1||i==j)
return -1;
p=G.vertices[i].firstarc; //p指向v的邻接顶点链表中的第一个邻接顶点
while(p->nextarc&&p->adjvex!=j) //找到邻接顶点w
p=p->nextarc;
if(p->nextarc) //找到邻接顶点w,且w非v的最后一个邻接顶点
{
q=p->nextarc;
return q->adjvex; //返回v的(相对于w)的下一个邻接顶点的序号
}
else
return -1; //没有找到w或w是v的最后一个邻接顶点
}
int Visit(char v)
{
printf("%c ",v);
return 1;
}
int add(ALGraph &G,int i,int j){
ArcNode *p,*q;
G.out[i]++;
G.in[j]++;
p=(ArcNode *)malloc(sizeof(ArcNode));
p->adjvex=j;
p->info=NULL;
p->nextarc=NULL;
if(!G.vertices[i].firstarc)
G.vertices[i].firstarc=p;
else
{//找尾结点
for(q=G.vertices[i].firstarc;q->nextarc;q=q->nextarc);
q->nextarc=p; //插入到链表尾
}
}
int CreateDG(ALGraph &G) //采用邻接表表示,构造有向图G
{
int v,e,i,j,t,f;
ArcNode *p,*q;
char tail,head;
printf("输入顶点个数:");
scanf("%d",&v);
if(v<0)
return 0;
G.vexnum=v;
printf("输入弧的条数:");
scanf("%d",&e);
if(e<0)
return 0;
G.arcnum=e;
printf("无向图/有向图(0/1):");
scanf("%d",&f);
printf("建立DG:\n");
for(t=0;t<G.vexnum;t++) //建立头结点顺序表
{
fflush(stdin);
printf("输入%d的信息:",t+1);
scanf("%c",&G.vertices[t].data);
G.vertices[t].firstarc=NULL; //初始化该头结点指针域
G.in[t]=0;
G.out[t]=0;
}
for(t=0;t<G.arcnum;t++) //建立表结点链表(每个顶点的邻接顶点链表)
{
fflush(stdin);
printf("输入弧的信息(弧尾-弧头)");
scanf("%c%*c%c",&tail,&head);
i=LocateVex(G,tail);
j=LocateVex(G,head);
if(i==-1||j==-1||i==j)
return 0;
add(G,i,j);
if(f)add(G,j,i);
}
return 1;
}
int DFS(ALGraph G,int v) //从第v个顶点出发,递归的深度优先遍历有向图G
{
int w;
visited[v]=-1;
printf("%c ",G.vertices[v].data);
w=FirstAdjVex(G,G.vertices[v].data);
for(;w>=0;w=NextAdjVex(G,G.vertices[v].data,G.vertices[w].data))
if(!visited[w])
DFS(G,w); //对v的尚未访问的邻接顶点w递归调用DFS()
return 1;
}
int DFSTraverse(ALGraph G) //深度优先搜索遍历图G
{
int i;
for(i=0;i<G.vexnum;i++)
visited[i]=0;
for(i=0;i<G.vexnum;i++)
if(!visited[i])
DFS(G,i);
return 1;
}
void printALGraph(ALGraph G){
for(int i=0;i<G.vexnum;i++){
printf("%c|%d-->",G.vertices[i].data,i);
for(ArcNode* q=G.vertices[i].firstarc;q;q=q->nextarc){
printf("%d-->",q->adjvex);
}
printf("null\n");
}
}
void printdegree(ALGraph G){
printf("Node\t入度\t出度\t度\n");
for(int i=0;i<G.vexnum;i++){
printf("%c\t%d\t%d\t%d\n",G.vertices[i].data,G.in[i],G.out[i],G.in[i]+G.out[i]);
}
}
int checkarc(ALGraph G){
while(1){
char tail,head;
fflush(stdin);
printf("输入弧的信息(弧尾-弧头)");
scanf("%c%*c%c",&tail,&head);
int i=LocateVex(G,tail);
int j=LocateVex(G,head);
if(i==-1||j==-1||i==j)
return 0;
int f=0;
for(ArcNode* q=G.vertices[i].firstarc;q;q=q->nextarc){
if(j==q->adjvex){
f=1;
break;
}
}
if(f)printf("Yes\n");
else printf("No\n");
}
}
int main()
{
ALGraph G;
printf("建立有向图G\n");
if(CreateDG(G))
{
printALGraph(G);
printdegree(G);
printf("深度优先搜索的顺序:");
DFSTraverse(G);
printf("\n");
}
checkarc(G);
return 0;
}
五、运行输出结果:
六、心得与体会:
1、掌握邻接表的存储结构以及邻接表的建立和操作。
2、构造无向图/有向图的邻接表。
3、转换思想,记录不变量。