[置顶] 图的BFS、DFS算法实现

一、实现说明

 1、算法只针对连通图进行DFS和BFS的处理,只为更加清晰理解DFS和BFS算法的意义。

 2、图的数据结构采用邻接表,DFS采用递归(所以用到了隐形栈),BFS采用链式队列(不带头节点)。

3、邻接表的的弧节点的插入是头插法。请注意输入时的顺序。本图采用的例图是严蔚敏数据结构图那章的G1图。

 4、代码实现功能简单,如代码的健壮性没有考虑那么完善,欢迎指出。

二、c代码实现

#include <stdio.h>
#include <string.h>
#include <malloc.h>

#define MAX_VEX_NUM 20
#define TRUE 1
#define FALSE 0

#define OK 1
#define FAIL 0

int visited[MAX_VEX_NUM];
typedef int status;
typedef int q_elemtype;


/* 邻接表的数据结构 */
enum GraphyKind
{
    DG,
    DN,
    UDG,
    UDN
};

struct ArcNode 
{
    int adjvex_no;
    void *arcinfo;
    struct ArcNode *nextarc;
};

struct VNode 
{
    char data[3];
    struct ArcNode * firstarc; 
};

struct ALGraphy
{
    int vexnum;
    int arcnum;
    enum GraphyKind kind; 
    struct VNode *HeadNode;
};

/* 链队列的数据结构  */
struct QNode
{
    q_elemtype data; 
    struct QNode *next;
};

struct linked_queue
{
    struct QNode *front;
    struct QNode *rear;
};

status init_queue(struct linked_queue *Q)
{
    (*Q).front = (*Q).rear = NULL;

    return OK;
}

int queue_empty(struct linked_queue Q)
{
    if (!Q.rear && !Q.front)
    {
        return 1;
    }
    else
    {
        return 0;
    }

}

status enqueue(struct linked_queue *Q, q_elemtype elem)
{
    struct QNode *p;

    p = (struct QNode*)malloc(sizeof(struct QNode));
    if (!p)
    {
        return FAIL;
    }

    p->data = elem;
    p->next = NULL;
 
    if (queue_empty(*Q))
    {
        (*Q).front = (*Q).rear = p;
    }
    else
    {
        (*Q).rear->next = p; 
        (*Q).rear = p;
    }
   
    return OK;
} 

status dequeue(struct linked_queue *Q, q_elemtype *elem)
{
    struct QNode *p;

    if (queue_empty(*Q))
    {
        return FAIL;
    }
    else
    {
        p = (*Q).front;
        (*elem) = p->data;
        (*Q).front = p->next;

        if (!p->next)
        {
            (*Q).rear = NULL;
        }

        free(p);

        return OK;
    }
}

int get_first_adjvex(struct ALGraphy G, int vex_no)
{
    if (G.HeadNode[vex_no].firstarc)
    {
        return G.HeadNode[vex_no].firstarc->adjvex_no; 
    }

    return -1;
}

int get_next_adjvex(struct ALGraphy G, int vex_no, int w)
{
    struct ArcNode *p;

    p = G.HeadNode[vex_no].firstarc;

    while (p && p->adjvex_no != w)
    {
        p = p->nextarc;
    }

    if (p && p->nextarc) 
    {
        return p->nextarc->adjvex_no; 
    }
    else
    {
        return -1;
    }
}

void visit(struct ALGraphy G, int vex_no)
{
    printf("visit %s\n", G.HeadNode[vex_no].data);
}

void DFS(struct ALGraphy G, int vex_no)
{
    int i;

    visited[vex_no] = TRUE;
    visit(G, vex_no);

    for (i = get_first_adjvex(G, vex_no); i != -1; i = get_next_adjvex(G, vex_no, i))
    {
        if (!visited[i])
        {
            DFS(G, i);
        }
    } 
}

void DFS_traverse(struct ALGraphy G)
{
    int i;

    for (i = 0; i < G.vexnum; i++)
    {
        visited[i] = FALSE;
    }

    i = 0;

    /* !不要误解这个for循环,这个只是针对非连通图而设置,对于连通图,只须DFS(G,0)即可 */
    //for (i = 0; i < G.vexnum; i++)
    //{
    //    if (!visited[i])
    //    {
            DFS(G, i);
    //    }
    //}
}

void BFS_traverse(struct ALGraphy G)
{
    int i;
    q_elemtype vex_no = 0;
    struct linked_queue Q;

    for (i = 0; i < G.vexnum; i++)
    {
        visited[i] = FALSE;
    }

    init_queue(&Q);

    /* !这里没有考虑非连通图的情况,反而便于读者理解,理解了后就很容易去理解非连通图的处理了 */
    visited[vex_no] = TRUE;
    visit(G, vex_no);
    enqueue(&Q, vex_no);

    while (!queue_empty(Q))
    {
        dequeue(&Q, &vex_no);

        for (i = get_first_adjvex(G, vex_no); i != -1; i = get_next_adjvex(G, vex_no, i))
        {
            if (!visited[i])
            {
                visited[i] = TRUE;
                visit(G, i);
                enqueue(&Q, i);
            }
        }
    }


}

status create_graphy(struct ALGraphy *G)
{
    int i;
    int v;
    struct ArcNode *pArcNode;
    char name[3] = {0};

    printf("please input vexnum:");
    scanf("%d", &(*G).vexnum);
    printf("please input graphy kind:(0(DG),1(DN),2(UDG),3(UDN):");
    scanf("%d", &(*G).kind);

    (*G).arcnum = 0;

    (*G).HeadNode = (struct VNode*)malloc(sizeof(struct VNode) * (*G).vexnum);
    if (!(*G).HeadNode)
    {
        printf("%s: malloc failed\n", __FUNCTION__);
        return FAIL;
    }

    for (i = 0; i < (*G).vexnum; i++)
    {
        sprintf(name, "v%d", i);
        strcpy((*G).HeadNode[i].data, name); 
        printf("data:%s\n",(*G).HeadNode[i].data); 

        (*G).HeadNode[i].firstarc = NULL;

        printf("please input v%d's last adjvex(or input -1 to exit the loop):", i);
        scanf("%d", &v);

        while (v != -1)
        {
            pArcNode = (struct ArcNode*)malloc(sizeof(struct ArcNode));
            if (!pArcNode)
            {
                printf("%s: malloc failed\n", __FUNCTION__);
                return FAIL;
            }

            (*G).arcnum++;

            pArcNode->adjvex_no = v;
            pArcNode->arcinfo = NULL;
            pArcNode->nextarc = (*G).HeadNode[i].firstarc; 
            (*G).HeadNode[i].firstarc = pArcNode;

            printf("please input v%d's another front adjvex(or input -1 to exit the loop):", i);
            scanf("%d", &v);
        }
    }

    return OK;
}

void print_graphy(struct ALGraphy G)
{
    int i;

    printf("vexnum:%3d\n", G.vexnum);
    printf("arcnum:%3d\n", G.arcnum);
    printf("kind:  %3d\n", G.kind);

    for (i = 0; i < G.vexnum; i++) //for循环老喜欢加;号阿,影响程序调试,罪过!
    {
        printf("Head data:%s\n", G.HeadNode[i].data);
    }

    //其余信息读者根据需要自己添加把,TODO
}

int main(void)
{
    struct ALGraphy  G;

    (void)create_graphy(&G);

    print_graphy(G);

    printf("Depth First Search:\n");
    DFS_traverse(G);

    printf("Breadth First Search:\n");
    BFS_traverse(G);

    return 0;
}

你可能感兴趣的:([置顶] 图的BFS、DFS算法实现)