首页 > 其他分享 >数据结构 图的遍历(广度优先遍历、深度优先遍历)

数据结构 图的遍历(广度优先遍历、深度优先遍历)

时间:2022-11-05 20:11:27浏览次数:47  
标签:vexnum 优先 遍历 return MGraph int char ++ 数据结构

8.6、图的广度优先遍历

  • 找到与顶点相邻的所有顶点,
  • 标记哪些顶点被访问过
  • 需要一个辅助队列

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

#define MaxSize 100
#define boolean int
#define true 1
#define false 0

//邻接矩阵存储图的信息
typedef struct MGraph{
    char Vex[MaxSize];//顶点信息
    int Edge[MaxSize][MaxSize];//邻接矩阵
    int vexnum,arcnum;//顶点数和边数
}MGraph;

//初始化一个邻接矩阵
boolean MG_Init(MGraph **G){
    *G = (MGraph*)malloc(sizeof(MGraph));
    if((*G) == NULL) return false;//申请空间失败
    (*G)->vexnum = 0;//顶点数为0
    (*G)->arcnum = 0;//边数为0
    // for(int i = 0;i < MaxSize;i++){
    //     for(int j = 0;j < MaxSize;j++){
    //         (*G)->Edge[i][j] = 0;
    //     }
    // }
    return true;
}

//获取该结点v的索引
int GetV_Index(MGraph *G,char v){
    for(int i = 0;i<G->vexnum;i++){
        if(G->Vex[i] == v) return i;
    }
    return -1;
}

//判断图中是否有结点v
boolean IsVEmpty(MGraph *G,char v){
    for(int i=0;i<G->vexnum;i++){
        if(G->Vex[i] == v) return true;//存在
    }
    return false;//不存在
}

//判断图中是否存在该边;传入边
boolean Adjancent(MGraph *G,char v,char w){
    int vi = GetV_Index(G,v);
    int wi = GetV_Index(G,w);

    return G->Edge[vi][wi];
}
//判断图中是否存在该边;传入边的索引
boolean Adjancent1(MGraph *G,int vi,int wi){
    if(G->Edge[vi][wi] == 1) return true;
    else return false;
}

//插入一个新的顶点
boolean InsertV(MGraph *G,char v){
    if(G->vexnum >= MaxSize || IsVEmpty(G,v)){
        printf("存储顶点数的空间满了或者改结点存在!\n");
        return false;
    }
    G->Vex[G->vexnum++] = v;
    return true;
}

//插入边(v,w)
boolean AddEdge(MGraph *G,char v,char w){
    if(!IsVEmpty(G,v) || !IsVEmpty(G,w)){
        printf("输入的边其中有一个顶点或者两个顶点不存在\n");
        return false;
    }
    //获取结点的索引
    int vi = GetV_Index(G,v);
    int wi = GetV_Index(G,w);
    if(Adjancent1(G,vi,wi)){
        printf("该边已经存在\n");
        return false;
    }
    //修改邻接矩阵
    G->Edge[vi][wi] = 1;
    G->Edge[wi][vi] = 1;
    //修改边数
    G->arcnum++;
    return true;
}

//删除边(v,w)
boolean RemoveEdge(MGraph *G,char v,char w){
    if(!IsVEmpty(G,v) || !IsVEmpty(G,w)){
        //判断这两个点是否存在
        printf("这两个点不存在\n");
        return false;
    }
    int vi = GetV_Index(G,v);
    int wi = GetV_Index(G,w);
    if(Adjancent1(G,vi,wi) == true){//存在该边就删除
        G->Edge[vi][wi] = 0;
        G->Edge[wi][vi] = 0;
        G->arcnum--;//边减1
        return true;
    }else{
        printf("删除的边不存在\n");
        return false;
    }
}

//获取某个结点v的所有邻接边
boolean NeighBors(MGraph *G,char v,char ***res,int *length){
    if(!IsVEmpty(G,v)){
        printf("输入的顶点不存在\n");
        return false;
    }
    int vi = GetV_Index(G,v);
    for(int i = 0;i < G->vexnum;i++){
        if(G->Edge[vi][i] == 1) {
            (*length)++;
        }
    }
    *res = (char **)malloc(sizeof(char)*(*length));
    int index = 0;
    for(int i = 0;i < G->vexnum;i++){
        if(G->Edge[vi][i] == 1) {
            (*res)[index] = (char *)malloc(sizeof(char)*2);
            (*res)[index][0] = v;
            (*res)[index][1] = G->Vex[i];
            index++;
        }
    }
    return true;
}


//队列的数据信息
typedef struct ElemType{
    int index;
    char v;
}ElemType;
//结点
typedef struct LinkNode{
    ElemType data;
    struct LinkNode *next;
}LinkNode;
//链队列定义
typedef struct{
    LinkNode *front,*rear;//*front 队头指针, *rear 队尾指针
}LinkQueue;
//初始化带头结点的队列
int InitLinkQueue(LinkQueue *Q){
    (*Q).front = (*Q).rear = (LinkNode *)malloc(sizeof(LinkNode));
    if((*Q).front == NULL || (*Q).rear == NULL) return false;
    (*Q).front->next = NULL;
    return true;
};
//带头结点判断是否为空
int IsEmpty(LinkQueue Q){
    if(Q.front == Q.rear) return true;
    else return false;
}
//带头结点入队操作
int EnQueue(LinkQueue *Q,ElemType e){
    LinkNode *p = (LinkNode *)malloc(sizeof(LinkNode));
    if(p==NULL) return false;//分配内存失败
    p->data = e;
    p->next = NULL;
    Q->rear->next = p;
    Q->rear = p;
}
//带头结点出队操作
int DeQueue(LinkQueue *Q,ElemType *e){
    if(Q->front == Q->rear) return false;//队列为空,出队失败
    LinkNode *p = Q->front->next;
    *e = p->data;
    Q->front->next = p->next;
    if(Q->rear == p){       //如果出队的元素是对尾元素,需要特殊处理
        Q->rear = Q->front;
    }
    free(p);//释放片
    return true;
}

//寻找某个结点V的所有邻接点
boolean Neighbors(MGraph *G,char V,int Vi,char **resNode,int **resIndex,int *length){
    for(int i = 0;i < G->vexnum;i++){
        if(G->Edge[Vi][i] == 1){
            (*length)++;
        } 
    }
    *resNode = (char *)malloc(sizeof(char)*(*length));
    *resIndex = (int *)malloc(sizeof(int)*(*length));
    int index = 0;
    for(int i = 0;i < G->vexnum;i++){
        if(G->Edge[Vi][i] == 1){
            (*resNode)[index] = G->Vex[i];
            (*resIndex)[index] = i;
            index++;
        }
    }
    return true;
}

//广度优先遍历
void BFS(MGraph *G,char V,int Vi,char **res,int *resLength,boolean **visited){
    LinkQueue Q;
    InitLinkQueue(&Q);
    ElemType e;
    e.index = Vi;
    e.v = V;
    (*visited)[Vi] = true;
    EnQueue(&Q,e);
    while(!IsEmpty(Q)){
        DeQueue(&Q,&e);
        (*res)[*resLength] = e.v;
        (*resLength)++;
        char *resChar;
        int *resIndex;
        int length = 0;
        Neighbors(G,e.v,e.index,&resChar,&resIndex,&length);
        for(int i = 0;i < length;i++){
            if((*visited)[resIndex[i]] == false){
                (*visited)[resIndex[i]] = true;
                ElemType e1;
                e1.index = resIndex[i];
                e1.v = resChar[i];
                EnQueue(&Q,e1);
            }
        }
    }
}
//访问结点
void visitV(char *res,int resLength){
    for(int i = 0;i < resLength;i++){
        printf("%c ,",res[i]);
    }
}
//对图G进行广度优先遍历
void BFSMGraph(MGraph *G,char V){
    int Vi = GetV_Index(G,V);
    char *res = (char *)malloc(sizeof(char)*G->vexnum);
    int resLength = 0;
    boolean *visited = (boolean *)malloc(sizeof(boolean)*G->vexnum);
    for(int i = 0;i < G->vexnum;i++){
        visited[i] = false;
    }
    BFS(G,'A',Vi,&res,&resLength,&visited);
    for(int i = 0;i < G->vexnum;i++){
        if(visited[i] == false){
            BFS(G,G->Vex[i],i,&res,&resLength,&visited);
        }
    }
    visitV(res,resLength);
}


int main(){
    MGraph *G;
    MG_Init(&G);
    printf("顶点数:%d;边数:%d\n",G->vexnum,G->arcnum);
    InsertV(G,'A');
    InsertV(G,'B');
    InsertV(G,'C');
    InsertV(G,'D');
    InsertV(G,'E');
    InsertV(G,'F');
    InsertV(G,'G');
    InsertV(G,'H');
    InsertV(G,'I');
    InsertV(G,'J');
    InsertV(G,'K');
    printf("顶点数:%d;边数:%d\n",G->vexnum,G->arcnum);
    AddEdge(G,'A','B');
    AddEdge(G,'A','C');
    AddEdge(G,'C','D');
    AddEdge(G,'D','E');
    AddEdge(G,'D','F');
    AddEdge(G,'E','F');
    AddEdge(G,'E','G');
    AddEdge(G,'F','G');
    AddEdge(G,'F','H');
    AddEdge(G,'G','H');
    AddEdge(G,'I','J');
    AddEdge(G,'J','K');
    AddEdge(G,'I','K');
    printf("顶点数:%d;边数:%d\n",G->vexnum,G->arcnum);
    BFSMGraph(G,'A');

    return 0;
}

//结果:
顶点数:0;边数:0
顶点数:11;边数:0
顶点数:11;边数:13
A ,B ,C ,D ,E ,F ,G ,H ,I ,J ,K ,

广度生成树

8.7、图的深度优先遍历

沿着一条路径往里面找,直到找不到结点才返回

使用递归的思想来完成

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

#define MaxSize 100
#define boolean int
#define true 1
#define false 0

//邻接矩阵存储图的信息
typedef struct MGraph{
    char Vex[MaxSize];//顶点信息
    int Edge[MaxSize][MaxSize];//邻接矩阵
    int vexnum,arcnum;//顶点数和边数
}MGraph;

//初始化一个邻接矩阵
boolean MG_Init(MGraph **G){
    *G = (MGraph*)malloc(sizeof(MGraph));
    if((*G) == NULL) return false;//申请空间失败
    (*G)->vexnum = 0;//顶点数为0
    (*G)->arcnum = 0;//边数为0
    // for(int i = 0;i < MaxSize;i++){
    //     for(int j = 0;j < MaxSize;j++){
    //         (*G)->Edge[i][j] = 0;
    //     }
    // }
    return true;
}

//获取该结点v的索引
int GetV_Index(MGraph *G,char v){
    for(int i = 0;i<G->vexnum;i++){
        if(G->Vex[i] == v) return i;
    }
    return -1;
}

//判断图中是否有结点v
boolean IsVEmpty(MGraph *G,char v){
    for(int i=0;i<G->vexnum;i++){
        if(G->Vex[i] == v) return true;//存在
    }
    return false;//不存在
}

//判断图中是否存在该边;传入边
boolean Adjancent(MGraph *G,char v,char w){
    int vi = GetV_Index(G,v);
    int wi = GetV_Index(G,w);

    return G->Edge[vi][wi];
}
//判断图中是否存在该边;传入边的索引
boolean Adjancent1(MGraph *G,int vi,int wi){
    if(G->Edge[vi][wi] == 1) return true;
    else return false;
}

//插入一个新的顶点
boolean InsertV(MGraph *G,char v){
    if(G->vexnum >= MaxSize || IsVEmpty(G,v)){
        printf("存储顶点数的空间满了或者改结点存在!\n");
        return false;
    }
    G->Vex[G->vexnum++] = v;
    return true;
}

//插入边(v,w)
boolean AddEdge(MGraph *G,char v,char w){
    if(!IsVEmpty(G,v) || !IsVEmpty(G,w)){
        printf("输入的边其中有一个顶点或者两个顶点不存在\n");
        return false;
    }
    //获取结点的索引
    int vi = GetV_Index(G,v);
    int wi = GetV_Index(G,w);
    if(Adjancent1(G,vi,wi)){
        printf("该边已经存在\n");
        return false;
    }
    //修改邻接矩阵
    G->Edge[vi][wi] = 1;
    G->Edge[wi][vi] = 1;
    //修改边数
    G->arcnum++;
    return true;
}

//删除边(v,w)
boolean RemoveEdge(MGraph *G,char v,char w){
    if(!IsVEmpty(G,v) || !IsVEmpty(G,w)){
        //判断这两个点是否存在
        printf("这两个点不存在\n");
        return false;
    }
    int vi = GetV_Index(G,v);
    int wi = GetV_Index(G,w);
    if(Adjancent1(G,vi,wi) == true){//存在该边就删除
        G->Edge[vi][wi] = 0;
        G->Edge[wi][vi] = 0;
        G->arcnum--;//边减1
        return true;
    }else{
        printf("删除的边不存在\n");
        return false;
    }
}

//获取某个结点v的所有邻接边
boolean NeighBors(MGraph *G,char v,char ***res,int *length){
    if(!IsVEmpty(G,v)){
        printf("输入的顶点不存在\n");
        return false;
    }
    int vi = GetV_Index(G,v);
    for(int i = 0;i < G->vexnum;i++){
        if(G->Edge[vi][i] == 1) {
            (*length)++;
        }
    }
    *res = (char **)malloc(sizeof(char)*(*length));
    int index = 0;
    for(int i = 0;i < G->vexnum;i++){
        if(G->Edge[vi][i] == 1) {
            (*res)[index] = (char *)malloc(sizeof(char)*2);
            (*res)[index][0] = v;
            (*res)[index][1] = G->Vex[i];
            index++;
        }
    }
    return true;
}

//寻找某个结点V的所有邻接点
boolean Neighbors(MGraph *G,char V,int Vi,char **resNode,int **resIndex,int *length){
    for(int i = 0;i < G->vexnum;i++){
        if(G->Edge[Vi][i] == 1){
            (*length)++;
        } 
    }
    *resNode = (char *)malloc(sizeof(char)*(*length));
    *resIndex = (int *)malloc(sizeof(int)*(*length));
    int index = 0;
    for(int i = 0;i < G->vexnum;i++){
        if(G->Edge[Vi][i] == 1){
            (*resNode)[index] = G->Vex[i];
            (*resIndex)[index] = i;
            index++;
        }
    }
    return true;
}


//访问结点
void visitV(char *res,int resLength){
    for(int i = 0;i < resLength;i++){
        printf("%c ,",res[i]);
    }
}

//深度优先遍历
void DFS(MGraph *G,char V,int Vi,char **res,int *resLength,boolean **visited){
    (*visited)[Vi] = true;
    (*res)[*resLength] = V;
    (*resLength)++;
    char *resChar;
    int *resIndex;
    int length = 0;
    Neighbors(G,V,Vi,&resChar,&resIndex,&length);
    for(int i = 0;i < length;i++){
        if((*visited)[resIndex[i]] == false){
            DFS(G,resChar[i],resIndex[i],res,resLength,visited);
        }
    }
}
//对图G进行广度优先遍历
void DFSMGraph(MGraph *G,char V){
    int Vi = GetV_Index(G,V);
    char *res = (char *)malloc(sizeof(char)*G->vexnum);
    int resLength = 0;
    boolean *visited = (boolean *)malloc(sizeof(boolean)*G->vexnum);
    for(int i = 0;i < G->vexnum;i++){
        visited[i] = false;
    }
    DFS(G,V,Vi,&res,&resLength,&visited);
    for(int i = 0;i < G->vexnum;i++){
        if(visited[i] == false){
            DFS(G,G->Vex[i],i,&res,&resLength,&visited);
        }
    }
    visitV(res,resLength);
}


int main(){
    MGraph *G;
    MG_Init(&G);
    printf("顶点数:%d;边数:%d\n",G->vexnum,G->arcnum);
    InsertV(G,'A');
    InsertV(G,'B');
    InsertV(G,'C');
    InsertV(G,'D');
    InsertV(G,'E');
    InsertV(G,'F');
    InsertV(G,'G');
    InsertV(G,'H');
    InsertV(G,'I');
    InsertV(G,'J');
    InsertV(G,'K');
    printf("顶点数:%d;边数:%d\n",G->vexnum,G->arcnum);
    AddEdge(G,'A','B');
    AddEdge(G,'A','C');
    AddEdge(G,'C','D');
    AddEdge(G,'D','E');
    AddEdge(G,'D','F');
    AddEdge(G,'E','F');
    AddEdge(G,'E','G');
    AddEdge(G,'F','G');
    AddEdge(G,'F','H');
    AddEdge(G,'G','H');
    AddEdge(G,'I','J');
    AddEdge(G,'J','K');
    AddEdge(G,'I','K');
    printf("顶点数:%d;边数:%d\n",G->vexnum,G->arcnum);
    DFSMGraph(G,'C');

    return 0;
}
//结果:
顶点数:0;边数:0
顶点数:11;边数:0
顶点数:11;边数:13
C ,A ,B ,D ,E ,F ,G ,H ,I ,J ,K ,

标签:vexnum,优先,遍历,return,MGraph,int,char,++,数据结构
From: https://www.cnblogs.com/shuisanya/p/16860983.html

相关文章

  • 105. 从前序与中序遍历序列构造二叉树
    给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。示例1:  输入:pre......
  • 二叉树的遍历总结
    二叉树的遍历总结前序:https://leetcode.cn/problems/binary-tree-preorder-traversal/中序:https://leetcode.cn/problems/binary-tree-inorder-traversal/后序:https://l......
  • C++——优先级队列(priority_queue)
    其为队列需要包含头文件#include,其与queue的不同之处在于,可以自定义数据的优先级,让优先级高的排在队列的前面,优先出队;优先队列具有队列的所有特性,包括基本操作,只是在此基......
  • 数据结构基本知识
    数据结构主要研究非数值计算问题数据结构是带“结构”的数据元素的集合算法+数据结构=程序 数据:是客观事物的符号表示,是所有能输入计算机中并被计算机程序处理的符号......
  • 数据结构扩展
    数据类型扩展float类型要在数字后面加个Flong类型要在数字后面加个L010是八进制的‘10’,也就是说这个数是80x10是十六进制的‘10’,也就是16floatf=0.......
  • JAVA8-Lambda-forEach遍历List/Map
    一、遍历List代码示例publicstaticvoidmain(String[]args){List<String>list=Arrays.asList("北","上","广","深");list.forEach(System.out::prin......
  • 数据结构与算法之查找
    查找【知识框架】1.查找概论查找的基本概念:查找(Searching):就是根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录)。查找表(SearchTable......
  • 数据结构--011--STL容器deque代码学习
    不提供代码了-------------------------------------------------------------------------------------------------------------自己网上找来自己撸---------------------......
  • LeetCode 145. 二叉树的后序遍历
    问题描述给定一个二叉树,返回它的后序遍历。示例:进阶:递归算法很简单,你可以通过迭代算法完成吗?题目代码/***Definitionforabinarytreenode.*publicclassTre......
  • MySQL---索引的数据结构
    索引的数据结构为什么使用索引索引及其优缺点概述优点缺点InNoDB中索引的推演索引之前的查找在一个页......