使用到的数据结构说明:
邻接表的形式说明
typedef struct node{//边表结点
int adjvex; //邻接点域
struct node *next; //链域
//若要表示边上的权,则应增加一个数据域
}EdgeNode;
typedef struct vnode{ //顶点表结点
VertexType vertex; //顶点域
EdgeNode *firstedge;//边表头指针
}VertexNode;
typedef VertexNode AdjList[MaxVertexNum];//AdjList是邻接表类型
typedef struct{
AdjList adjlist;//邻接表
int n,e; 图中当前顶点数和边数
}ALGraph;
一.广度优先遍历
图的广度优先遍历是:对于每个结点而言先遍历其的兄弟结点,然后遍历其子节点。使用队列完成
假设图的数据结构为邻接表。
程序流程:
1.创建并初始队列
2.假如从V1结点开始遍历图,则输出V1,并将v1入队列
3.v1从队列中删除(以下3-5为循环体内的执行步骤)
4.循环遍历v1的所有邻接节点,对于v1的邻接节点,所示已经访问过,则跳过,否则,访问,并入队列。
5.第4步循环结束,则令指针指向下一个结点
6.当指针不为空时,循环3-5步。
代码:
void BFS(ALGraph* G,int k)//表示从Vk结点开始遍历
{
Queue Q;
EdgeNode *p;
InitQueue(&Q);
//访问源点Vk
printf(G->adjlist[k].vertex);
visited[k = true];//将k结点对应的标志设置为已遍历
EnQueue(k);//k结点入队列
while(!QueueEmpty(Q))
{
i = DeQueue(&Q);//上一个元素出队列
p = G->adlist[i].fistage;
while(p != NULL)
{
if(!visited[p->vertex])
{
printf(p->vertex);
visited[p->vertex] = true;
EnQueue(p->vertex);
}
p = p->next;
}
}
}
二.图的深度优先遍历
图的数据结构仍然使用邻接表
用栈实现深度优先遍历伪代码:
1.初始化栈
2.若第一个元素不为空,输出他,并压入栈
3.while(栈不为空)
{
1.取出栈顶的元素,但是不要将其出栈
2.遍历该元素的相邻结点是否有未被标记访问。若有,则访问,并标记为已访问,然后压入栈。
若都已经访问过,则将栈顶元素出栈
}
代码:
void DFS(ALGraph* G,int k)
{
Stack s;
InitStack(s);
EdgeNode* p;
int i;
if(!visited[G->adlist[k].vertex] && G!=NULL)
{
printf(G->adlist[k].vertex);
push(k);
}
while(!StackEmpty(s))//栈不为空说明还有节点未被访问
{
i = getTop(s);
p = G->adlist[i]->fistage;
while(p!=NULL)//遍历p节点的子节点,若是查到有未被访问的则结束循环
{
if(!visited[p->vertex])
{
visited[p->vertex] = true;
printf(p->vertex);
push(p->vertex);
break;
}
}
if(p == NULL)//这说明p节点所有子节点已经全部访问过,故需要弹出栈顶元素,那么下次循环时,p就指向前一个节点
{
pop(s);
}
}
}