Sir zach

专注于算法,AI, Android以及音视频领域 欢迎关注我的最新博客: zachliu.cn

导航

图算法之BFS

Posted on 2014-08-11 23:15  SirZach  阅读(219)  评论(0编辑  收藏  举报

深度优先搜索(Breadth  First Search),类似于树的层序遍历,搜索模型是队列,还是以下面的无向图为例:

DFSBFS_thumb_thumb

实验环境是Ubuntu 14.04 x86

 

伪代码实现如下:

其中u v 的先辈或父母。

BFS(G, s)

for each vertex u ∈ V [G] - {s}
        do color[u] ← WHITE
           d[u] ← ∞
           π[u] ← NIL   //除了源顶点s之外,第1-4行置每个顶点为白色,置每个顶点u的d[u]为无穷大,置每个顶点的父母为NIL。
color[s] ← GRAY  // 将源顶点s置为灰色,这是因为在过程开始时,源顶点已被发现。
d[s] ← 0      
π[s] ← NIL     //将源顶点的父顶点置为NIL。
Q ← Ø
ENQUEUE(Q, s)           //第8、9行,初始化队列Q,使其仅含源顶点s。
while Q ≠ Ø
      do u ← DEQUEUE(Q)   //确定队列头部Q头部的灰色顶点u,并将其从Q中去掉。
         for each v ∈ Adj[u]        //for循环考察u的邻接表中的每个顶点v
             do if color[v] = WHITE
                   then color[v] ← GRAY     
                        d[v] ← d[u] + 1    
                        π[v] ← u            //u记为该顶点的父母
                        ENQUEUE(Q, v)        //插入队列中
         color[u] ← BLACK

 

队列推荐使用链式队列。

邻接表实现:

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

#define MAX_VERTEX_NUM 50 

typedef char vertexType;
typedef int edgeType;
typedef int QueueElemType;

/* 边表 */
typedef struct ArcNode
{
    int adjIndex;
    struct ArcNode *nextArc;  
    edgeType weight;
}ArcNode;

/* 顶点表 */
typedef struct VNode
{
    vertexType data;
    ArcNode *firstArc;
}VNode, AdjList[MAX_VERTEX_NUM];

/* 图结构 */
typedef struct
{
    AdjList adjList;
    int vexNum;
    int edgeNum;
}ALGraph;

typedef struct QueueNode
{
    QueueElemType data;
    struct QueueNode *next;
}QueueNode;

typedef struct
{
    QueueNode *front;
    QueueNode *rear;
}LinkQueue;


int visit[MAX_VERTEX_NUM] = {0};

void initLinkQueue(LinkQueue *queue)
{
    QueueNode *head = (QueueNode*)malloc(sizeof(QueueNode));
    if(head  == NULL)
    {
        printf("malloc failed\n");
        return;
    }
    
    head->next = NULL;
    queue->front = queue->rear = head;

    return;
}

void insertLinkQueue(LinkQueue *queue, QueueElemType data)
{
    QueueNode *newNode = (QueueNode *)malloc(sizeof(QueueNode));
    if(NULL == newNode)
    {
        printf("malloc failed\n");
        return;
    }

    newNode->data = data;
    newNode->next = NULL;

    queue->rear->next = newNode;
    queue->rear = newNode;

    return;
}

int deleteLinkQueue(LinkQueue *queue, QueueElemType *data)
{
    QueueNode *p;

    if (queue->front == queue->rear)
    {
        printf("no element!\n");
        return 0;
    }

    p = queue->front->next;
    *data = p->data;

    queue->front->next = p->next;
    if (p == queue->rear)
    {
        queue->rear = queue->front;
    }

    free(p);
    return 1;
}

void BFSTraverse(ALGraph G)
{
    QueueElemType q;
    LinkQueue queue;
    ArcNode *adjEdge;
    int index = 0;

    initLinkQueue(&queue);

    for (int i = 0; i < G.vexNum; i++)
    {
        if (!visit[i])
        {
            visit[i] = 1;
            printf("%c ", G.adjList[i].data);    
            insertLinkQueue(&queue, i);

            while (deleteLinkQueue(&queue, &q))
            {
                adjEdge = G.adjList[q].firstArc;
                while (adjEdge)
                {
                    index = adjEdge->adjIndex;

                    if (!visit[index])
                    {
                        visit[index] = 1;
                        printf("%c ", G.adjList[index].data);

                        insertLinkQueue(&queue, index);
                    }
                    adjEdge = adjEdge->nextArc;
                }
            }
        }

    }

} 

void CreateALGraph(ALGraph *G)
{
    int i, j, k;
    ArcNode *e;
    int c;

    printf("输入顶点数和边数:\n");
    scanf("%d %d", &G->vexNum, &G->edgeNum);
    setbuf(stdin, NULL);

    for (i = 0; i < G->vexNum; i++)
    {
        printf("输入顶点信息:\n");
        scanf("%c", &G->adjList[i].data);
        G->adjList[i].firstArc = NULL;

        while((c = getchar()) != '\n' && c != EOF);
    }

    for (k = 0; k < G->edgeNum; k++)
    {
        printf("输入边(vi,vj)的顶点序号i,j:\n");
        scanf("%d %d", &i, &j);

        while((c = getchar()) != '\n' && c != EOF);
        
        e = (ArcNode*)malloc(sizeof(ArcNode));
        if (NULL == e)
        {
            return;
        }

        e->adjIndex = j;
        e->nextArc = G->adjList[i].firstArc;
        G->adjList[i].firstArc = e;

        // double direction copy
        e = (ArcNode *)malloc(sizeof(ArcNode));
        if (NULL == e)
        {
            return;
        }
        e->adjIndex = i;
        e->nextArc = G->adjList[j].firstArc;
        G->adjList[j].firstArc = e;
    }
}

int main(int argc, char const *argv[])
{
    ALGraph G;    
    CreateALGraph(&G);

    BFSTraverse(G);
    return 0;
}

运行结果: A F B G E I C H D

 

邻接矩阵实现:

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

#define MAX_VERTEX_NUM 50 

typedef char vertexType;
typedef int edgeType;
typedef int QueueElemType;

typedef struct
{
    vertexType vexs[MAX_VERTEX_NUM];
    edgeType arc[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
    int vexNum;
    int edgeNum;
}Graph;

typedef struct QueueNode
{
    QueueElemType data;
    struct QueueNode *next;
}QueueNode;

typedef struct
{
    QueueNode *front;
    QueueNode *rear;
}LinkQueue;

int visit[MAX_VERTEX_NUM] = {0};

void initLinkQueue(LinkQueue *queue)
{
    QueueNode *head = (QueueNode*)malloc(sizeof(QueueNode));
    if(head  == NULL)
    {
        printf("malloc failed\n");
        return;
    }
    
    head->next = NULL;
    queue->front = queue->rear = head;

    return;
}

void insertLinkQueue(LinkQueue *queue, QueueElemType data)
{
    QueueNode *newNode = (QueueNode *)malloc(sizeof(QueueNode));
    if(NULL == newNode)
    {
        printf("malloc failed\n");
        return;
    }

    newNode->data = data;
    newNode->next = NULL;

    queue->rear->next = newNode;
    queue->rear = newNode;

    return;
}

int deleteLinkQueue(LinkQueue *queue, QueueElemType *data)
{
    QueueNode *p;

    if (queue->front == queue->rear)
    {
        printf("no element!\n");
        return 0;
    }

    p = queue->front->next;
    *data = p->data;

    queue->front->next = p->next;
    if (p == queue->rear)
    {
        queue->rear = queue->front;
    }

    free(p);
    return 1;
}
void CreateALGraph(Graph *G)
{
    int i, j, k;
    int c;

    printf("输入顶点数和边数:\n");
    scanf("%d %d", &G->vexNum, &G->edgeNum);
    setbuf(stdin, NULL);

    for (i = 0; i < G->vexNum; i++)
    {
        printf("输入第%d个顶点信息:\n", i + 1);
        scanf("%c", &G->vexs[i]);

        while((c = getchar()) != '\n' && c != EOF);
    }

    for (i = 0; i < G->vexNum; i++)
    {
        for (j = 0; j < G->vexNum; j++)
        {
            G->arc[i][j] = 0;
        }
    }


    for (k = 0; k < G->edgeNum; k++)
    {
        printf("输入边(vi,vj)的下标i,j:\n");
        scanf("%d %d", &i, &j);

        while((c = getchar()) != '\n' && c != EOF);

        // set a default weight
        G->arc[i][j] = G->arc[j][i] = 1;   
    }
}

void BFSTraverse(Graph G)
{
    LinkQueue queue;
    QueueElemType q;

    initLinkQueue(&queue);

    for(int i = 0; i < G.vexNum; i++)
    {
        if (!visit[i])
        {
            visit[i] = 1;
            printf("%c ", G.vexs[i]);

            insertLinkQueue(&queue, i);
            while (deleteLinkQueue(&queue, &q))
            {
                for (int j = 0; j < G.vexNum; j++)
                {
                    if (G.arc[q][j] == 1 && !visit[j])
                    {
                        visit[j] = 1;
                        printf("%c ", G.vexs[j]);
                        insertLinkQueue(&queue, j);
                    }
                }
            }
        }
    }
}

int main(int argc, char const *argv[])
{
    Graph G;    
    CreateALGraph(&G);

    BFSTraverse(G);
    return 0;
}

运行结果:A B F C G I E D H