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

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 ,
posted @ 2022-11-05 20:08  水三丫  阅读(178)  评论(0编辑  收藏  举报