数据结构。
上机实验:图的深度优先搜索遍历和广度优先搜索遍历。拓扑排序。
测试数据:
6 8
A B C D E F
A B
A C
A D
C E
C B
C E
D E
F D
F E
测试结果:
请输入图的顶点数,边数:6 8
请输入6个顶点的值:
A B C D E F
请输入8条弧的弧尾 弧头:
A B
A C
A D
C E
C B
C E
D E
F D
深度优先搜索遍历的结果为:
A D E C B F
广度优先搜索遍历的结果为:
A D C B E F
F A C B D E 为一个拓扑序列。
#include <stdio.h>
#include <stdlib.h>
#define MAX_VERTEX_NUM 20 //最大顶点数
#define stackinitsize 100
#define stackincrement 10
#define ok 1
#define error 0
#define overflow -1
typedef char VertexType; //顶点类型
typedef int status;
typedef int SElemType; //定义栈元素为整型
typedef int QElemType; //定义队列元素为整型
struct ElemType
{
int adjvex; //该弧所指向的顶点的位置,无其他弧信息
};
typedef struct ArcNode //表结点,存弧的信息
{
ElemType data; //除指针以外的部分都属于ElemType
ArcNode *nextarc; //指向下一条弧的指针
}ArcNode,*parcnode;
typedef struct //头结点,存顶点的信息
{
VertexType data; //顶点信息
ArcNode *firstarc; //第1个表结点的地址,指向第1条依附该顶点的弧的指针
}VNode,AdjList[MAX_VERTEX_NUM];
struct ALGraph //邻接表结构
{
AdjList vertices; //头结点(顶点)数组
int vexnum,arcnum; //图的当前顶点数和弧数
};
//栈的操作
typedef struct SqStack
{
SElemType *base;
SElemType *top;
int stacksize;
}SqStack;
status InitStack(SqStack &S)
{
S.base = (SElemType *)(malloc)(stackinitsize * sizeof(SElemType));
if(!S.base) exit(overflow);
S.top=S.base;
S.stacksize=stackinitsize;
return ok;
}
status 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(overflow);
S.top=S.base + S.stacksize;
S.stacksize += stackincrement;
}
*S.top++ =e;
return ok;
}
status Pop(SqStack &S,SElemType &e)
{
if(S.top==S.base) return error;
e =*--S.top;
return ok;
}
status StackEmpty(SqStack S)
{
if(S.top==S.base) return 1;
else return 0;
}
//链队列的操作
typedef struct QNode
{
QElemType data;
QNode *next;
}*QueuePtr;
struct LinkQueue
{
QueuePtr front,rear;
};
void InitQueue(LinkQueue &Q)
{
Q.front=Q.rear=(QueuePtr)malloc(sizeof(QNode));
if(!Q.front)
exit(overflow);
Q.front->next=NULL;
}
status QueueEmpty(LinkQueue &Q)
{
if(Q.front->next==NULL)
return 1;
else
return 0;
}
void EnQueue(LinkQueue &Q,QElemType e)
{
QueuePtr p;
p=(QueuePtr)malloc(sizeof(QNode));
if(!p) exit(overflow);
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
}
status DeQueue(LinkQueue &Q,QElemType &e)
{
QueuePtr p;
if(Q.front==Q.rear) return error;
p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p)
Q.rear=Q.front;
free(p);
return ok;
}
//图的操作
bool visited[MAX_VERTEX_NUM]; //访问标记数组
void ListInsert(parcnode &L,int i,ElemType e) //插入函数
{
parcnode s;
s=(ArcNode *)malloc(sizeof(ArcNode));
s->data=e;
s->nextarc=L;
L=s;
}
int LocateVex(ALGraph G,VertexType u)
{
int i;
for(i=0;i<G.vexnum;++i)
{
if(G.vertices[i].data==u) return i;
}
return -1;
}
void CreateGraph(ALGraph &G) //采用邻接表存储结构,构造有向图
{
int i,j,k;
ElemType e;
VertexType v1,v2;
printf("请输入图的顶点数,边数:");
scanf("%d%d",&G.vexnum,&G.arcnum);
getchar();
printf("请输入%d个顶点的值:\n",G.vexnum);
for(i=0;i<G.vexnum;++i)
{
scanf("%c",&G.vertices[i].data);
getchar();
G.vertices[i].firstarc=NULL;
}
printf("请输入%d条弧的弧尾 弧头:\n",G.arcnum);
for(k=0;k<G.arcnum;++k)
{
scanf("%c %c",&v1,&v2);
getchar();
i=LocateVex(G,v1); //弧头
j=LocateVex(G,v2); //弧尾
e.adjvex=j;
ListInsert(G.vertices[i].firstarc,1,e);
}
}
void Visit(VertexType e)
{
printf("%c ",e);
}
void DFS(ALGraph G,int v,void(*Visit)(VertexType)) //深度优先搜索遍历
{
ArcNode *p;
visited[v]=true;
Visit(G.vertices[v].data);
for(p=G.vertices[v].firstarc;p;p=p->nextarc)
if(!visited[p->data.adjvex])
DFS(G,p->data.adjvex,Visit);
}
void DFSTraverse(ALGraph G,void(*Visit)(VertexType))
{
int v;
for(v=0;v<G.vexnum;++v)
visited[v]=false;
for(v=0;v<G.vexnum;++v)
{
if(!visited[v])
DFS(G,v,Visit);
}
printf("\n\n");
}
void BFSTraverse(ALGraph G,void(*Visit)(VertexType)) //广度优先搜索遍历
{
ArcNode *p;
LinkQueue Q;
int v,u;
for(v=0;v<G.vexnum;++v)
visited[v]=false;
InitQueue(Q);
for(v=0;v<G.vexnum;++v)
{
if(!visited[v])
{
visited[v]=true;
Visit(G.vertices[v].data);
EnQueue(Q,v);
while(!QueueEmpty(Q))
{
DeQueue(Q,u);
for(p=G.vertices[u].firstarc;p;p=p->nextarc)
if(!visited[p->data.adjvex])
{
visited[p->data.adjvex]=true;
Visit(G.vertices[p->data.adjvex].data);
EnQueue(Q,p->data.adjvex);
}
}
}
}
printf("\n\n");
}
//拓扑排序
int indegree[MAX_VERTEX_NUM];
void FindInDegree(ALGraph G)
{
int i;
ArcNode *p;
for(i=0;i<G.vexnum;++i)
indegree[i]=0;
for(i=0;i<G.vexnum;++i)
{
p=G.vertices[i].firstarc;
while(p)
{
indegree[p->data.adjvex]++;
p=p->nextarc;
}
}
}
status TopologicalSort(ALGraph G)
{
int i,k,count=0;
SqStack S;
ArcNode *p;
FindInDegree(G);
InitStack(S);
for(i=0;i<G.vexnum;++i)
if(!indegree[i])
Push(S,i);
while(!StackEmpty(S))
{
Pop(S,i);
Visit(G.vertices[i].data);
++count;
for(p=G.vertices[i].firstarc;p;p=p->nextarc)
{
k=p->data.adjvex;
if(!(--indegree[k]))
Push(S,k);
}
}
if(count<G.vexnum)
{
printf("此图存在回路\n");
return error;
}
else
{
printf("为一个拓扑序列。\n");
return ok;
}
}
int main()
{
ALGraph g;
CreateGraph(g);
printf("深度优先搜索遍历的结果为:\n");
DFSTraverse(g,Visit);
printf("广度优先搜索遍历的结果为:\n");
BFSTraverse(g,Visit);
TopologicalSort(g);
return 0;
}