【C语言】数据结构——邻接矩阵的bfs dfs

研究了很长时间,注释就是我的心得体会

//dfs,bfs的多种实现

//code 1 邻接矩阵

#include<stdio.h>

#include<stdlib.h>

#include<malloc.h>

#include<string.h>

#include<stdbool.h>

#define INF __INT_MAX__ //最大值,有向网,无向网用

#define MAXSIZE 50 //最多几个节点

typedef int Staus;//实现功能函数

typedef int HStaus;//辅助函数

typedef char VertexType[4]; //节点名称,也就是每个节点叫啥

typedef char IntoPtr;//用来指定弧的信息

typedef int VRType;//是否有弧(网时有权值)

typedef enum{DG,DN,UDG,UDN} GraphKind;//图的类型(有向图,有向网,无向图,无向网)

typedef struct{

    VRType adj;//邻接矩阵的0 1存储位置

    IntoPtr*info;//储存信息,先给指针数组的头结点,之后有需要开辟新空间

}ArcNode,AdjMatrix[MAXSIZE][MAXSIZE];/*邻接表,要用的!*/

typedef struct{

    VertexType vex[MAXSIZE];//用于存储节点信息,只需要把节点记在一个数组中即可,不用附加其他条件

    AdjMatrix arc;//直接把邻接矩阵放在这个图的定义里,方便后续拿取

    int vernum,arcnum;//顶点数和弧的数目

    GraphKind kind;//图的类型

}MGraph;

bool visted[MAXSIZE];

//创建列表

HStaus CreateGraphALL(MGraph &N);

//创建有向图

Staus CreateGraphDG(MGraph &N);

//创建无向图

Staus CreateGraphUDG(MGraph &N);

//创建有向网

Staus CreateGraphDN(MGraph &N);

//创建无向网

Staus CreateGraphUDN(MGraph &N);

//深度优先算法

void DFS(MGraph N,int checknum);

void DFSTra(MGraph N);//这个函数的目的是使visited数组初始化,并且还能规避不连通图

//广度优先算法

void BFSTraverse(MGraph G);

//定义队列

typedef struct{

    int data[MAXSIZE];

    int front;

    int rear;

}Queue;

//初始化空队列

HStaus InitQueue(Queue &Q);

//判断队列是否为空

HStaus QueueEmpty(Queue Q);

//插入

HStaus EnQueue(Queue&Q,int*e);

//删除

HStaus DeQueue(Queue&Q,int&e);

//找到节点的位置,用于构建领接矩阵

HStaus FindPos(VertexType str,MGraph N);

//展示图

void ShowGraphA(MGraph N);

//展示网

void ShowGraphB(MGraph N);

//销毁图

void DestoryGraph(MGraph &N);

int main(void)

{

    MGraph GraA;

    int ret=0;

    printf("创建一个图GraA!\n");

    ret=CreateGraphALL(GraA);

    switch(ret)

    {

        case 1:ShowGraphA(GraA);break;

        case 2:ShowGraphB(GraA);break;

        default:break;

    }

    DFSTra(GraA);

    BFSTraverse(GraA);

    DestoryGraph(GraA);

    return 0;

}

HStaus CreateGraphALL(MGraph &N)

{

    int ki=0;

    printf("请输入图的类型(有向图:1,有向网:2,无向图:3,无向网:4)");

    scanf("%d",&ki);

    switch(ki)

    {

        case 1: CreateGraphDG(N);return true;

        case 2: CreateGraphDN(N);return true+1;

        case 3: CreateGraphUDG(N);return true;

        case 4: CreateGraphUDN(N);return true+1;

        default: printf("error!");return false;

    }

}

Staus CreateGraphDG(MGraph &N)

{

    MGraph* ptr=&N;

    printf("请输入节点个数:");

    scanf("%d",&ptr->vernum);

    printf("请输入%d个节点(小于四个字符)的值,每个节点之间用‘ ’区分:",ptr->vernum);

    //输入节点

    for(int i=0;i<ptr->vernum;i++)

    {

        char tempchar[4]={'\0'};

        scanf("%s",tempchar);

        strcpy(ptr->vex[i],tempchar);

    }

    //初始化邻接矩阵

    for(int i=0;i<ptr->vernum;i++)

    {

        for(int j=0;j<ptr->vernum;j++)

        {

            ptr->arc[i][j].adj=0;

            ptr->arc[i][j].info=NULL;

        }

    }

    //输入弧

    printf("请输入有几条弧:");

    scanf("%d",&ptr->arcnum);

    printf("请指定%d条弧的弧头、弧尾 (若弧包含信息,请输入1)\n",ptr->arcnum);

    printf("格式为:弧头 弧尾 是否有信息:");

    for(int i=0;i<ptr->arcnum;i++)

    {

        VertexType v1={'\0'},v2={'\0'};

        int message=0;

        int v1num=0,v2num=0;

        printf("第%d次输入",i+1);

        scanf("%s %s %d",v1,v2,&message);

        v1num=FindPos(v1,N);

        //printf("\n v1num:%d",v1num);

        v2num=FindPos(v2,N);

        //printf("\n v2num:%d",v2num);

        ptr->arc[v1num][v2num].adj=1;

        //有信息执行

        if(message==1)

        {

            char Mestemp[10]={'\0'};

            printf("请输入该弧的信息(不超过10个字节)");

            scanf("%s",Mestemp);

            ptr->arc[v1num][v2num].info=(char*)malloc(sizeof(Mestemp));

            strcpy(ptr->arc[v1num][v2num].info,Mestemp);

        }

    }

    return true;

}

HStaus FindPos(VertexType str,MGraph N)

{

    int i=0;

    for(i=0;i<N.vernum;i++)

    {

        if(strcmp(str,N.vex[i])==0)

        {

            return i;

        }

    }

    return false;

}

void ShowGraphA(MGraph N)

{

    printf("图的类型为:");

    switch(N.kind)

    {

        case DG:printf("有向图\n");break;

        case DN:printf("有向网\n");break;

        case UDG:printf("无向图\n");break;

        case UDN:printf("无向网\n");break;

        default:printf("error!");return;

    }

    printf("图的节点有:\n");

    for(int i=0;i<N.vernum;i++)

    {

        printf("%s",N.vex[i]);

        printf("\n");

    }

    printf("图的邻接矩阵有:\n");

    for(int i=0;i<N.vernum;i++)

    {

        for(int j=0;j<N.vernum;j++)

        {

            printf("%4d",N.arc[i][j].adj);

        }

        printf("\n");

    }

}

Staus CreateGraphUDG(MGraph &N)

{

    MGraph* ptr=&N;

    printf("请输入节点个数:");

    scanf("%d",&ptr->vernum);

    printf("请输入%d个节点(小于四个字符)的值,每个节点之间用‘ ’区分:",ptr->vernum);

    //输入节点

    for(int i=0;i<ptr->vernum;i++)

    {

        char tempchar[4]={'\0'};

        scanf("%s",tempchar);

        strcpy(ptr->vex[i],tempchar);

    }

    //初始化邻接矩阵

    for(int i=0;i<ptr->vernum;i++)

    {

        for(int j=0;j<ptr->vernum;j++)

        {

            ptr->arc[i][j].adj=0;

            ptr->arc[i][j].info=NULL;

        }

    }

    //输入弧

    printf("请输入有几条边(一半):");

    scanf("%d",&ptr->arcnum);

    printf("请指定%d条弧的弧头、弧尾 (若弧包含信息,请输入1)\n",ptr->arcnum*2);

    printf("格式为:弧头 弧尾 是否有信息:");

    for(int i=0;i<ptr->arcnum;i++)

    {

        VertexType v1={'\0'},v2={'\0'};

        int message=0;

        int v1num=0,v2num=0;

        printf("第%d次输入",i+1);

        scanf("%s %s %d",v1,v2,&message);

        v1num=FindPos(v1,N);

        //printf("\n v1num:%d",v1num);

        v2num=FindPos(v2,N);

        //printf("\n v2num:%d",v2num);

        ptr->arc[v1num][v2num].adj=1;

        ptr->arc[v2num][v1num].adj=1;

        //有信息执行

        if(message==1)

        {

            char Mestemp[10]={'\0'};

            printf("请输入该弧的信息(不超过10个字节)");

            scanf("%s",Mestemp);

            ptr->arc[v1num][v2num].info=(char*)malloc(sizeof(Mestemp));

            ptr->arc[v2num][v1num].info=(char*)malloc(sizeof(Mestemp));

            strcpy(ptr->arc[v1num][v2num].info,Mestemp);

            strcpy(ptr->arc[v2num][v1num].info,Mestemp);

        }

    }

    return true;

}

void DestoryGraph(MGraph &N)

{

    for(int i=0;i<N.vernum;i++)

    {

        for(int j=0;j<N.vernum;j++)

        {

            if(N.arc[i][j].adj!=INF)

            {

                if(N.arc[i][j].info!=NULL)

                {

                    free(N.arc[i][j].info);

                    N.arc[i][j].info=NULL;

                }

            }

        }

    }

    N.vernum=0;

    N.arcnum=0;

}

Staus CreateGraphDN(MGraph &N)

{

    MGraph* ptr=&N;

    printf("请输入节点个数:");

    scanf("%d",&ptr->vernum);

    printf("请输入%d个节点(小于四个字符)的值,每个节点之间用‘ ’区分:",ptr->vernum);

    //输入节点

    for(int i=0;i<ptr->vernum;i++)

    {

        char tempchar[4]={'\0'};

        scanf("%s",tempchar);

        strcpy(ptr->vex[i],tempchar);

    }

    //初始化邻接矩阵

    for(int i=0;i<ptr->vernum;i++)

    {

        for(int j=0;j<ptr->vernum;j++)

        {

            ptr->arc[i][j].adj=INF;

            ptr->arc[i][j].info=NULL;

        }

    }

    //输入弧

    printf("请输入有几条弧:");

    scanf("%d",&ptr->arcnum);

    printf("请指定%d条弧的弧头、弧尾 权值(若弧包含信息,请输入1)\n",ptr->arcnum);

    printf("格式为:弧头 弧尾 权值 是否有信息:");

    for(int i=0;i<ptr->arcnum;i++)

    {

        VertexType v1={'\0'},v2={'\0'};

        int message=0;

        int v1num=0,v2num=0;

        int rig=0;

        printf("第%d次输入",i+1);

        scanf("%s %s %d %d",v1,v2,&rig,&message);

        v1num=FindPos(v1,N);

        //printf("\n v1num:%d",v1num);

        v2num=FindPos(v2,N);

        //printf("\n v2num:%d",v2num);

        ptr->arc[v1num][v2num].adj=rig;

        //有信息执行

        if(message==1)

        {

            char Mestemp[10]={'\0'};

            printf("请输入该弧的信息(不超过10个字节)");

            scanf("%s",Mestemp);

            ptr->arc[v1num][v2num].info=(char*)malloc(sizeof(Mestemp));

            strcpy(ptr->arc[v1num][v2num].info,Mestemp);

        }

    }

    return true;

}

void ShowGraphB(MGraph N)

{

    printf("图的类型为:");

    switch(N.kind)

    {

        case DG:printf("有向图\n");break;

        case DN:printf("有向网\n");break;

        case UDG:printf("无向图\n");break;

        case UDN:printf("无向网\n");break;

        default:printf("error!");return;

    }

    printf("图的节点有:\n");

    for(int i=0;i<N.vernum;i++)

    {

        printf("%s",N.vex[i]);

        printf("\n");

    }

    printf("图的邻接矩阵有:\n");

    for(int i=0;i<N.vernum;i++)

    {

        for(int j=0;j<N.vernum;j++)

        {

            if(N.arc[i][j].adj==INF)

            {

                printf("   ∞");

            }

            else

            {

                printf("%4d",N.arc[i][j].adj);

            }

        }

        printf("\n");

    }

}

Staus CreateGraphUDN(MGraph &N)

{

    MGraph* ptr=&N;

    printf("请输入节点个数:");

    scanf("%d",&ptr->vernum);

    printf("请输入%d个节点(小于四个字符)的值,每个节点之间用‘ ’区分:",ptr->vernum);

    //输入节点

    for(int i=0;i<ptr->vernum;i++)

    {

        char tempchar[4]={'\0'};

        scanf("%s",tempchar);

        strcpy(ptr->vex[i],tempchar);

    }

    //初始化邻接矩阵

    for(int i=0;i<ptr->vernum;i++)

    {

        for(int j=0;j<ptr->vernum;j++)

        {

            ptr->arc[i][j].adj=INF;

            ptr->arc[i][j].info=NULL;

        }

    }

    //输入弧

    printf("请输入有几条边(一半):");

    scanf("%d",&ptr->arcnum);

    printf("请指定%d条弧的弧头、弧尾 权值(若弧包含信息,请输入1)\n",ptr->arcnum*2);

    printf("格式为:弧头 弧尾 权值 是否有信息:");

    for(int i=0;i<ptr->arcnum;i++)

    {

        VertexType v1={'\0'},v2={'\0'};

        int message=0;

        int v1num=0,v2num=0;

        int rig=0;

        printf("第%d次输入",i+1);

        scanf("%s %s %d %d",v1,v2,&rig,&message);

        v1num=FindPos(v1,N);

        //printf("\n v1num:%d",v1num);

        v2num=FindPos(v2,N);

        //printf("\n v2num:%d",v2num);

        ptr->arc[v1num][v2num].adj=rig;

        ptr->arc[v2num][v1num].adj=rig;

        //有信息执行

        if(message==1)

        {

            char Mestemp[10]={'\0'};

            printf("请输入该弧的信息(不超过10个字节)");

            scanf("%s",Mestemp);

            ptr->arc[v1num][v2num].info=(char*)malloc(sizeof(Mestemp));

            ptr->arc[v2num][v1num].info=(char*)malloc(sizeof(Mestemp));

            strcpy(ptr->arc[v1num][v2num].info,Mestemp);

            strcpy(ptr->arc[v2num][v1num].info,Mestemp);

        }

    }

    return true;

}

void DFS(MGraph N,int checknum)

{

    visted[checknum]=true;//开始访问这个节点了,所以要标记一下

    printf("%4s",N.vex[checknum]);

    for(int i=0;i<N.vernum;i++)//现在的checknum是固定的,现在找与checknum链接的节点,然后搜索到的节点继续往下深搜

    {

        if(!visted[i]&&N.arc[checknum][i].adj==1)//未访问而且有路能找到这个节点

        {

            DFS(N,i);//往下深度搜索,其实有隐含着return的条件:一条路也找不见就直接返回了

        }

    }

}

void DFSTra(MGraph N)

{

    printf("开始深度搜索!\n");

    for(int i=0;i<N.vernum;i++)

    {

        visted[i]=false;//初始全是未访问

    }

    for(int i=0;i<N.vernum;i++)

    {

        if(!visted[i])

        {

            DFS(N,i);//正因为visted数组是全局变量,所以这里吧vis修改后就不变了

        }

    }

    printf("\n");

}

HStaus InitQueue(Queue &Q)

{

    Queue*ptr=&Q;

    ptr->front=0;

    ptr->rear=0;

    return true;

}

HStaus EnQueue(Queue&Q,int e)

{

    Queue*ptr=&Q;

    if((ptr->rear+1)%MAXSIZE==ptr->front)

    {

        return false;

    }

    ptr->data[ptr->rear]=e;

    ptr->rear=(ptr->rear+1)%MAXSIZE;

    return true;

}

HStaus QueueEmpty(Queue Q)

{

    if(Q.front==Q.rear)

    {

        return true;

    }

    else

    {

        return false;

    }

}

HStaus DeQueue(Queue&Q,int*e)

{

    Queue*ptr=&Q;

    if(ptr->front==ptr->rear)//判断是不是空队列

    {

        return false;

    }

    *e=ptr->data[ptr->front];//用于返回删除的值

    ptr->front=(ptr->front+1)%MAXSIZE;

    return true;

}

void BFSTraverse(MGraph G)

{

    Queue Q;

    printf("开始广度优先遍历!\n");

    for(int i=0;i<G.vernum;i++)//初始化访问数组

    {

        visted[i]=false;

    }

    InitQueue(Q);//初始化辅助队列

    for(int i=0;i<G.vernum;i++)

    {

        if(!visted[i])

        {

            visted[i]=true;

            printf("%4s",G.vex[i]);

            EnQueue(Q,i);

            while (!QueueEmpty(Q))

            {

                DeQueue(Q,&i);

                for(int j=0;j<G.vernum;j++)

                {

                    if(G.arc[i][j].adj==1&&!visted[j])

                    {

                        visted[j]=true;

                        printf("%4s",G.vex[j]);//从母节点开始,把与母节点相连的都放进队列里

                        EnQueue(Q,j);//在下一回循环时就能把下一个节点输出,并且把下一层加到队列中

                    }//这样不断的就能慢慢把信息输出完

                }

            }

           

        }

    }

    printf("\n");

}

以下是C语言邻接矩阵实现的BFSDFS算法的示例代码: BFS算法: ```c #include <stdio.h> #include <stdlib.h> #define MaxInt 32767 #define MVNum 100 typedef char VerTexType; typedef int ArcType; typedef struct { VerTexType vexs[MVNum]; ArcType arcs[MVNum][MVNum]; int vexnum, arcnum; } AMGraph; int visited[MVNum]; void BFS(AMGraph G, int v) { int queue[MVNum], front = 0, rear = 0; int i, j, w; printf("%c ", G.vexs[v]); visited[v] = 1; queue[rear++] = v; while (front != rear) { i = queue[front++]; for (j = 0; j < G.vexnum; j++) { if (G.arcs[i][j] != MaxInt && !visited[j]) { printf("%c ", G.vexs[j]); visited[j] = 1; queue[rear++] = j; } } } } int main() { AMGraph G; int i, j; printf("请输入顶点数和边数:"); scanf("%d%d", &G.vexnum, &G.arcnum); printf("请输入顶点信息:"); for (i = 0; i < G.vexnum; i++) { scanf("%c", &G.vexs[i]); } printf("请输入邻接矩阵:"); for (i = 0; i < G.vexnum; i++) { for (j = 0; j < G.vexnum; j++) { scanf("%d", &G.arcs[i][j]); if (G.arcs[i][j] == 0) { G.arcs[i][j] = MaxInt; } } } printf("请输入遍历起点:"); int v; scanf("%d", &v); printf("BFS遍历结果:"); BFS(G, v); return 0; } ``` DFS算法: ```c #include <stdio.h> #include <stdlib.h> #define MaxInt 32767 #define MVNum 100 typedef char VerTexType; typedef int ArcType; typedef struct { VerTexType vexs[MVNum]; ArcType arcs[MVNum][MVNum]; int vexnum, arcnum; } AMGraph; int visited[MVNum]; void DFS(AMGraph G, int v) { int i; printf("%c ", G.vexs[v]); visited[v] = 1; for (i = 0; i < G.vexnum; i++) { if (G.arcs[v][i] != MaxInt && !visited[i]) { DFS(G, i); } } } int main() { AMGraph G; int i, j; printf("请输入顶点数和边数:"); scanf("%d%d", &G.vexnum, &G.arcnum); printf("请输入顶点信息:"); for (i = 0; i < G.vexnum; i++) { scanf("%c", &G.vexs[i]); } printf("请输入邻接矩阵:"); for (i = 0; i < G.vexnum; i++) { for (j = 0; j < G.vexnum; j++) { scanf("%d", &G.arcs[i][j]); if (G.arcs[i][j] == 0) { G.arcs[i][j] = MaxInt; } } } printf("请输入遍历起点:"); int v; scanf("%d", &v); printf("DFS遍历结果:"); DFS(G, v); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值