图的深度、广度优先遍历

1、输入有向图的顶点和弧的数据,建立该有向图的邻接表,要求在链表插入时候使用头插入法;
2、实现该有向图的深度优先遍历,并输出结果;
3、实现该有向图的广度优先遍历,并输出结果;

4、遍历序列从输入的第一个结点开始。

【输入形式】

9.png

     对于如上所示的有向图,设置输入形式如下:

     5        //结点个数

     A B C D E//输入多个结点值,每个值之间用一个空格隔开

     6        //有向弧个数

     A B    //第1条边的弧尾和弧头,中间用一个空格隔开

     A C    //第2条边的弧尾和弧头,中间用一个空格隔开

     A D    //第3条边的弧尾和弧头,中间用一个空格隔开

     D E    //第4条边的弧尾和弧头,中间用一个空格隔开

     E C    //第5条边的弧尾和弧头,中间用一个空格隔开

     C B    //第6条边的弧尾和弧头,中间用一个空格隔开

【输出形式】输出图的深度优先遍历序列和图的广度优先遍历序列,每个字符之间用一个空格隔开。
【样例输入】

5
A B C D E
6
A B
A C
A D
D E
E C
C B
【样例输出】

A  D  E  C  B
A  D  C  B  E 

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

#define MAX_VERTEX_NUM 100 // 最大顶点数

// 定义邻接表结点
typedef struct ArcNode {
    int adjvex;                 // 弧头结点的位置
    struct ArcNode* nextarc;    // 指向下一条弧的指针
} ArcNode;

// 定义顶点表结点
typedef struct VNode {
    char data;              // 结点数据
    ArcNode* firstarc;      // 指向第一条依附该结点的弧
} VNode, AdjList[MAX_VERTEX_NUM];

// 定义图结构
typedef struct {
    AdjList vertices;       // 邻接表
    int vexnum, arcnum;     // 图的顶点数和弧数
} ALGraph;


// 初始化图
void InitGraph(ALGraph* G, int n, char vertex[]) {
    G->vexnum = n;
    G->arcnum = 0;
    for (int i = 0; i < n; i++) {
        G->vertices[i].data = vertex[i];
        G->vertices[i].firstarc = NULL;
    }
}

// 插入边(使用头插法)
void InsertArc(ALGraph* G, int tail, int head) {
    ArcNode* arcNode = (ArcNode*)malloc(sizeof(ArcNode));
    arcNode->adjvex = head;
    arcNode->nextarc = G->vertices[tail].firstarc;
    G->vertices[tail].firstarc = arcNode;
    G->arcnum++;
}

// 深度优先遍历递归函数
void DFS(ALGraph* G, int v, int visited[]) {
    visited[v] = 1; // 标记该结点已访问
    printf("%c ", G->vertices[v].data);

    ArcNode* p = G->vertices[v].firstarc;
    while (p != NULL) {
        if (!visited[p->adjvex]) {
            DFS(G, p->adjvex, visited);
        }
        p = p->nextarc;
    }
}

// 深度优先遍历
void DFSTraverse(ALGraph* G) {
    int visited[MAX_VERTEX_NUM];
    for (int i = 0; i < G->vexnum; i++) {
        visited[i] = 0;
    }

    for (int i = 0; i < G->vexnum; i++) {
        if (!visited[i]) {
            DFS(G, i, visited);
        }
    }
}

// 广度优先遍历
void BFSTraverse(ALGraph* G) {
    int visited[MAX_VERTEX_NUM];
    for (int i = 0; i < G->vexnum; i++) {
        visited[i] = 0;
    }

    int queue[MAX_VERTEX_NUM];  // 辅助队列
    int front = 0, rear = 0;    // 队头和队尾指针

    for (int i = 0; i < G->vexnum; i++) {
        if (!visited[i]) {
            visited[i] = 1;
            printf("%c ", G->vertices[i].data);
            queue[rear++] = i;//当前元素 i 被存储在 queue[rear] 中,然后 rear 的值递增1

            while (front < rear) {
                int v = queue[front++];
                ArcNode* p = G->vertices[v].firstarc;
                while (p != NULL) {
                    if (!visited[p->adjvex]) {
                        visited[p->adjvex] = 1;
                        printf("%c ", G->vertices[p->adjvex].data);
                        queue[rear++] = p->adjvex;
                    }
                    p = p->nextarc;
                }
            }
        }
    }
}

int main() {
    int n; // 结点个数
    char vertex[MAX_VERTEX_NUM]; // 结点值数组
    int m; // 弧的个数

    scanf("%d", &n); // 输入结点个数
    for (int i = 0; i < n; i++) {
        scanf(" %c", &vertex[i]); // 输入结点值
    }

    ALGraph G;
    InitGraph(&G, n, vertex);

    scanf("%d", &m); // 输入弧的个数
    for (int i = 0; i < m; i++) {
        char tail, head;
        scanf(" %c %c", &tail, &head); // 输入弧尾和弧头
        int tailIndex = -1, headIndex = -1;
        for (int j = 0; j < n; j++) {
            if (G.vertices[j].data == tail) {
                tailIndex = j;
            }
            if (G.vertices[j].data == head) {
                headIndex = j;
            }
        }
        if (tailIndex != -1 && headIndex != -1) {
            InsertArc(&G, tailIndex, headIndex);
        }
    }

    DFSTraverse(&G);
    printf("\n");
    BFSTraverse(&G);
    
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值