数据结构之图的构造以及DFS和BFS搜索(C程序描述)

//本程序使用邻接矩阵和邻接表构造无向图,并进行DFS和BFS遍历全图;

//可移植性程序能在Linux/Mac os/Windows下运行;

//若有不足之处请提出,博主会尽所能修改;

//若是对您有用的话请点赞收藏或分享给它人;

//未经允许严禁抄袭以及转载;

//源代码奉上,希望能够对您有所启发;

//----------------------------------------------------------------------------------------------------;

//邻接矩阵.c

#include <stdio.h>
#include <ctype.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAXNUM 5

typedef int Item;

typedef struct
{
    
    
    char mes[MAXNUM];          //结点信息;
    int graph[MAXNUM][MAXNUM]; //邻接矩阵;
    int size, edge;            //图中顶点的个数及边的个数;
} AdjacentMatrix_Graph;

typedef struct qnode
{
    
    
    Item value;
    struct qnode *next;
} QNODE;

typedef struct
{
    
    
    QNODE *front;
    QNODE *rear;
} Queue;

void initialize_graph(AdjacentMatrix_Graph *g);              //初始化一个邻接矩阵构造的图;
void dfs(AdjacentMatrix_Graph *g, int *visited, int source); //深度遍历连通图;
void dfs_traverse(AdjacentMatrix_Graph *g);                  //深度遍历非连通图;
void bfs_traverse(AdjacentMatrix_Graph *g);                  //广度遍历连通图或非连通图;
void print_graph(AdjacentMatrix_Graph *g);                   //打印整个图信息;
void initialize_queue(Queue *temp);                          //初始化空队列;
bool enqueue(Queue *temp, Item val);                         //添加元素至队列中;
bool queue_is_empty(Queue *temp);                            //判断队列是否为空;
bool dequeue(Queue *temp, Item *val);                        //从队列中删除元素;

int main(void)
{
    
    
    AdjacentMatrix_Graph map;

    initialize_graph(&map);
    printf("深度优先搜索遍历图信息如下:\n");
    dfs_traverse(&map);
    printf("广度优先搜索遍历图信息如下:\n");
    bfs_traverse(&map);
    printf("此图的邻接矩阵信息如下:\n");
    print_graph(&map);

    return 0;
}

void initialize_graph(AdjacentMatrix_Graph *g)
{
    
    
    char ch;
    int i, j, k, vex1, vex2, weight;

    g->edge = 0;
    g->size = MAXNUM;
    for (i = 0; i < g->size; i++)
    {
    
    
        for (j = 0; j < g->size; j++)
        {
    
    
            g->graph[i][j] = INT_MAX; //初始时所有顶点不邻接;
        }
    }
    for (i = 0; i < g->size; i++)
    {
    
    
        g->mes[i] = 'a' + i; //5个结点信息分别是a,b,c,d,e;
    }
    for (i = 0; i < g->size; i++)
    {
    
    
        printf("请输入与%c结点相邻的结点和权值(#结束输入):\n", g->mes[i]);
        for (j = 0; j < g->size; j++)
        {
    
    
            scanf("%c", &ch);
            if (ch == '#')
            {
    
    
                getchar();
                break;
            }
            scanf("%d", &weight);
            for (k = 0; k < g->size; k++)
            {
    
    
                if (g->mes[k] == ch)
                {
    
    
                    g->graph[i][k] = weight;
                    g->edge++;
                }
            }
            getchar();
        }
    }
    g->edge /= 2; //构造后边数除以2(无向图);
    /*
    输入示例(相邻结点及其权值):
        b 5 c 3 #
        a 5 d 7 e 4 #
        a 3 d 6 #
        b 7 c 6 e 1 #
        b 4 d 7 #
    */
    /*
    此图二维数组如下:
       a  b  c  d  e
    a  ∞  5  3  ∞  ∞
    b  5  ∞  ∞  7  4
    c  3  ∞  ∞  6  ∞
    d  ∞  7  6  ∞  1
    e  ∞  4  ∞  1  ∞
    */
    return;
}

void dfs(AdjacentMatrix_Graph *g, int *visited, int source)
{
    
    
    int i;

    visited[source] = 1;
    printf("%c ", g->mes[source]); //打印结点信息;
    for (i = 0; i < g->size; i++)
    {
    
    
        if (g->graph[source][i] != INT_MAX && !visited[i])
        {
    
    
            dfs(g, visited, i);
        }
    }
    return;
}

void dfs_traverse(AdjacentMatrix_Graph *g)
{
    
    
    int i;

    int visited[g->size];
    for (i = 0; i < g->size; i++)
    {
    
    
        visited[i] = 0;
    }
    for (i = 0; i < g->size; i++) //遍历非联通结点;
    {
    
    
        if (!visited[i])
        {
    
    
            dfs(g, visited, i);
        }
    }
    putchar('\n');
    return;
}

void bfs_traverse(AdjacentMatrix_Graph *g)
{
    
    
    int i, j;
    Queue temp;
    int visited[g->size];

    for (i = 0; i < g->size; i++)
    {
    
    
        visited[i] = 0;
    }
    initialize_queue(&temp);
    for (i = 0; i < g->size; i++)
    {
    
    
        if (!visited[i])
        {
    
    
            visited[i] = 1;
            printf("%c ", g->mes[i]);
            enqueue(&temp, i); //图中首结点入队;
            while (!queue_is_empty(&temp))
            {
    
    
                dequeue(&temp, &i);           //图第i个结点出队;
                for (j = 0; j < g->size; j++) //遍历关联结点;
                {
    
    
                    if (!visited[j] && g->graph[i][j] != INT_MAX)
                    {
    
    
                        visited[j] = 1;
                        printf("%c ", g->mes[j]); //输出结点信息;
                        enqueue(&temp, j);        //与i相关联的结点入队;
                    }
                }
            }
        }
    }
    putchar('\n');
    return;
}

void print_graph(AdjacentMatrix_Graph *g)
{
    
    
    int i, j;

    for (i = 0; i < g->size; i++)
    {
    
    
        for (j = 0; j < g->size; j++)
        {
    
    
            printf("%-15d", g->graph[i][j]);
        }
        putchar('\n');
    }
    return;
}

void initialize_queue(Queue *temp)
{
    
    
    temp->front = temp->rear = NULL;
    return;
}

bool enqueue(Queue *temp, Item val)
{
    
    
    QNODE *newqnode = (QNODE *)malloc(sizeof(QNODE));
    if (NULL == newqnode)
    {
    
    
        fprintf(stderr, "动态内存分配失败!本程序退出!\n");
        exit(EXIT_FAILURE);
    }
    newqnode->value = val;
    newqnode->next = NULL;
    if (queue_is_empty(temp))
    {
    
    
        temp->front = newqnode; //添加新结点令队头指针指向此结点;
    }
    else
    {
    
    
        temp->rear->next = newqnode; //将新结点添加至队尾;
    }
    temp->rear = newqnode; //修改队尾指针指向新结点;
    return true;
}

bool queue_is_empty(Queue *temp)
{
    
    
    return NULL == temp->front;
}

bool dequeue(Queue *temp, Item *val)
{
    
    
    if (queue_is_empty(temp))
    {
    
    
        return false;
    }
    QNODE *p = temp->front;          //声明一个临时指针指向队头结点;
    *val = p->value;                 //保存队头结点的数据;
    temp->front = temp->front->next; //使得头指针指向队头结点的后继结点;
    if (p == temp->rear)             //最后一个元素出队时的情况;
    {
    
    
        temp->rear = NULL;
    }
    free(p);
    return true;
}

//邻接表.c

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAXNUM 5 //图中最多的结点个数;

typedef int Item;
typedef char node_type;

typedef struct arc_node
{
    
    
    int pos;
    int weight;
    struct arc_node *next;
} Arcnode; //保存结点的相邻结点信息;

typedef struct node
{
    
    
    node_type info;
    Arcnode *next;
} Graphnode; //保存结点信息;

typedef struct graph
{
    
    
    Graphnode vertexs[MAXNUM];
    int arc, vertex;
} AdjacentList_Graph; //邻接表;

typedef struct qnode
{
    
    
    Item value;
    struct qnode *next;
} QNODE;

typedef struct
{
    
    
    QNODE *front;
    QNODE *rear;
} Queue;

Arcnode *make_node(const int pos, const int weight);       //封装好的分配内存函数;
void initialize_graph(AdjacentList_Graph *g);              //初始化一个邻接表构造的图;
void dfs(AdjacentList_Graph *g, int *visited, int source); //深度遍历连通图;
void dfs_traverse(AdjacentList_Graph *g);                  //深度遍历非连通图;
void bfs(AdjacentList_Graph *g, int *visited, int source); //广度遍历连通图;
void bfs_traverse(AdjacentList_Graph *g);                  //广度遍历非连通图;
void print_graph(AdjacentList_Graph *g);                   //打印整个图信息;
void initialize_queue(Queue *temp);                        //初始化空队列;
bool enqueue(Queue *temp, Item val);                       //添加元素至队列中;
bool queue_is_empty(Queue *temp);                          //判断队列是否为空;
bool dequeue(Queue *temp, Item *val);                      //从队列中删除元素;
Item get_front_value(Queue *temp);

int main(void)
{
    
    
    AdjacentList_Graph map;

    initialize_graph(&map);
    printf("深度优先搜索遍历图信息如下:\n");
    dfs_traverse(&map);
    printf("广度优先搜索遍历图信息如下:\n");
    bfs_traverse(&map);
    printf("此图的邻接矩阵信息如下:\n");
    print_graph(&map);

    return 0;
}

Arcnode *make_node(const int pos, const int weight)
{
    
    
    Arcnode *new_node = (Arcnode *)malloc(sizeof(Arcnode));
    if (new_node == NULL)
    {
    
    
        exit(EXIT_FAILURE);
    }
    new_node->next = NULL;
    new_node->weight = weight;
    new_node->pos = pos;
    return new_node;
}

void initialize_graph(AdjacentList_Graph *g)
{
    
    
    char ch;
    Arcnode *temp;
    int i, j, k, num;

    g->vertex = MAXNUM;
    for (i = 0; i < g->vertex; i++)
    {
    
    
        g->vertexs[i].info = 'a' + i; //构造5个结点分别为a,b,c,d,e;
        g->vertexs[i].next = NULL;
    }
    for (i = 0; i < g->vertex; i++)
    {
    
    
        printf("请输入与结点%c相邻的结点和权值(#结束输入)\n", g->vertexs[i].info);
        for (j = 0; j < g->vertex; j++)
        {
    
    
            scanf("%c", &ch);
            if (ch == '#')
            {
    
    
                getchar();
                break;
            }
            scanf("%d", &num);
            getchar();
            for (k = 0; k < g->vertex; k++)
            {
    
    
                if (g->vertexs[k].info == ch) //寻找到ch结点后构造结点关系;
                {
    
    
                    if (g->vertexs[k].next == NULL) //没有相邻结点时的情况;
                    {
    
    
                        g->vertexs[k].next = make_node(i, num);
                    }
                    else //已有相邻结点的情况;
                    {
    
    
                        temp = g->vertexs[k].next;
                        while (temp->next != NULL)
                        {
    
    
                            temp = temp->next;
                        }
                        temp->next = make_node(i, num);
                    }
                }
            }
        }
    }
    /*
    输入示例(相邻结点及其权值):
        b 5 c 3 #
        a 5 d 7 e 4 #
        a 3 d 6 #
        b 7 c 6 e 1 #
        b 4 d 1 #
    */
    /*
    此图相对次序如下:
    a  1 2
    b  0 3 4
    c  0 3
    d  1 2 4
    e  1 3
    */
    return;
}

void dfs(AdjacentList_Graph *g, int *visited, int source)
{
    
    
    Arcnode *temp = NULL;

    visited[source] = 1;
    printf("%c ", g->vertexs[source].info); //输出当前结点的名称信息;
    temp = g->vertexs[source].next;         //寻找到temp指向的结点的相邻结点;
    while (temp != NULL)
    {
    
    
        if (!visited[temp->pos])
        {
    
    
            dfs(g, visited, temp->pos);
        }
        temp = temp->next;
    }
    return;
}

void dfs_traverse(AdjacentList_Graph *g)
{
    
    
    int i;

    int visited[g->vertex];
    for (i = 0; i < g->vertex; i++)
    {
    
    
        visited[i] = 0;
    }
    for (i = 0; i < g->vertex; i++) //遍历非联通结点;
    {
    
    
        if (!visited[i])
        {
    
    
            dfs(g, visited, i);
        }
    }
    putchar('\n');
    return;
}

void bfs(AdjacentList_Graph *g, int *visited, int source)
{
    
    
    Item t;
    int pos;
    Queue line;
    Arcnode *temp = NULL;

    visited[source] = 1;
    initialize_queue(&line); //初始化空队列;
    enqueue(&line, source);  //第source个结点入队;
    while (!queue_is_empty(&line))
    {
    
    
        pos = get_front_value(&line);        //获取队头结点;
        printf("%c ", g->vertexs[pos].info); //输出队头结点的名称信息;
        temp = g->vertexs[pos].next;         //寻找到temp指向的结点的相邻结点;
        while (temp != NULL)
        {
    
    
            if (!visited[temp->pos])
            {
    
    
                visited[temp->pos] = 1;    //标记此结点已被访问过;
                enqueue(&line, temp->pos); //相邻结点位置入队;
            }
            temp = temp->next;
        }
        dequeue(&line, &t);
    }
    putchar('\n');
    return;
}

void bfs_traverse(AdjacentList_Graph *g)
{
    
    
    int i;

    int visited[g->vertex];
    for (i = 0; i < g->vertex; i++)
    {
    
    
        visited[i] = 0;
    }
    for (i = 0; i < g->vertex; i++) //遍历非联通结点;
    {
    
    
        if (!visited[i])
        {
    
    
            bfs(g, visited, i);
        }
    }
    return;
}

void print_graph(AdjacentList_Graph *g)
{
    
    
    int i;
    Arcnode *temp;

    for (i = 0; i < g->vertex; i++)
    {
    
    
        printf("%c\t", g->vertexs[i].info);
        temp = g->vertexs[i].next;
        while (temp != NULL)
        {
    
    
            printf("相邻%c结点(权值:%d)\t", g->vertexs[temp->pos].info, temp->weight);
            temp = temp->next;
        }
        putchar('\n');
    }
    putchar('\n');
    return;
}

void initialize_queue(Queue *temp)
{
    
    
    temp->front = temp->rear = NULL;
    return;
}

bool enqueue(Queue *temp, Item val)
{
    
    
    QNODE *newqnode = (QNODE *)malloc(sizeof(QNODE));
    if (NULL == newqnode)
    {
    
    
        fprintf(stderr, "动态内存分配失败!本程序退出!\n");
        exit(EXIT_FAILURE);
    }
    newqnode->value = val;
    newqnode->next = NULL;
    if (queue_is_empty(temp))
    {
    
    
        temp->front = newqnode; //添加新结点令队头指针指向此结点;
    }
    else
    {
    
    
        temp->rear->next = newqnode; //将新结点添加至队尾;
    }
    temp->rear = newqnode; //修改队尾指针指向新结点;
    return true;
}

bool queue_is_empty(Queue *temp)
{
    
    
    return NULL == temp->front;
}

bool dequeue(Queue *temp, Item *val)
{
    
    
    if (queue_is_empty(temp))
    {
    
    
        return false;
    }
    QNODE *p = temp->front;          //声明一个临时指针指向队头结点;
    *val = p->value;                 //保存队头结点的数据;
    temp->front = temp->front->next; //使得头指针指向队头结点的后继结点;
    if (p == temp->rear)             //最后一个元素出队时的情况;
    {
    
    
        temp->rear = NULL;
    }
    free(p);
    return true;
}

Item get_front_value(Queue *temp)
{
    
    
    if (!queue_is_empty(temp))
    {
    
    
        return temp->front->value;
    }
    return -1;
}

//----------------------------------------------------------------------------------------------------;

//-------------------------------------------------2020年11月9日-------------------------------------------------------;

扫描二维码关注公众号,回复: 12354448 查看本文章

猜你喜欢

转载自blog.csdn.net/m0_46181359/article/details/109574374