【Registro de aprendizagem de estrutura de dados 20】 —— Dois tipos de travessia do gráfico

Um. Dois tipos de travessia

1. Primeira pesquisa de profundidade (DFS)

A pesquisa em profundidade, como o nome sugere, é pesquisar lugares mais profundos primeiro. Supondo que seja uma árvore, a pesquisa em profundidade irá, preferencialmente, pesquisar 深度nós mais altos. Como o conceito de pesquisa em profundidade não retorna até o nó mais profundo, nós no mesmo nível são acessados ​​primeiro e, em seguida, percorridos, o que está em conformidade com o modelo de estrutura de pilha, portanto, nossa pesquisa em profundidade é geralmente implementada por meio de recursão.
Para este gráfico em forma de árvore:
Insira a descrição da imagem aqui
suponha que nosso percurso comece em 1, então ele irá preferencialmente visitar os vértices com maior profundidade:
Insira a descrição da imagem aqui
finalmente, sua ordem de percurso é:
GraphG DFS:1 2 4 8 5 3 6 7

2. Amplitude da primeira pesquisa (BFS)

A definição é semelhante ao DFS, a pesquisa em largura é primeiro pesquisar nós no mesmo nível antes de pesquisar nós na próxima profundidade. Vamos usar a árvore como exemplo: suponha que uma árvore seja pesquisada por largura primeiro, então ela primeiro atravessará seus nós irmãos antes de atravessar para os nós filhos mais profundos. Portanto, os filhos do mesmo nó são visitados primeiro e percorridos primeiro, portanto, está em linha com o modelo de fila, de modo que geralmente o implementamos por meio da fila.
Para esta imagem,
Insira a descrição da imagem aqui
nosso amplo processo de pesquisa é: O
Insira a descrição da imagem aqui
resultado é:
GraphG BFS:1 2 3 4 5 6 7 8

3. A diferença entre os dois

Use duas imagens para representar visualmente esses dois tipos de pesquisa. Por exemplo, o quadrado A está no labirinto e temos que percorrer o caminho até o fim.
Profundidade primeira pesquisa:
Insira a descrição da imagem aqui

Amplitude da primeira pesquisa:

Insira a descrição da imagem aqui

2. Implementação do código

Veja o efeito:
Insira a descrição da imagem aqui

Por causa das várias estruturas do grafo, adotamos o método de grafo direcionado + lista de adjacência para alcançá-lo.
Construa os vértices primeiro, depois os arcos.

#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");
}

Acho que você gosta

Origin blog.csdn.net/u011017694/article/details/110621552
Recomendado
Clasificación