广度优先搜索的c语言实现

    今天下午有时间,好奇图论,所以把算法导论的22章的图论的基础给看了一下,最后那个强连通分量我没看,不知道有什么用处,等到要用的时候再看吧,一切按照兴趣走。晚上花了两个多小时把广度优先搜索的部分给实现了一遍,感觉还是比较棒的。整个过程中的数据结构方面,我没有因为实现方面的原因而浪费空间,尽力实现了这个广度优先搜索。

    直接上附上代码,以后直接在代码上注释吧,不过多地写废话了,一些概念都在书上,但是自己写的代码有时候自己却会忘记。

/*************************************************************************
    > File Name: graph.c
    > Author: jeff zhu
    > Mail: [email protected] 
    > Created Time: 2016年09月04日 星期日 18时58分08秒
 ************************************************************************/

#include 
#include 
#include 

#define MAXSIZE 100    //图的最大的顶点数量为100,
#define WHITE 1            //定义每个顶点的可能的颜色,白色代表没有探索,灰色代表已经探索,但是其邻接的定点没有完全探索,黑的代表其所有邻接的顶点都探索过。
#define GRAY 2
#define BLACK 3
#define INFINITE INT_MAX    //定义一个正无穷

typedef struct gra_ptr_node {    //这个地方我定义了一个数据结构,这个数据结构用来实现链表(这个链表的节点的关键字是指针,所以节省了空间,在效率上也没有损耗)
    struct gra_ptr_node *next;
    struct graph_node *ptr;
}PTR_NODE;
typedef struct graph_node {     //图的每个顶点,parent用来实现广度优先搜索树,nect用来实现来链表,key代表编号,d是距离搜索顶点的距离,f是为了深度优先搜索而准备							//的 
    struct graph_node *parent;
    struct graph_node *next;
    int key;
    int d;
    int f;
    int color;
}NODE;
typedef struct graph {      //图的数据结构,length代表adj实际的长度
    PTR_NODE *adj[MAXSIZE];
    int length;
}GRAPH;
typedef struct stack_of_granode {    //在BFS中会用到的栈
    NODE *arr_temp[MAXSIZE];
    int start;
    int end;
    int length;
    int count;
}NODEQUEUE;

NODE *arr_V[MAXSIZE];  //这个数组保存所有的顶点,可以直接在这个数组中找到想要的定点
void BFS (GRAPH *G , NODE *s) ;

void init_graph (GRAPH *G , int len) ;
NODE *create_and_init_node (int key) ;
void insert_to_adj (GRAPH *G , NODE *x , int key) ;
void init_queue (NODEQUEUE *Q , GRAPH *G) ;
void enqueue (NODEQUEUE *Q , NODE *x) ;
NODE *dequeue (NODEQUEUE *Q) ;
void BFS (GRAPH *G , NODE *s) ;

int main () {
    int i;
    int count = 0;
    GRAPH G;
    NODE *temp;
    NODE *temp1;
    PTR_NODE *ptr_temp;
    NODEQUEUE Q;  //一下两行代码放到BFS函数中更好,写注释的时候发现的懒得改了
    init_queue (&Q , &G);

    init_graph (&G , 8);   //初始化图

    temp = create_and_init_node (0);  //一下代码都是初始化一个图,图的逻辑结构见《算法导论》图22-3
    arr_V[count++] = temp;
    insert_to_adj (&G , temp , 1);

    temp = create_and_init_node (1);
    arr_V[count++] = temp;
    insert_to_adj (&G , temp , 0);
    insert_to_adj (&G , temp , 2);

    temp = create_and_init_node (2);
    temp1 = temp;
    arr_V[count++] = temp;
    insert_to_adj (&G , temp , 1);
    insert_to_adj (&G , temp , 3);

    temp = create_and_init_node (3);
    arr_V[count++] = temp;
    insert_to_adj (&G , temp , 2);
    insert_to_adj (&G , temp , 4);
    insert_to_adj (&G , temp , 5);

    temp = create_and_init_node (4);
    arr_V[count++] = temp;
    insert_to_adj (&G , temp , 3);
    insert_to_adj (&G , temp , 5);
    insert_to_adj (&G , temp , 6);
    insert_to_adj (&G , temp , 7);

    temp = create_and_init_node (5);
    arr_V[count++] = temp;
    insert_to_adj (&G , temp , 3);
    insert_to_adj (&G , temp , 4);
    insert_to_adj (&G , temp , 6);

    temp = create_and_init_node (6);
    arr_V[count++] = temp;
    insert_to_adj (&G , temp , 5);
    insert_to_adj (&G , temp , 4);
    insert_to_adj (&G , temp , 7);

    temp = create_and_init_node (7);
    arr_V[count++] = temp;
    insert_to_adj (&G , temp , 6);
    insert_to_adj (&G , temp , 4);  //图初始化结束

    for (i = 0 ; i < 8 ; i++) {
        ptr_temp = G.adj[i];
        while (ptr_temp != NULL) {
            printf ("%d " , ptr_temp->ptr->key);
            ptr_temp = ptr_temp->next;
        }
        printf ("\n");
    }                           //打印一下结果,看看是否和逻辑图是一样的
    printf ("\n\n");
    BFS (&G , temp1);   //执行BFS算法

    for (i = 0 ; i < count ; i++) {
        printf ("%d  " , arr_V[i]->d);
    }
    printf ("\n");
}

void init_graph (GRAPH *G , int len) {  //初始化图的函数
    int i;

    G->length = len;
    for (i = 0 ; i < len ; i++) {
        G->adj[i] = NULL;
    }
}

NODE *create_and_init_node (int key) {   //创建和初始化图
    NODE *temp = (NODE *) malloc (sizeof (NODE));

    temp->key = key;
    temp->d = 0;
    temp->f = 0;
    temp->next = NULL;
    temp->parent = NULL;

    return temp;
}

void insert_to_adj (GRAPH *G , NODE *x , int key) {  //这个函数从图论的角度来说是将边加入到一个关于顶点的便于搜索数组。
    if (key >= G->length) {
        printf ("the key is too big");
        return;
    }

    PTR_NODE *temp;
    temp = (PTR_NODE *) malloc (sizeof (PTR_NODE));
    temp->next = G->adj[key];
    temp->ptr = x;
    G->adj[key] = temp;
}

void init_queue (NODEQUEUE *Q , GRAPH *G) {  //初始化BFS算法要用到的队列Q。
    Q->start = 0;
    Q->end = 0;
    Q->length = G->length;
    Q->count = 0;
}
void enqueue (NODEQUEUE *Q , NODE *x) {  //将节点x加入到队列Q中。同时,Q->count加1。
    if (((Q->end+1) % Q->length) == Q->start)
        return;
    else {
        Q->arr_temp[Q->end] = x;
        Q->end++;
        if (Q->end == Q->length)
            Q->end = 0;
        Q->count++;
    }
}

NODE *dequeue (NODEQUEUE *Q) {   //返回Q->arr[Q->start],同时将这个数组给删除。同时,Q->count减1。
    NODE *temp;
    if (Q->start == Q->end)
        return;
    else {
        temp = Q->arr_temp[Q->start];
        Q->start++;
        if (Q->start == Q->length)
            Q->start = 0;
        Q->count--;
    }
    return temp;
}

void BFS (GRAPH *G , NODE *s) {   //终于到了广度优先算法了,这个算法的核心思想就是,先探索和当前节点邻接的顶点,然后再探索别的定点
    int i;
    NODEQUEUE Q;
    init_queue (&Q , G);
    NODE *temp;
    PTR_NODE *ptr_temp;

    for (i = 0 ; i < G->length ; i++) {
        if (arr_V[i] != s) {
            arr_V[i]->color = WHITE;
            arr_V[i]->d = INFINITE;
            arr_V[i]->parent = NULL;
        }
    }
    s->color = GRAY;
    s->parent = NULL;
    s->d = 0;
    enqueue (&Q , s);

    while (Q.count != 0) {
        temp = dequeue (&Q);
        ptr_temp = G->adj[temp->key];
        while (ptr_temp != NULL) {
            if (ptr_temp->ptr->color == WHITE) {
                ptr_temp->ptr->color = GRAY;
                ptr_temp->ptr->d = temp->d + 1;
                ptr_temp->ptr->parent = temp;
                enqueue (&Q , ptr_temp->ptr);
            }
            ptr_temp = ptr_temp->next;
        }
        temp->color = BLACK;
    }
}

你可能感兴趣的:(算法导论)