欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

图的深度优先遍历和广度优先遍历

程序员文章站 2022-05-21 21:05:02
...

最近几天在复习数据结构的考试,也算是一个查缺补漏的过程,所以手写代码记录一下.另外因为c/c++类中实参与形参最好不能重名的问题,困扰了许久,也是醉了.

函数指针void (*visit)可以接收一个函数名,将函数作为参数,类似于python里的函数式编程.
指针函数int *visit的返回值是一个地址值。函数返回值必须用同类型的指针变量来接受,也就是说,指针函数一定有函数返回值,而且,在主调函数中,函数返回值必须赋给同类型的指针变量。

下面记录一下,在c/c++中,成员函数与成员形参不能同名,

class A
{
private:
    int a;
public:
    A(int a){a=a;}  //该方法不行,形参a的作用域将覆盖成员变量的作用域,所以成员变量a不会被赋值
}

接下来是图的两种遍历方法
第一种是DFS(深度优先遍历),采用递归的方式从一个顶点不断访问他的最近的邻接顶点,直到末端再返回到有其他其他邻接点的顶点处进行递归

template<class T>
void AdjListUndirGraph<T>::DFS(int v,void (*(visit)(const T &e)))const
{
    SetTag(v,true);
    T e;
    GetElem(v,e);
    (*visit)(e);
    for(int w=FirstAdjVex(v);w>=0;w=NextAdjVex(v,w))
        if(!GetTag(w))
            DFS(w);
}
template<class T>
void AdjListUndirGraph<T>::DFSTraverse(void (*(visit)(const T &e)))const
{
    int v;
    for(v=0;v<GetVexNum();v++)
        SetTag(v,false);
    for(v=0;v<GetVexNum();v++)
        if(!GetTag(v))
            DFS(v,visit);
}

第二种是BFS(广度优先遍历),将一个顶点的所有邻接顶点入队访问,再依次出队,接着继续将邻接顶点的邻接顶点入队,再依次出队,不断重复,直到访问结束.

template<class T>
void AdjListDirGraph<T>::BFS(int v,void (*visit)(const T &e))const
{
    SetTag(v,true);
    T e;
    GetElem(v,e);
    (*visit)(e);
    LinkQueue q;
    q.InQueue(v);
    while(!q.Empty())
    {
        int u,w;
        q.OutQueue(u);
        for(w=FirstAdjVex(u);w>=0;w=NextAdjVex(u,w))
            if(!GetTag(w))
            {
                SetTag(w,true);
                GetElem(w,e);
                (*visit)(e);
                q.InQueue(w);
            }
}
template<class T>
void AdjListDirGraph<T>::BFSTraverse(void (*visit)(const T &e))const
{
    int v;
    for(v=0;v<GetVexNum;v++)
        SetTag(v,false);
    for(v=0;v<GetVexNum;v++)
        if(!GetTag(v))
            BFS(v,visit);
}