数据结构-图的遍历

#include <stdio.h>
#include <stdlib.h>
#define MAX_Vertex_NUM 20 //图的最大顶点数
#define MAXQSIZE 30 //队列的最大容量
#define INFINITY 32768 /*表示极大值,即∞*/
#define TRUE 1
#define FALSE 0
#define ERROR -1
#define OK 1

typedef int QueueElementType;
typedef struct Node
{
QueueElementType data; /*数据域*/
struct Node *next; /*指针域*/
}LinkQueueNode;

typedef struct
{
LinkQueueNode *front;
LinkQueueNode *rear;
}LinkQueue;

/*初始化操作。*/
int InitQueue(LinkQueue *Q)
{
/* 将Q初始化为一个空的链队列 */
Q->front=(LinkQueueNode *)malloc(sizeof(LinkQueueNode));
if(Q->front!=NULL)
{
Q->rear=Q->front;
Q->front->next=NULL;
return(TRUE);
}
else return(FALSE); /* 溢出!*/
}

/*入队操作。*/
int EnterQueue(LinkQueue *Q,QueueElementType x)
{
/* 将数据元素x插入到队列Q中 */
LinkQueueNode *NewNode;
NewNode=(LinkQueueNode * )malloc(sizeof(LinkQueueNode));
if(NewNode!=NULL)
{
NewNode->data=x;
NewNode->next=NULL;
Q->rear->next=NewNode;
Q->rear=NewNode;
return(TRUE);
}
else return(FALSE); /* 溢出!*/
}

/*出队操作。*/
int DeleteQueue(LinkQueue *Q,QueueElementType *x)
{
/* 将队列Q的队头元素出队,并存放到x所指的存储空间中 */
LinkQueueNode * p;
if(Q->front==Q->rear)
return(FALSE);
p=Q->front->next;
Q->front->next=p->next; /* 队头元素p出队 */
if(Q->rear==p) /* 如果队中只有一个元素p,则p出队后成为空队 */
Q->rear=Q->front;
*x=p->data;
free(p); /* 释放存储空间 */
return(TRUE);
}

int IsEmpty(LinkQueue *Q)
{
if(Q->front==Q->rear)
return(TRUE);
else
return(FALSE);
}

#define ElemType char
#define MAXSIZE 100 /*此处的宏定义常量表示线性表可能达到的最大长度*/
typedef struct
{
ElemType elem[MAXSIZE]; /*线性表占用的数组空间*/
int last; /*记录线性表中最后一个元素在数组elem[ ]中的位置(下标值),空表置为-1*/
}SeqList;

void InitList(SeqList *L)
{
L->last=-1;
}

int AddTail(SeqList *L, ElemType e)
{
if(L->last>=MAXSIZE-1)
{
printf("表已满,无法添加!");
return ERROR;
}
L->elem[++L->last]=e;
return OK;
}

 

typedef enum{DG, DN, UDG, UDN} GraphKind; /*图的种类:DG表示有向图, DN表示有向网, UDG表示无向图, UDN表示无向网*/
typedef char VertexData; /*假设顶点数据为字符型*/

typedef struct ArcNode
{
int adj; /*对于无权图,用1或0表示是否相邻;对带权图,则为权值类型*/

} ArcNode;

typedef struct
{
VertexData vertex[MAX_Vertex_NUM]; /*顶点向量*/
ArcNode arcs[MAX_Vertex_NUM][MAX_Vertex_NUM]; /*邻接矩阵*/
int vexnum,arcnum; /*图的顶点数和弧数*/
GraphKind kind; /*图的种类标志*/
}AdjMatrix; /*(Adjacency Matrix Graph)*/

int LocateVertex(AdjMatrix *G,VertexData v) /*求顶点位置函数*/
{
int j=ERROR,k;
for(k=0;k<G->vexnum;k++)
if(G->vertex[k]==v)
{
j=k;
break;
}
return(j);
}

 


int CreateDN(AdjMatrix *G) /*创建一个有向网*/
{
int i,j,k,weight;
VertexData v1,v2;
printf("输入图的类型:0-有向图,1-有向网,2-无向图,3-无向网\n");
scanf("%d",&G->kind);
printf("\n 请输入图的总边数:");
scanf("%d",&G->arcnum);
printf("\n 请输入图的总顶点数:");
scanf("%d",&G->vexnum);
for(i=0;i<G->vexnum;i++)
for(j=0;j<G->vexnum;j++)
getchar();
printf("\n输入图的各顶点,以逗号相隔:");
for(i=0;i<G->vexnum;i++)
scanf("%c",&G->Vertex[i]);
getchar();
printf("\n输入无向图的每条边,以(v1,v2)的方式输入,边之间用“;”相隔:");
for(k=0;k<G->arcnum;k++)
{
scanf("%c,%c;",&v1,&v2);
i=LocateVertex(G,v1);
j=LocateVertex(G,v2);
G->arcs[i][j]=1;
G->arcs[j][i]=1;
}
printf("\n");
return(OK);
}

 


int visited[MAX_Vertex_NUM]; /*访问标志数组*/
/*用邻接矩阵方式实现深度优先搜索*/
void DepthFirstSearch(AdjMatrix g,int v0) /* 图g 为邻接矩阵类型AdjMatrix */
{ int vj;
visit(g,v0);
visited[v0]=TRUE;
for(vj=0;vj<g.vexnum;vj++)
if(!visited[vj]&&g.arcs[v0][vj].adj==1)
DepthFirstSearch(g,vj);
//请编程实现此函数功能;
}/* DepthFirstSearch */

/*用邻接矩阵方式实现广度优先搜索*/
void BreadthFirstSearch(AdjMatrix g,int v0)
{
int w;char x;
LinkQueue Q;
visit(g,v0);
visited[v0]=True;
InitQueue(&Q);
EnterQueue(&Q,g,v0);
while(!IsEmpty(&Q))
{
DeleteQueue(&Q,&x);
v0=LocateVertex(&g,x);
w=FirstAdjVertex(g,v0);
while(w!=-1)
{
if(!visited[w])
{
visit(g,w);
visited[w]=True;
EnterQueue(&Q,g,w);
}
w=NexAdjVertex(g,v0,w);
}
}
//请编程实现此函数功能;
}

void TraverseGraph1(AdjMatrix g)
/*对图g进行深度优先搜索*/
{
int vi;
for(vi=0;vi<g.vexnum;vi++)
visited[vi]=FALSE ;/*访问标志数组初始*/
for(vi=0;vi<g.vexnum;vi++) /*调用深度遍历连通子图的操作*/
if (!visited[vi])
DepthFirstSearch(g,vi); /*若图g是连通图,则此循环调用函数只执行一次*/
}/* TraverseGraph */

void TraverseGraph2(AdjMatrix g)
/*对图g进行广度优先搜索*/
{
int vi;
for(vi=0;vi<g.vexnum;vi++)
visited[vi]=FALSE ;/*访问标志数组初始*/
for(vi=0;vi<g.vexnum;vi++) /*调用深度遍历连通子图的操作*/
if (!visited[vi])
DepthFirstSearch(g,vi); /*若图g是连通图,则此循环调用函数只执行一次*/
}/* TraverseGraph */

#define INFINITY 32768
typedef unsigned int WeightType;
typedef SeqList VertexSet;

int Member(VertexData v, VertexSet s)
{
int i;
for(i=0;i<=s.last;i++)
if(s.elem[i]==v)
return TRUE;
return FALSE;
}

void ShortestPath_DJS(AdjMatrix g,int v0,WeightType dist[MAX_Vertex_NUM],VertexSet path[MAX_Vertex_NUM])
/* path[i]中存放顶点i的当前最短路径。dist[i]中存放顶点i的当前最短路径长度*/
{
int i,t,k;
unsigned int min;
VertexSet s; /*s为已找到最短路径的终点集合*/
for(i = 0; i < g.vexnum; i++)
{
InitList(&path[i]); /*初始化dist[i]和path[i]*/
dist[i] = g.arcs.[v0][i].adj; /*dist[i]初始放当前顶点i到v0的路径长度*/
if(dist[i] < INFINITY)
{ /*如果经过上一步权值存在(路径存在)*/
AddTail(&path[i], g.vertex[v0]); /*AddTail是表尾添加操作*/
AddTail(&path[i], g.vertex[i]); /*构造从v0到i的路径序列,存储在顺序表数组的第i行*/
}
}
InitList(&s);
AddTail(&s, g.vertex[v0]); /*将v0看成第一个已找到最短路径的终点*/
for(t = 1; t <= g.vexnum - 1; t++)
{ /*求v0到其余n-1个顶点额最短路径(n=g.vexnum)*/
min = INFINITY;
for(i = 0; t <= g.vexnum; i++)
{
if(!Member(g.vertex[i], s) && dist[i] < min) {//该点不存在s集合中且该点到v0的路径存在
k = i; min = dist[i];
}
}
if(min == INFINITY) return; //如果经过上步没有修改min的值,说明当前顶点到v0没有路径 回退
AddTail(&s, g.vertex[k]); //把当前顶点加到s集合中
for(i = 0; i < g.vertex; i++)
{
//如果该顶点不在s集合中且路径存在且该点通过已经加进s集合的点建立的新路径长度小于原路径
if(!Member(g.vertex[i], s) && g.arcs[k][i].adj != INFINITY
&& (dist[k] + g.arc[k][i].adj < dist[i]))
{
dist[i] = dist[k] + g.arcs[k][i].adj; //修改dist[i]为即最新的最短路径长度
path[i] = path[k]; //更新路径
AddTail(&path[i], g.vertex[i]); /*path[i] = path[k]∪{vi}*/
}
}
}
//请编程实现此函数功能;

void print(AdjMatrix G,VertexSet s[])
{
int i,j;
for(i=0;i<G.vexnum;i++)
{
if(s[i].last==-1)
printf("到%c点没有路径。\n",G.Vertex[i]);
else
{
for(j=0;j<=s[i].last;j++)
printf("%c->",s[i].elem[j]);
printf("\b\b \n");
}
}
}

void main()
{
AdjMatrix G; //采用邻接表结构的图
char sp;
int choice,flag=1,v0;
WeightType dist[MAX_Vertex_NUM];
VertexSet path[MAX_Vertex_NUM];

printf("本程序实现图的操作:\n");
printf("可以进行创建图, 深度优先、广度优先操作,实现最短路径查找等的应用。\n");

while(flag)
{
printf("请选择: \n");
printf("1.创建图\n");
printf("2.深度优先遍历\n");
printf("3.广度优先遍历\n");
printf("4.最短路径查找\n");
printf("5.退出程序\n");
scanf("%d",&choice);
switch(choice)
{
case 1:
CreateDN(&G);
break;
case 2:
if(G.kind==DN||G.kind==UDN)
printf("此为加权网!不适合遍历。\n");
else
{
TraverseGraph1(G);
printf("\b\b \n");
}
break;
case 3:
if(G.kind==DN||G.kind==UDN)
printf("此为加权网!不适合遍历。\n");
else
{
TraverseGraph2(G);
printf("\b\b \n");
}
break;
case 4:
printf("输入源点:\n");
fflush(stdin);
scanf("%c",&sp);
v0=LocateVertex(&G,sp);
ShortestPath_DJS(G,v0,dist,path);
print(G,path);
break;
default:
flag=0;
printf("程序结束,按任意键退出!\n");
}
}
}

转载于:https://www.cnblogs.com/dnwjafg/p/8032424.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值