C语言 图的广度优化搜索

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

图的广度优化搜索简介

所有因为展开节点而得到的子节点都会被加进一个先进先出的队列中。一般的实现里,其邻居节点尚未被检验过的节点会被放置在一个被称为 open 的容器中(例如队列或是链表),而被检验过的节点则被放置在被称为 closed 的容器中。(open-closed表)

与深度优化搜索相比,深度优化搜索并不能找出最短路径。而广度优化搜索正是为了这个目标才出现的。

实现过程

注:以下图片取自:数据结构(七)图
这里写图片描述

实现关键:
* 需要一个队列
* 不能够使用递进的方法

我的想法是分成三个部分:
1. 插入顶点,将顶点入队列
2. 遍历顶点之后的所有树,进入队列
3. 依次出列,从1开始循环,直到所有顶点被遍历到

代码实现

核心部分:

void bfs(AdjGraphPtr adj, int *marked, int pos, QueuePtr q) {
    if (*(marked + pos) == 0) {
        //one
        insertQueue(q, adj->vertexList[pos]->data);
        *(marked + pos) = 1;

        //two
        EdgePtr e = adj->vertexList[pos]->firstEdge;
        int vPos;
        while (e == NULL) {
            insertQueue(q, e->adjvex);
            vPos = _vertexPos(adj, e->adjvex);
            *(marked + vPos) = 1;
            e = e->next;
        }

        //three
        while (q->head != NULL) {
            VTYPE vertex = outQueue(q);
            printf("%c\n", vertex);
            //vPos = _vertexPos(a, vertex);
            //bfs(a, marked, vPos, s);  //错误

            vPos = _vertexPos(adj, vertex);
            e = adj->vertexList[vPos]->firstEdge;
            while (e != NULL) {
                vPos = _vertexPos(adj, e->adjvex);
                if (*(marked + vPos) == 0) {
                    insertQueue(q, e->adjvex);
                    *(marked + vPos) = 1;
                }
                e = e->next;
            }
        }
    }
}

void breadthFirstSearch(AdjGraphPtr adj){
    QueuePtr q = createQueue();
    int length = adj->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)
            bfs(adj, marked, i, q);  //first:0
    }
    free(marked);
}

ADT:

#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;

typedef struct qnode {
    VTYPE data;
    struct qnode *next;
} QueueNode, *QueueNodePtr;

typedef struct {
    QueueNodePtr head;
    QueueNodePtr tail;
} Queue, *QueuePtr;

QueuePtr createQueue();
QueueNodePtr createQueueNode(VTYPE key);
void insertQueue(QueuePtr q, VTYPE key);
VTYPE outQueue(QueuePtr q);
void deleteQueue(QueuePtr q);

void freeAdj(AdjGraphPtr a);
int _vertexPos(const AdjGraphPtr m, const VTYPE key);

EdgePtr createEdgeNode(VTYPE key);
void insertVertex(AdjGraphPtr adj, const VTYPE key);
void insertEdge(AdjGraphPtr adj, VTYPE a, VTYPE b, int weight);

AdjGraphPtr createAdjGraph(VTYPE *v, int v_length, 
                            int *e, int e_length_1, int e_length_2) ; //test

void bfs(AdjGraphPtr adj, int *marked, int pos, QueuePtr q);
void breadthFirstSearch(AdjGraphPtr adj);

完整代码:

#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;

typedef struct qnode {
    VTYPE data;
    struct qnode *next;
} QueueNode, *QueueNodePtr;

typedef struct {
    QueueNodePtr head;
    QueueNodePtr tail;
} Queue, *QueuePtr;

QueuePtr createQueue();
QueueNodePtr createQueueNode(VTYPE key);
void insertQueue(QueuePtr q, VTYPE key);
VTYPE outQueue(QueuePtr q);
void deleteQueue(QueuePtr q);

void freeAdj(AdjGraphPtr a);
int _vertexPos(const AdjGraphPtr m, const VTYPE key);

EdgePtr createEdgeNode(VTYPE key);
void insertVertex(AdjGraphPtr adj, const VTYPE key);
void insertEdge(AdjGraphPtr adj, VTYPE a, VTYPE b, int weight);

AdjGraphPtr createAdjGraph(VTYPE *v, int v_length, 
                            int *e, int e_length_1, int e_length_2) ; //test


void bfs(AdjGraphPtr adj, int *marked, int pos, QueuePtr q) {
    if (*(marked + pos) == 0) {
        insertQueue(q, adj->vertexList[pos]->data);
        *(marked + pos) = 1;

        EdgePtr e = adj->vertexList[pos]->firstEdge;
        int vPos;
        while (e == NULL) {
            insertQueue(q, e->adjvex);
            vPos = _vertexPos(adj, e->adjvex);
            *(marked + vPos) = 1;
            e = e->next;
        }

        while (q->head != NULL) {
            VTYPE vertex = outQueue(q);
            printf("%c\n", vertex);
            //vPos = _vertexPos(a, vertex);
            //bfs(a, marked, vPos, s);  //错误

            vPos = _vertexPos(adj, vertex);
            e = adj->vertexList[vPos]->firstEdge;
            while (e != NULL) {
                vPos = _vertexPos(adj, e->adjvex);
                if (*(marked + vPos) == 0) {
                    insertQueue(q, e->adjvex);
                    *(marked + vPos) = 1;
                }
                e = e->next;
            }
        }
    }
}

void breadthFirstSearch(AdjGraphPtr adj){
    QueuePtr q = createQueue();
    int length = adj->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)
            bfs(adj, marked, i, q);  //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);
    breadthFirstSearch(adj);
    freeAdj(adj);
}




QueuePtr createQueue() {
    QueuePtr q = (QueuePtr)malloc(sizeof(Queue));
    memset(q, 0, sizeof(Queue));
    q->head = q->tail = NULL;
    return q;
}

QueueNodePtr createQueueNode(VTYPE key) {
    QueueNodePtr q = (QueueNodePtr)malloc(sizeof(Queue));
    memset(q, 0, sizeof(QueueNode));
    q->next = NULL;
    q->data = key;
    return q;
}

void insertQueue(QueuePtr q, VTYPE key) {
    QueueNodePtr a = createQueueNode(key);
    if (q->head == NULL) {  //notice
        q->head = q->tail = a;
    }
    else {
        q->tail->next = a;
        q->tail = a;
    }
}

VTYPE outQueue(QueuePtr q) {
    VTYPE v;
    if (q->head != NULL) {   //notice
        v = q->head->data;
        QueueNodePtr tmp = q->head->next;
        free(q->head);
        q->head = tmp;
    }
    else {
        v = NULL;
    }
    return v;
}

void deleteQueue(QueuePtr q) {
    if (q->head != NULL) {  //notice
        QueueNodePtr tmp = q->head;
        QueueNodePtr tmp2;
        while (tmp != NULL) {
            tmp2 = tmp;
            tmp = tmp->next;
            free(tmp2);
        }
    }
    free(q);
}


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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值