1、和树的遍历类似,我们希望从图中某一顶点出发遍历访问图中其余顶点,且使每一个顶点仅被访问一次。
分为深度优先与广度优先:
--------------------------------------------------------------------------------------------------------------------------------
代码:
#include<stdio.h>
#include<stdlib.h>
#include<limits.h>
#define ERROR 0
#define OK 1
#define INFINITY INT_MAX //最大值
#define MAX_VERTEX_NUM 21 //最大顶点个数
bool visited[MAX_VERTEX_NUM];
typedef enum{ DG,DN,UDG,UDN } GraphKind; //{有向图,有向网,无向图,无向网}
//--------图的邻接表存储表示---------------//
typedef struct ArcNode{
int adjvex; //该弧所指向的顶点的位置
int quan;
struct ArcNode *nextarc; //指向下一条弧的指针
}ArcNode,*AList; //表结点
typedef struct VNode{
char data; //顶点信息
AList firstarc; //指向第一条依附该顶点的弧的指针
}VNode,AdjList[MAX_VERTEX_NUM]; //头结点
typedef struct{
AdjList vertices;
int vexnum,arcnum; //图的当前顶点数和弧数
GraphKind kind; //图的种类标志
}ALGraph;
//--------------队列与栈的操作----------------//
typedef struct QNode{
char data;
struct QNode *next;
}QNode,*QueuePre;
typedef struct{
QueuePre front; //头指针
QueuePre rear; //尾指针
}LinkQueue; //队列
typedef struct{
int *base;
int *top;
int stacksize;
}SqStack; //栈
//----------------------------------------//
//队列的创建
int InitQueue(LinkQueue &Q){
Q.front=Q.rear=(QueuePre)malloc(sizeof(QNode));
if(!Q.front) return ERROR;
Q.front->next=NULL;
return OK;
}
//元素入队
int EnQueue(LinkQueue &Q,int e){
QueuePre p;
p=(QueuePre)malloc(sizeof(QNode));
if(!p) return OK;
p->data=e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
return OK;
}
//元素除队列
int DeQueue(LinkQueue &Q,int &e){
QueuePre p;
if(Q.front==Q.rear) return ERROR;
p=Q.front->next;
e=p->data;
Q.front->next=p->next; //将队列的下一元素赋值给 Q.front
if(Q.rear==p)
Q.rear=Q.front;
free(p);
return OK;
}
//判断队列是否为空
int QueueEmpty(LinkQueue Q){
if(Q.front==Q.rear)
return OK;
return ERROR;
}
//邻接表顶点定位
int LocateVex(ALGraph G,char v){
int m;
for(m=1;m<=G.vexnum;m++){
if(G.vertices[m].data==v)
return m;
}
printf("你输入的顶点不存在!");
return ERROR;
}
//创建无向图邻接表
int CreatAList(ALGraph &G){
int i,j,m,n,key[MAX_VERTEX_NUM];
char x,y;
AList p,q;
printf("邻接表,请输入顶点的个数和弧个数:");
scanf("%d %d",&G.vexnum,&G.arcnum);
if(G.vexnum>20){ //顶点个数过多
printf("你输入的顶点个数超过最大值");
return ERROR;
}
printf("请输入 %d 个顶点数:\n",G.vexnum);
for(i=1;i<=G.vexnum;i++){
fflush(stdin);
scanf("%c",&G.vertices[i].data); //构造顶点向量的值
G.vertices[i].firstarc=NULL; //指向下一条弧的指针 先初始化为 NULL
key[i]=0; //
}
printf("请输入弧(如 A B ,其中 AB 与 BA是不同的弧):");
for(j=1;j<=2*G.arcnum;j++){ //输入弧
fflush(stdin);
scanf("%c %c",&x,&y);
m=LocateVex(G,x); //定位
n=LocateVex(G,y);
p=G.vertices[m].firstarc; // AList p,q
q=(AList)malloc(sizeof(ArcNode));
if(!q) return ERROR;
q->nextarc=NULL; //q初始化的过程
q->adjvex=n;
while(key[m] && p->nextarc){
p=p->nextarc;
key[m]++;
}
if(!key[m]){ //key[m]为0
G.vertices[m].firstarc=q;
key[m]++;
}
else
p->nextarc=q;
}
return OK;
}
//打印输出
int OutPut(ALGraph G2){
int i,j;
AList s;
printf("无向图的邻接表: \n");
for(i=1;i<=G2.vexnum;i++){ //将邻接表输出
printf("%c",G2.vertices[i]);
s=G2.vertices[i].firstarc;
while(s){
j=s->adjvex; //该顶点在数组中的位置
fflush(stdin);
printf("(%c",G2.vertices[i]);
printf(",%c)",G2.vertices[j]);
s=s->nextarc;
}
printf("\n");
}
return OK;
}
//返回数组指针 的 第一个位置
int FirstAdjVex(ALGraph G,int v){
if(G.vertices[v].firstarc)
return G.vertices[v].firstarc->adjvex;
return 0;
}
int NextAdjVex(ALGraph G,int v,int w){
AList s;
s=G.vertices[v].firstarc;
while(s->adjvex != w)
s=s->nextarc;
if(s->nextarc)
return s->nextarc->adjvex;
return 0;
}
//从第 v 个顶点出发递归地深度优先遍历图G
void DFS(ALGraph G,int v){
int w;
visited[v]=1; //访问第 v 个顶点
printf("%c",G.vertices[v]);
for(w=FirstAdjVex(G,v) ; w>=1 ; w=NextAdjVex(G,v,w)){
if(!visited[w])
DFS(G,w);
}
}
//深度优先遍历
int DFSTraverse(ALGraph G){
int v;
visited[0]=1; //使用全局变量 visited[],使 DFS 不必设函数指针参数
for(v=1;v<=G.vexnum;v++)
visited[v]=0; //访问标志数组初始化
for(v=1;v<=G.vexnum;v++) //对尚未访问的顶点调用 DFS
if(!visited[v])
DFS(G,v);
return OK;
}
//广度优先遍历
int BFSTraverse(ALGraph G){
int v,w,u;
LinkQueue Q;
for(v=1;v<=G.vexnum;v++)
visited[v]=0; //初始化为0
visited[0]=1;
InitQueue(Q);
for(v=1;v<=G.vexnum;v++)
if(!visited[v]){ //如果visited[v]没有被访问过
visited[v]=1;
printf(" %c",G.vertices[v]);
EnQueue(Q,v);
while(!QueueEmpty(Q)){
DeQueue(Q,u);
for(w=FirstAdjVex(G,u);w>=1;w=NextAdjVex(G,u,w)){
if(!visited[w]){
visited[w]=1;
printf(" %c",G.vertices[w]);
EnQueue(Q,w);
}
else
break;
}
}
}
return OK;
}
//主函数
void main(){
ALGraph G;
CreatAList(G);
OutPut(G);
printf("无向图的深度优先遍历: \n");
DFSTraverse(G);
printf("\n\n");
printf("无向图的广度优先遍历: \n");
BFSTraverse(G);
}