NOJ-基于图的深度优先搜索策略-西工大数据结构

    昨天讲了图,睡着了,今天运动会学了一下,回来写了一道。题目如下:


    看一下题目,就是用领接表构建一个图,再寻找是否有特定的路径。

    邻接表也没什么好说的,每个顶点节点存储相连接的边的信息。那么3 3    1 2 3    1 2     1 3     2 1可以构建下面的图:


    深度搜索中,我使用了回溯和递归,记录下已走过的顶点,避免走进死循环,若找到路径,直接返回1,否则返回0,以便后续的输出,寻找1 3的步骤如下:


    以下是我的实现:

#include <stdio.h>
#include <stdlib.h>

struct edgeNode
{
    int headVex;
    struct edgeNode *next;
};

struct vexNode
{
    int vex;
    struct edgeNode *head;
};

struct graphList
{
    struct vexNode vex[3000];
    int vexNum;
    int edgeNum;
};

void run ();
void createNewGraphList (struct graphList *gList);
void clearVexNodes (struct graphList *gList);
int findVex (int vex,struct graphList *gList);
void createNewEdgeNode (int n,struct graphList *gList);
void existWay (struct graphList *gList);
int depthFirstSearch (char flags[],struct graphList *gList,int cur,int find);

int main()
{
    run ();
    return 0;
}

void run ()
{
    struct graphList gList;
    createNewGraphList (&gList);
    existWay (&gList);
}

void createNewGraphList (struct graphList *gList)
{
    scanf ("%d%d",&(gList->vexNum),&(gList->edgeNum));

    clearVexNodes (gList);

    int i;
    for (i=0;i<gList->vexNum;i++)
    {
        scanf ("%d",&(gList->vex[i].vex));
    }

    int vex,n;
    for (i=0;i<gList->edgeNum;i++)
    {
        scanf ("%d",&vex);
        n=findVex (vex,gList);
        createNewEdgeNode (n,gList);
    }
}

void clearVexNodes (struct graphList *gList)
{
    int i;
    for (i=0;i<gList->vexNum;i++)
    {
        gList->vex[i].vex=0;
        gList->vex[i].head=NULL;
    }
}

int findVex (int vex,struct graphList *gList)
{
    int i;
    for (i=0;i<gList->vexNum;i++)
    {
        if (vex==gList->vex[i].vex)
        {
            return i;
        }
    }
    return -1;
}

void createNewEdgeNode (int n,struct graphList *gList)
{
    struct edgeNode *p,*q;
    int vex;
    p=(struct edgeNode *)malloc(sizeof(struct edgeNode));
    scanf ("%d",&vex);
    p->headVex=findVex (vex,gList);
    p->next=NULL;
    if (gList->vex[n].head==NULL)
    {
        gList->vex[n].head=p;
    }
    else
    {
        q=gList->vex[n].head;
        while (q->next)
        {
            q=q->next;
        }
        q->next=p;
    }
}

void existWay (struct graphList *gList)
{
    int vi,cur,find;
    scanf ("%d%d",&vi,&find);
    cur=findVex (vi,gList);
    char flags[3000]={0};
    if (depthFirstSearch (flags,gList,cur,find))
    {
        printf ("yes");
    }
    else
    {
        printf ("no");
    }
}

int depthFirstSearch (char flags[],struct graphList *gList,int cur,int find)
{
    struct edgeNode *p;
    int nextCur;
    if (gList->vex[cur].vex==find)
    {
        return 1;
    }
    else
    {
        flags[cur]=1;
        p=gList->vex[cur].head;
        while (p)
        {
            if (!flags[p->headVex])
            {
                nextCur=p->headVex;
                if (depthFirstSearch (flags,gList,nextCur,find))
                {
                    return 1;
                }
            }
            p=p->next;
        }
        flags[cur]=0;
        return 0;
    }
}
    以下是个函数的注释:

void run ()
{
    struct graphList gList;
    createNewGraphList (&gList);//创建图
    existWay (&gList);//是否存在路径
}
void createNewGraphList (struct graphList *gList)
{
    scanf ("%d%d",&(gList->vexNum),&(gList->edgeNum));//输入顶点数,边数

    clearVexNodes (gList);//清空所有顶点节点

    int i;
    for (i=0;i<gList->vexNum;i++)//遍历输入顶点
    {
        scanf ("%d",&(gList->vex[i].vex));
    }

    int vex,n;
    for (i=0;i<gList->edgeNum;i++)//遍历构建边表
    {
        scanf ("%d",&vex);//输入边尾(箭头尾,不是箭头尖)
        n=findVex (vex,gList);//得到边尾节点的位置
        createNewEdgeNode (n,gList);//在边尾的表中创建新的边节点
    }
}
void clearVexNodes (struct graphList *gList)
{
    int i;
    for (i=0;i<gList->vexNum;i++)//遍历清空
    {
        gList->vex[i].vex=0;
        gList->vex[i].head=NULL;
    }
}
int findVex (int vex,struct graphList *gList)
{
    int i;
    for (i=0;i<gList->vexNum;i++)//遍历寻找
    {
        if (vex==gList->vex[i].vex)//若找到就返回位置
        {
            return i;
        }
    }
    return -1;//否则返回-1
}
void createNewEdgeNode (int n,struct graphList *gList)
{
    struct edgeNode *p,*q;
    int vex;
    p=(struct edgeNode *)malloc(sizeof(struct edgeNode));//创建边节点
    scanf ("%d",&vex);
    p->headVex=findVex (vex,gList);//存入边头节点的位置
    p->next=NULL;//next设为空
    if (gList->vex[n].head==NULL)//若该顶点节点的边表为空
    {
        gList->vex[n].head=p;//表头就是新边节点
    }
    else//若不空
    {
        q=gList->vex[n].head;
        while (q->next)//找到最后一个边节点
        {
            q=q->next;
        }
        q->next=p;//加入新边节点
    }
}
void existWay (struct graphList *gList)
{
    int vi,cur,find;
    scanf ("%d%d",&vi,&find);//输入寻找的路径起点和终点
    cur=findVex (vi,gList);//起点的位置
    char flags[3000]={0};//初始化路径记录数组
    if (depthFirstSearch (flags,gList,cur,find))
    {
        printf ("yes");//若找到
    }
    else
    {
        printf ("no");//若未找到
    }
}
int depthFirstSearch (char flags[],struct graphList *gList,int cur,int find)
{
    struct edgeNode *p;
    int nextCur;
    if (gList->vex[cur].vex==find)//若当前节点是所找节点,返回1
    {
        return 1;
    }
    else
    {
        flags[cur]=1;//记录当前顶点走过
        p=gList->vex[cur].head;
        while (p)//遍历所有边节点
        {
            if (!flags[p->headVex])//若未走过
            {
                nextCur=p->headVex;
                if (depthFirstSearch (flags,gList,nextCur,find))//递归寻找,若以此顶点找到,返回1,剩下路径不找了
                {
                    return 1;
                }
            }
            p=p->next;
        }
        flags[cur]=0;//未找到,当前顶点标记未走过,返回上一顶点
        return 0;
    }
}
    

    以上就是我的实现。








猜你喜欢

转载自blog.csdn.net/qq_30180107/article/details/80067355