深度遍历和广度遍历图

#include
#include
#include
#define Ok 1
#define True 1
#define False 0
#define Error -1
#define Queue_Size 100
#define Stack_Size 100
#define MAX_VERTEX_NUM 100
typedef enum{DG} GraphKind; //图的类型
typedef char VertexData; //图的结点的类型
typedef int StackElementType; //存放栈元素的数组的类型

int visited[MAX_VERTEX_NUM]; //标记数组,用来存放图中每个顶点是否被访问的信息,初值为0,访问后的顶点的对应数组元素的值就置为1

typedef struct
{
int element[Queue_Size];
int front;
int rear;
}SeqQueue; //循环队列的结构体

typedef struct
{
StackElementType elem[Stack_Size];
int top;
}SeqStack; //顺序栈的结构体

typedef struct ArcNode
{
int adj;
//int info; //这个不需要
int adjvex;
struct ArcNode *nextarc;
}ArcNode; //邻接矩阵和邻接表的弧结点结构体

typedef struct
{
VertexData vexs[MAX_VERTEX_NUM];
ArcNode arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int vexnum,arcnum;
}AdjMatrix; //邻接矩阵结的构体

typedef struct VertexNode
{
VertexData data;
ArcNode *firstarc;
}VertexNode; //表头结点结构体

typedef struct
{
VertexNode vertex[MAX_VERTEX_NUM];
int vexnum,arcnum;
}AdjList; //邻接表的结构体

void InitStack(SeqStack *S) //置空栈
{
S->top=-1;
}

int IsEmpty(SeqStack *S) //判栈是否为空,如果是空,返回1;否则返回0
{
return(S->top==-1? True:False);
}

int PushStack(SeqStack *S,StackElementType x) //压栈操作
{
if(S->top==Stack_Size-1)
return False;
S->top++;
S->elem[S->top]=x;
return True;
}

int Pop(SeqStack *S,StackElementType *x) //出栈操作
{
if(S->top==-1)
return False;
else
{
*x=S->elem[S->top];
S->top--;
return True;
}
}

int LocateVertex(AdjMatrix *G, VertexData v) //求邻接矩阵中相应顶点的位置
{
int j,k;
for(k=0;kvexnum;k++)
{
if(G->vexs[k]==v)
{
j=k;
break;
}
}
return(j);
}

int Locate(AdjList *L,VertexData v) //求邻接表中相应顶点的位置
{
int i;
for(i=1;i<=L->vexnum;i++)
if(L->vertex[i].data==v)
return i;
return -1;
}

int EnterQueue(SeqQueue *Q,int x) //入队操作
{
if((Q->rear+1)%Queue_Size==Q->front)
return(False);
Q->element[Q->rear]=x;
Q->rear=(Q->rear+1)%Queue_Size;
return(True);
}

int DeleteQueue(SeqQueue *Q,int *x) //出队操作
{
if(Q->front==Q->rear)
return(False);
*x=Q->element[Q->front];
Q->front=(Q->front+1)%Queue_Size;
return(*x);
}

int FirstAdjVertex(AdjMatrix *G,int k) //在邻接矩阵中求第一个结点
{
int i;
if(k>=0&&kvexnum) //判断k结点在不在图中
{
for(i=0;ivexnum;i++) //找遍图中所有的顶点
if(G->arcs[k][i].adj!=0) //在邻接矩阵中找与k结点有边相连的结点(k只是结点在图中的位置,并不

真正表示结点,这个结点的真正表示是vexs[k],为了方便起见,我就用结点的位置(序号)表示结点。这个看不懂,可以问问你们舍长)
return i;
}
return(Error);

}

int NextAdjVertex(AdjMatrix *G,int i,int j) //求下一个邻接点
{
int k;
if(i>=0&&ivexnum&&j>=0&&jvexnum) //判断结点i,j是否在图中
{
for(k=j+1;kvexnum;k++) //找遍图中所有的顶点,注意,结点k是i的下一个邻接点
if(G->arcs[i][k].adj!=0) //表示结点i与结点k有边相连
return k;
}
return(Error);
}

int CreateDG(AdjMatrix *G) //创建一个有向图,此图基于邻接矩阵的存储结构
{
int i,j,k,w;
VertexData v1,v2;
printf("请输入有向图(此图以邻接矩阵作为存储结构)的顶点数和边数:");
scanf("%d,%d",&G->vexnum,&G->arcnum);
for(i=0;ivexnum;i++)
for(j=0;jvexnum;j++)
{
G->arcs[i][j].adj=0; //初始化邻接矩阵,全部为0
//G->arcs[i][j].info=NULL; //这一行可以不要
}
for(i=0;ivexnum;i++)
{
printf("请输入图的一个顶点:");
scanf("\n%c",&G->vexs[i]); //初始化图的结点信息
}
for(k=0;karcnum;k++) //搭建边以及给边赋权值
{
printf("请输入图中边的端点以及边的权值:");
scanf("\n%c\n%c\n%d",&v1,&v2,&w);
i=LocateVertex(G,v1); //找到输入结点v1所在图中的位置
j=LocateVertex(G,v2); //找到输入结点v2所在图中的位置
G->arcs[i][j].adj=w; //赋边的权值
}
return(True);
}

void CreateDG(AdjList *L) //创建一个有向图,此图基于邻接表的存储结构
{
int i,j,k;
char v1,v2;
ArcNode *p;
printf("请输入有向图(此图以邻接表作为存储结构)的顶点数和边数:");
scanf("%d,%d",&L->vexnum,&L->arcnum);
getchar(); //接受回车
for(i=1;i<=L->vexnum;i++)
{
printf("请输入图的一个顶点:");
scanf("%c",&L->vertex[i].data); //初始化图的结点
getchar(); //接受回车,下面的getchar()都是这个意思
L->vertex[i].firstarc=NULL;
}
for(k=1;k<=L->arcnum;k++)
{
printf("请输入图中一条边的两个端点:");
scanf("%c,%c",&v1,&v2);
getchar();
i=Locate(L,v1); //找到输入结点v1所在图中的位置
j=Locate(L,v2); //找到输入结点v1所在图中的位置
p=(ArcNode *)malloc(sizeof(ArcNode));
p->adjvex=j; //把找出的与顶点相邻的结点在图中的位置放到弧结点的邻接点域当中
p->nextarc=L->vertex[i].firstarc; //采用头插法
L->vertex[i].firstarc=p;
}
}

void visit(AdjMatrix *G,int i) //打印图的结点
{
printf("%c ",G->vexs[i]);
}

void InitQueue(SeqQueue *Q) //初始化循环队列
{
Q->front=Q->rear=0;
}

void DepthFirstSearch(AdjMatrix *G,int i) //深度遍历i所在的连通子图
{
int j;
visit(G,i); //访问结点i
visited[i]=True; //给访问标志数组赋1,表示结点i已经

访问过了
for(j=0;jvexnum;j++)
if(!visited[j]&&G->arcs[i][j].adj==1) //如果结点j没有被访问,并且结点j与结点i有边相连
DepthFirstSearch(G,j); //递归调用此函数
}

void BreadthFirstSearch(AdjMatrix *G,int i) //广度遍历i所在的连通子图
{
int w;
SeqQueue *Q;
Q=(SeqQueue *)malloc(sizeof(SeqQueue));
visit(G,i); //访问结点i
visited[i]=True; //给访问标志数组赋1,表示结点i已经访问过了
InitQueue(Q);
EnterQueue(Q,i); //将访问过的结点i入队列
while(Q->front!=Q->rear) //只要队列布控,这个循环不会停止
{
DeleteQueue(Q,&i); //出队列
w=FirstAdjVertex(G,i); //求结点i的第一个邻接点并赋给w
while(w!=-1) //只要i的邻接点存在
{
if(!visited[w]) //如果w(i的第一个邻接点)没有被访问
{
visit(G,w); //访问结点点w
visited[w]=True; //置1表示w已经访问过了
EnterQueue(Q,w); //将访问过的结点w入队列
}
w=NextAdjVertex(G,i,w); //找结点i相对于w的下一个邻接点
}
}
}

void PrintfGraph(AdjMatrix *G) //打印邻接矩阵以表示建图成功
{
int i,j;
printf(" ");
for(i=0;ivexnum;i++)
printf("%c ",G->vexs[i]); //打印出一列结点(如A B C D E F ……)
printf("\n");
for(i=0; ivexnum;i++)
{
printf("%c",G->vexs[i]); //打印出每行的结点(每行的开头)
for(j=0;jvexnum;j++)
printf("%d ",G->arcs[i][j].adj); //打印出对应的权值,没有权值的打印出0
printf("\n");
}
}

void PrintfGraph(AdjList *L) //打印图的邻接表以表示建图成功
{
int i;
ArcNode *p;
for(i=1;i<=L->vexnum;i++)
{
printf("%d %c->",i,L->vertex[i].data); //按照书上的邻接表的形式,纵向打印出结点在图中的位置以及结点信息
p=(ArcNode *)malloc(sizeof(ArcNode));
p=L->vertex[i].firstarc; //将指针p指向与结点i有关联的第一条弧
while(p)
{
printf("%d->",p->adjvex); //打印出每行的边表信息
p=p->nextarc; //p指针后移
}
printf("NULL\n");
}
}

void DepthFirstTraverseGraph(AdjMatrix *G) //图的深度遍历
{
int i;
for(i=0;ivexnum;i++)
visited[i]=False; //给标志数组赋初值,都是0
for(i=0;ivexnum;i++)
{
if(!visited[i])
DepthFirstSearch(G,i); //如果没有被访问过,递归深度遍历这个图
}
}

void BreadthFirstTraverseGraph(AdjMatrix *G) //图的广度遍历
{
int i;
for(i=0;ivexnum;i++)
visited[i]=False; //给标志数组赋初值,都是0
for(i=0;ivexnum;i++)
{
if(!visited[i])
BreadthFirstSearch(G,i); //如果没有被访问过,递归广度遍历这个图
}
}

void FindID(AdjList *L,int in_degree[MAX_VERTEX_NUM]) //求图中每个顶点的入度
{
int i;
ArcNode *p;
for(i=1;i<=L->vexnum;i++)
in_degree[i]=0;
for(i=1;i<=L->vexnum;i++) //这个算法的思想我上次给你了
{
p=

L->vertex[i].firstarc;
while(p!=NULL)
{
in_degree[p->adjvex]++;
p=p->nextarc;
}
}
}

int TopoSort(AdjList *L) //拓扑排序
{
SeqStack S;
int i,k,count;
int in_degree[MAX_VERTEX_NUM];
ArcNode *p;
FindID(L,in_degree);
InitStack(&S);
for(i=1;i<=L->vexnum;i++)
if(in_degree[i]==0)
PushStack(&S,i);
count=0;
printf("该图的拓扑序列是");
while(!IsEmpty(&S)) //这个算法的思想我上次也给你了
{
Pop(&S,&i);
printf(" %c",L->vertex[i].data);
count++;
p=L->vertex[i].firstarc;
while(p!=NULL)
{
k=p->adjvex;
in_degree[k]--;
if(in_degree[k]==0)
PushStack(&S,k);
p=p->nextarc;
}
}
if(countvexnum)
return Error;
else
return Ok;
}

void Menu() //菜单,这个原样输出
{
printf("--------------------------TraverseGraph(G)--------------------------\n");
printf(" 1.PrintfGraph(G)\n");
printf(" 2.DepthFirstTraverseGraph(G)\n");
printf(" 3.BreadthFirstTraverseGraph(G)\n");
printf(" 4.Topological Sort\n");
printf(" 5.exit(0)\n");
}

void main() //主函数
{
int leap; //定义leap变量是用来接收你选择的选项,如1,2,3,4,5等等
AdjMatrix *G;
AdjList *L;
G=(AdjMatrix *)malloc(sizeof(AdjMatrix));
L=(AdjList *)malloc(sizeof(AdjList));
//clrscr();
CreateDG(G);
printf("\n");
CreateDG(L);
Menu();
printf("\n请从上述菜单选择选项:");
scanf("%d",&leap);
while(1)
{
switch(leap)
{
case 1:
printf("下面是基于邻接矩阵作为其存储结构的图的打印:\n");
PrintfGraph(G); //C++中允许函数重载
printf("下面是基于邻接表作为其存储结构的图的打印:\n");
PrintfGraph(L);break; //C++中允许函数重载
case 2:
DepthFirstTraverseGraph(G);break;
case 3:
BreadthFirstTraverseGraph(G);break;
case 4:
TopoSort(L);break;
case 5:
exit(0);break;
default:
printf("您的输入有误,请核实后再输,谢谢……");
}
printf("\n\n请从上述菜单选择选项:");
scanf("%d",&leap);
}
}

相关文档
最新文档