C语言 图的深度优化搜索

29 篇文章 0 订阅
8 篇文章 0 订阅

深度优先遍历简介

深度优先遍历图的方法是,从图中某顶点v出发:
(1)访问顶点v;
(2)依次从v的未被访问的邻接点出发,对图进行深度优先遍历;直至图中和v有路径相通的顶点都被访问;
(3)若此时图中尚有顶点未被访问,则从一个未被访问的顶点出发,重新进行深度优先遍历,直到图中所有顶点均被访问过为止。 当然,当人们刚刚掌握深度优先搜索的时候常常用它来走迷宫.事实上我们还有别的方法,那就是广度优先搜索(BFS).

实现过程

深度优化搜索可以追溯到Tremaux搜索:
注:图片取自书籍: 算法》 第四版
这里写图片描述

实现的几个关键步骤:
* 需要标注每一个经过的点,所以我们可以使用一个数组标记是否走过
* 通过递归的方式对顶点之后的节点递归

代码实现
void dfs(AdjGraphPtr a, int *marked, int pos) {
    if (*(marked + pos) == 0) {  //遍历每个结点
        printf("%c\n", a->vertexList[pos]->data);
        EdgePtr tmp = a->vertexList[pos]->firstEdge;  //while (tmp != NULL) {
            *(marked + pos) = 1;
            dfs(a, marked, _vertexPos(a, tmp->adjvex));
            tmp = tmp->next;
        }
    }
}

void depthFirstSearch(AdjGraphPtr a) {
    int length = a->vNum;
    int *marked = (int *)malloc(sizeof(int)*length);
    memset(marked, 0, sizeof(int)*length);
    for (int i = 0; i < length; i++) {
        if(*(marked +  i) == 0)
            dfs(a, marked, i);  //first:0
    }
    free(marked);
}

完整代码:
图:
这里写图片描述

#include <stdio.h>
#include <malloc.h>
#include <memory.h>
#define MAXVEX 100
#define VTYPE char

typedef struct EdgeNode {
    VTYPE adjvex;
    int weight;
    struct EdgeNode *next;
} Edge, *EdgePtr;

typedef struct VertexNode {
    VTYPE data;
    EdgePtr firstEdge;
} Vertex, *VertexPtr;

typedef struct {
    VertexPtr vertexList[MAXVEX];
    int vNum;
} AdjGraph, *AdjGraphPtr;

void freeAdj(AdjGraphPtr a) {
    for (int i = 0; i < a->vNum; i++) {
        EdgePtr tmp = a->vertexList[i]->firstEdge;
        while (tmp->next != NULL) {
            EdgePtr t = tmp;
            tmp = tmp->next;
            free(t);
        }
        free(tmp);
        free(a->vertexList[i]);
    }
    free(a);
}

EdgePtr createEdgeNode(VTYPE key) {
    EdgePtr a = (EdgePtr)malloc(sizeof(Edge));
    memset(a, 0, sizeof(Edge));
    a->adjvex = key;
    a->next = NULL;
    return a;
}


int _vertexPos(const AdjGraphPtr m, const VTYPE key) {
    for (int i = 0; i < m->vNum; i++) {
        if (m->vertexList[i]->data == key)
            return i;
    }
    return -1;
}


void insertVertex(AdjGraphPtr adj, const VTYPE key) {
    for (int i = 0; i < adj->vNum; i++) {
        if (adj->vertexList[i] == key)
            return;
    }

    VertexPtr vNode = (VertexPtr)malloc(sizeof(Vertex));
    memset(vNode, 0, sizeof(Vertex));
    vNode->data = key;
    vNode->firstEdge = NULL;

    adj->vertexList[adj->vNum] = vNode;
    adj->vNum++;
}

void insertEdge(AdjGraphPtr adj, VTYPE a, VTYPE b, int weight) {
    int pos_a = _vertexPos(adj, a);

    EdgePtr avex = createEdgeNode(b);
    avex->weight = weight;

    if (adj->vertexList[pos_a]->firstEdge == NULL) {
        adj->vertexList[pos_a]->firstEdge = avex;
    }
    else {
        EdgePtr tmp = adj->vertexList[pos_a]->firstEdge;
        while (tmp->next != NULL) {
            tmp = tmp->next;
        }
        tmp->next = avex;
    }
}


AdjGraphPtr createAdjGraph(VTYPE *v, int v_length, int *e, int e_length_1, int e_length_2) {
    AdjGraphPtr adj = (AdjGraphPtr)malloc(sizeof(AdjGraph));
    memset(adj, 0, sizeof(AdjGraph));

    for (int i = 0; i < v_length; i++) {
        insertVertex(adj, v[i]);
    }

    EdgePtr tmp = NULL;
    for (int i = 0; i < e_length_1; i++) {
        VTYPE a = *(e + e_length_2 * i + 0);
        VTYPE b = *(e + e_length_2 * i + 1);
        int weight = *(e + e_length_2 * i + 2);
        insertEdge(adj, a, b, weight);
    }
    return adj;
}

void dfs(AdjGraphPtr a, int *marked, int pos) {
    if (*(marked + pos) == 0) {  //遍历每个结点
        printf("%c\n", a->vertexList[pos]->data);
        EdgePtr tmp = a->vertexList[pos]->firstEdge;  //边
        while (tmp != NULL) {
            *(marked + pos) = 1;
            dfs(a, marked, _vertexPos(a, tmp->adjvex));
            tmp = tmp->next;
        }
    }
}

void depthFirstSearch(AdjGraphPtr a) {
    int length = a->vNum;
    int *marked = (int *)malloc(sizeof(int)*length);
    memset(marked, 0, sizeof(int)*length);
    for (int i = 0; i < length; i++) {
        if(*(marked +  i) == 0)
            dfs(a, marked, i);  //first:0
    }
    free(marked);
}

void main() {
    int e[13][3] = {
        { 'A', 'F', 60 },
        { 'A', 'E', 30 },
        { 'A', 'C', 10 },
        { 'F', 'A', 60 },
        { 'F', 'E', 20 },
        { 'E', 'A', 30 },
        { 'E', 'D', 50 },
        { 'D', 'E', 50 },
        { 'D', 'C', 11 },
        { 'C', 'D', 11 },
        { 'C', 'A', 10 },
        { 'C', 'B', 5 },
        { 'B', 'C', 5 }
    };
    const int e_length_1 = 13;
    const int e_length_2 = 3;

    VTYPE v[6] = { 'A','F','E','D','C','B' };
    const int v_length = 6;

    AdjGraphPtr adj = createAdjGraph(v, v_length, e, e_length_1, e_length_2);
    depthFirstSearch(adj);
    freeAdj(adj);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值