【Data Structure Learning Record 20】——Two kinds of traversal of graph

One. Two kinds of traversal

1. Depth First Search (DFS)

Depth-first search, as the name suggests, is to search deeper places first. Assuming this is a tree, then the depth-first search will preferentially search for 深度higher nodes. Because the concept of depth-first search does not return until the deepest node, nodes at the same level are accessed first, then traversed, conforming to the stack structure model, so our depth-first search is generally implemented through recursion.
For this tree-like graph:
Insert picture description here
suppose our traversal starts from 1, then he will preferentially visit the vertices with higher depth:
Insert picture description here
finally, its traversal order is:
GraphG DFS:1 2 4 8 5 3 6 7

2. Breadth First Search (BFS)

The definition is similar to DFS, breadth-first search is to first search for nodes at the same level before searching for nodes at the next depth. Let's use a tree as an example again: Suppose a tree performs a breadth-first search, then it will first traverse its sibling nodes before traversing to the deeper son nodes. Therefore, the sons of the same node are visited first and traversed first, so it is in line with the queue model, so we generally implement it through the queue.
For this picture,
Insert picture description here
our breadth-first search process is: The
Insert picture description here
result is:
GraphG BFS:1 2 3 4 5 6 7 8

3. The difference between the two

Use two pictures to visually represent these two kinds of searches. For example, the A square is in the maze, and we have to traverse the way to the end.
Depth first search:
Insert picture description here

Breadth first search:

Insert picture description here

2. Code implementation

See the effect:
Insert picture description here

Because of the various structures of the graph, we adopt the method of directed graph + adjacency list to achieve it.
Construct the vertices first, then the arcs.

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

#define         OK          1
#define         ERROR       0
#define         MaxLen      100

typedef struct ArcNode{
    
    
    int Head;
    struct ArcNode *nextArc;
}ArcNode;   // 创建弧结点

typedef struct VNode{
    
    
    char NodeName;
    ArcNode *nextArc;
}VNode;     // 创建Vertex顶点结点

typedef struct Graph{
    
    
    int len;
    VNode *Nbase;   // 线性存储顶点结点
}Graph;     // 创建一张图

int MarkGraph[MaxLen];  // 标记数组

Graph *GraphCreat(void);
int GraphShowList(Graph *G);
int GraphDFS(Graph *G);
int DFS(Graph *G, int vertex);
int GraphBFS(Graph *G);

int main()
{
    
    
    Graph *map = GraphCreat();
    GraphShowList(map);
    GraphDFS(map);
    GraphBFS(map);
    return 0;
}

Graph *GraphCreat(void)
{
    
    
    Graph *G = (Graph*)malloc(sizeof(Graph));
    int lenV, lenA;
    int i, tail, head;
    char temp;
    ArcNode *ArcNow, *ArcLast;

    printf("please input the number of Vertex and Arc:");
    scanf("%d %d", &lenV, &lenA);   // 获取 顶点数和弧的个数

    if (lenV > MaxLen)
    {
    
    
        printf("Over MaxLenth");
        exit(ERROR);
    }   // 限制下大小

    // 创建顶点线性表
    G->len = lenV;
    G->Nbase = (VNode*)malloc(sizeof(VNode)*lenV);
    
    // 存顶点名字
    printf("please input Vertexs' name:\n");
    rewind(stdin);
    for (i = 0; i < lenV; ++i)
    {
    
    
        scanf("%c", &temp);
        (G->Nbase+i)->NodeName = temp;
        (G->Nbase+i)->nextArc = NULL;
    }
    // 存弧
    printf("please input (tail,head) as the arc:\n");
    for (i = 0; i < lenA; ++i)
    {
    
    
        rewind(stdin);
        scanf("%d %d", &tail, &head);
        
        // 如果是顶点的第一个弧
        if ((G->Nbase+tail)->nextArc == NULL)
        {
    
    
            (G->Nbase+tail)->nextArc = (ArcNode*)malloc(sizeof(ArcNode));
            (G->Nbase+tail)->nextArc->Head = head;
            (G->Nbase+tail)->nextArc->nextArc = NULL;
        }
        else // 非顶点的第一个弧
        {
    
    
            ArcNow = (G->Nbase+tail)->nextArc;
            while(ArcNow->nextArc != NULL)  // 循环移动到最后一个弧
            {
    
    
                ArcNow = ArcNow->nextArc;
            }
            // 创建弧结点
            ArcNow->nextArc = (ArcNode*)malloc(sizeof(ArcNode));
            ArcNow->nextArc->Head = head;
            ArcNow->nextArc->nextArc = NULL;
        }
    }

    return G;
}

int GraphShowList(Graph *G) // 循环输出每个顶点的弧信息
{
    
    
    int i;
    ArcNode *ArcNow;

    printf("\n");
    for (i = 0; i < G->len; ++i)    // 循环
    {
    
    
        printf("%d: %c", i, (G->Nbase+i)->NodeName); // 输出顶点名
        ArcNow = (G->Nbase+i)->nextArc;
        while(ArcNow != NULL)   // 循环输出每个弧
        {
    
    
            printf("->%c", (G->Nbase+ArcNow->Head)->NodeName);
            ArcNow = ArcNow->nextArc;
        }
        printf("\n");
    }
}

int GraphDFS(Graph *G)  // DFS初始化
{
    
    
    int i = 0;
    for (i = 0; i < G->len; ++i)    // 更新结点标记数组
    {
    
    
        MarkGraph[i] = 0;
    }
    printf("\nGraphG DFS:");
    DFS(G, 0);  // 开始DFS
    
}

int DFS(Graph *G, int vertex)
{
    
    
    ArcNode *ArcNow;
    if (MarkGraph[vertex] == 0) // 如果该顶点未被访问过
    {
    
    
        printf("%c ", (G->Nbase+vertex)->NodeName); // 输出该顶点
        MarkGraph[vertex] = 1;  // 标记该顶点被访问过
        ArcNow = (G->Nbase+vertex)->nextArc;    // 下一条弧
        while(ArcNow != NULL)   // 循环递归该顶点的所有弧
        {
    
    
            DFS(G, ArcNow->Head);   
            ArcNow = ArcNow->nextArc;
        }
    }
}

int GraphBFS(Graph *G)  // BFS
{
    
    
    int *Queue = (int*)malloc(sizeof(int) * G->len * G->len);   // 创建一个模拟队列
    int QFront, QTail, vertex, i;   // 队列顶指针 队列尾
    ArcNode *ArcNow;

    Queue[0] = 0; // 把0号顶点压入队列
    QFront = 0;
    QTail = 1;
    for (i = 0; i < G->len; ++i)    // 初始化标记数组
    {
    
    
        MarkGraph[i] = 0;
    }
    printf("\nGraphG BFS:");

    while(QFront < QTail)   // 队尾队头相等,则队列空
    {
    
    
        vertex = Queue[QFront]; // 队头出队
        QFront += 1;
        if (MarkGraph[vertex] == 0) // 类似于DFS了
        {
    
    
            printf("%c ", (G->Nbase+vertex)->NodeName); // 输出当前顶点信息
            MarkGraph[vertex] = 1;  // 标记当前顶点已用
            ArcNow = (G->Nbase+vertex)->nextArc;    // 开始循环
            while(ArcNow != NULL)   // 非空
            {
    
    
                Queue[QTail] = ArcNow->Head;    // 入队
                QTail += 1;
                ArcNow = ArcNow->nextArc;   // 迭代
            }
        }
    }
    printf("\n");
}

Guess you like

Origin blog.csdn.net/u011017694/article/details/110621552