DFS和BFS

文章详细介绍了如何使用C语言实现无向图的数据结构,包括邻接矩阵和邻接列表,并展示了深度优先搜索(DFS)和广度优先搜索(BFS)算法的应用。
摘要由CSDN通过智能技术生成

 邻接矩阵实现无向图:

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<malloc.h>

#define MAX 100
#define LENGTH(a)  (sizeof(a)/sizeof(a[0]))
#define isLetter(a) ((((a)>='a')&&((a)<='z'))||(((a)>='A')&&((a)<='Z')))


//邻接矩阵
typedef struct _graph{
    char vexs[MAX];//顶点集合
    int vexnum;//顶点数
    int edgnum;//边数
    int matrix[MAX][MAX];//临界矩阵
}Graph,*PGraph;
//_graph Graph;*PGraph;

//返回ch在邻接矩阵中的位置
static int get_position(Graph g,char ch){
    int i;
    for(i=0;i<g.vexnum;i++){
        if(g.vexs[i]==ch)
            return i;
    }
    return -1;
}

//读取一个输入字符
static char read_char(){
    char ch;

    do{
    ch=getchar();
    }while(!isLetter(ch));

    return ch;
}

//创建自己输入的图
Graph* creat_graph(){
    char c1,c2;
    int v,e;
    int i,p1,p2;
    Graph* pG;

    //输入顶点数和边数
    printf("输入顶点数:");
    scanf("%d",&v);
    printf("输入边的个数:");
    scanf("%d",&e);
    if(v<1||e<1||(e>v*(v-1))){
        printf("输入错误");
        return NULL;
    }
    if((pG=(Graph*)malloc(sizeof(Graph)))==NULL)
        return NULL;
    memset(pG,0,sizeof(Graph));

    //初始化顶点数和边数
    pG->vexnum=v;
    pG->edgnum=e;
    //初始化顶点
    for(i=0;i<pG->vexnum;i++){
        printf("vertex(%d):",i);
        pG->vexs[i]=read_char();
    }
    //初始化边
    for(i=0;i<pG->edgnum;i++){
        //读取边的起始顶点和结束顶点
        printf("edge(%d):",i);
        c1=read_char();
        c2=read_char();

        p1=get_position(*pG,c1);
        p2=get_position(*pG,c2);

        if(p1==-1||p2==-1){
            printf("错误输入");
            free(pG);
            return NULL;
        }
        pG->matrix[p1][p2]=1;
        pG->matrix[p2][p1]=1;
    }

    return pG;

}

//用已经提供的图创建矩阵
Graph* creat_example_graph(){
    char vexs[ ] = {'A','B','C','D','E','F','G'};
    char edges[ ][2] = {
        {'A','C'},
        {'A','D'},
        {'A','F'},
        {'B','C'},
        {'C','D'},
        {'E','G'},
        {'F','G'}
    };
    int vlen = LENGTH(vexs);
    int elen = LENGTH(edges);
    int i,p1,p2;
    Graph* pG;
    //printf("%d %d\n",vlen,elen);

    //输入顶点数和边数
    if((pG=(Graph*)malloc(sizeof(Graph))) == NULL)
        return NULL;
    memset(pG,0,sizeof(Graph));

    //初始化顶点数和边数
    pG->vexnum = vlen;
    pG->edgnum = elen;
    //printf("%d %d\n",pG->vexnum,pG->edgnum);
    //初始化顶点
    for(i=0;i<pG->vexnum;i++){
        pG->vexs[i] = vexs[i];
    }
    //初始化边
    for(i=0;i<pG->edgnum;i++){
        //读取边的起始顶点和结束顶点
        p1 = get_position(*pG,edges[i][0]);
        p2 = get_position(*pG,edges[i][1]);
        //printf("%d %d\n",p1,p2);
        pG->matrix[p1][p2] = 1;
        pG->matrix[p2][p1] = 1;
    }

    return pG;
}

void DFSTraverse(Graph G){
    int i;
    int visited[MAX];

    //初始化所有顶点都没有被访问
    for(i=0;i<G.vexnum;i++)
        visited[i]=0;

    printf("DFS:");
    for(i=0;i<G.vexnum;i++){
        if(!visited[i])
            DFS(G,i,visited);
    }

}

//深度优先搜索遍历图的递归实现
void DFS(Graph G,int i,int *visited ){
    int w;

    visited[i] = 1;
    printf("%c ",G.vexs[i]);
    //遍历该顶点的所有邻接顶点,如果是没有访问过的,就继续往下走
    for(w = first_vertex(G,i);w >=0;w = next_vertix(G,i,w)){
        if(!visited[w])
            DFS(G,w,visited);
    }
}

//返回顶点v的第一个邻接顶点的索引,失败则返回-1
int first_vertex(Graph G,int v){
    int i;

    if(v<0||v>(G.vexnum-1))
        return -1;

    for(i=0;i<G.vexnum;i++){
        if(G.matrix[v][i] == 1)
            return i;
    }

    return -1;

}

//返回顶点v相对于w的下一个邻接顶点的索引,失败则返回-1
int next_vertix(Graph G,int v,int w){
    int i;

    if(v<0||v>(G.vexnum-1)||w<0||w>(G.vexnum-1))
        return -1;

    for(i=w+1;i<G.vexnum;i++){
        if(G.matrix[v][i]==1)
            return i;
    }
    return -1;
}

//广度优先搜索
static void BFS(Graph G){
    int head=0;
    int rear=0;
    int queue[MAX];//辅助队列
    int visited[MAX];//顶点访问标记
    int i,j,k;

    for(i=0;i<G.vexnum;i++){
        visited[i]=0;
    }

    printf("BFS: ");
    for(i=0;i<G.vexnum;i++){
        if(!visited[i]){
            visited[i]=1;//如果没有被访问,则将访问数组置为1,再进行输出,再入队列
            printf("%c ",G.vexs[i]);
            queue[rear++]=i;//入队列
        }
        while(head!=rear){
             j=queue[head++];//出队列
             for(k=first_vertex(G,j);k>=0;k=next_vertix(G,j,k)){
                if(!visited[k]){
                    visited[k]=1;
                    printf("%c ",G.vexs[k]);
                    queue[rear++]=k;
                }
             }
        }
    }
    printf("\n");
}

//打印矩阵队列
void print_graph(Graph G){
    int i,j;

    printf("无向图邻接矩阵:\n");
    for(i=0;i<G.vexnum;i++){
        for(j=0;j<G.vexnum;j++){
            printf("%d",G.matrix[i][j]);
        }
        printf("\n");
    }
}

int main()
{
    Graph *pG;

    //自定义图(输入矩阵队列)
    pG = creat_graph();
    //采用已有的图
    //pG  = creat_example_graph();

    print_graph(*pG);//打印出创建的图
    DFSTraverse(*pG);//深度优先搜索
    BFS(*pG);//广度优先搜索
    return 0;
}

领接表实现无向图:

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


#define MAX 100
#define LENGTH(a) (sizeof(a)/sizeof(a[0]))

//领接表中的表对应的链表的顶点
typedef struct _ENode{
    int ivex;//该边所指向的顶点的位置
    struct _ENode* next_edge;//指向下一条弧的指针
}ENode,*PENode;

//邻接表中的表的顶点
typedef struct _VNode{
    char data;//顶点信息
    ENode *first_edge;//指向第一条依附该顶点的弧
}VNode;

//邻接表
typedef struct _LGraph{
    int vexnum;//图的顶点个数
    int edgnum;//图的边的数目
    VNode vexs[MAX];
}LGraph;

//返回ch在邻接节点数组里面的位置

int get_position(LGraph g,char ch){
    int i;
    for(i=0;i<g.vexnum;i++){
        if(g.vexs[i].data==ch)
            return i;
    }
    return -1;
}

//将enode顶点链接到List的末尾
void link_last(ENode* list,ENode* node){
    ENode* p=list;
    while(p->next_edge)
        p=p->next_edge;
    p->next_edge=node;
}


//创建自定义的图
LGraph* creat_lgraph(){
    
}

//创建已有的图
LGraph* creat_example_lgraph(){
    char c1,c2;
    char vexs[ ]={'A','B','C','D','E','F','G'};
    char edges[ ][2]={
    {'A','C'},
    {'A','D'},
    {'A','F'},
    {'B','C'},
    {'C','D'},
    {'E','G'},
    {'F','G'}};
    int vlen=LENGTH(vexs);
    int elen=LENGTH(edges);
    int i,p1,p2;
    ENode *node1,*node2;
    LGraph* pG;

    if((pG=(LGraph*)malloc(sizeof(LGraph)))==NULL)
        return NULL;
    memset(pG,0,sizeof(LGraph));

    //初始化顶点数和边数
    pG->vexnum=vlen;
    pG->edgnum=elen;

    //初始化顶点
    for(i=0;i<pG->vexnum;i++){
        pG->vexs[i].data=vexs[i];
        pG->vexs[i].first_edge=NULL;
    }

    //初始化领接表的边
    for(i=0;i<pG->edgnum;i++){
        c1=edges[i][0];
        c2=edges[i][1];

        p1=get_position(*pG,c1);
        p2=get_position(*pG,c2);
        //printf("%d %d\n",p1,p2);
        //初始化节点1
        node1=(ENode*)malloc(sizeof(ENode));
        node1->ivex=p2;
        node1->next_edge=NULL;
        //将node1链接到节点的末尾
        if(pG->vexs[p1].first_edge==NULL)
            pG->vexs[p1].first_edge=node1;
        else
            link_last(pG->vexs[p1].first_edge,node1);


        //初始化节点2
        node2=(ENode*)malloc(sizeof(ENode));
        node2->ivex=p1;
        node2->next_edge=NULL;
        //将节点2链接到节点的末尾
        if(pG->vexs[p2].first_edge==NULL)
            pG->vexs[p2].first_edge=node2;
        else
            link_last(pG->vexs[p2].first_edge,node2);
    }
    return pG;
}


//深度优先搜索
void DFSTraverse(LGraph G){
    int i;
    int visited[MAX];

    //初始化所有顶点都没有被访问
    for(i=0;i<G.vexnum;i++){
        visited[i]=0;
    }
    printf("DFS访问结果:");
    for(i=0;i<G.vexnum;i++){
        if(visited[i]!=1)
            DFS(G,i,visited);
    }
    printf("\n");
}

//DFS递归搜索
void DFS(LGraph G,int i,int *visited){
         int w;
         ENode *node;

         visited[i]=1;
         printf("%c",G.vexs[i].data);
         node=G.vexs[i].first_edge;
         while(node!=NULL){
            if(!visited[node->ivex]){
                DFS(G,node->ivex,visited);
            }
            node=node->next_edge;
         }
}

//广度优先搜索
void BFS(LGraph G){
    int head=0;
    int rear=0;
    int queue[MAX];
    int visited[MAX];
    int i,j,k;
    ENode* node;

    for(i=0;i<G.vexnum;i++){
        visited[i]=0;
    }
    printf("BFS访问结果:");
    for(i=0;i<G.vexnum;i++){
        if(!visited[i]){
            visited[i]=1;
            printf("%c",G.vexs[i].data);
            queue[rear++]=i;
        }
        while(head!=rear){
            j=queue[head++];
            node=G.vexs[j].first_edge;
            while(node!=NULL){
                k=node->ivex;
                if(!visited[k]){
                    visited[k]=1;
                    printf("%c",G.vexs[k].data);
                    queue[rear++]=k;
                }
                node=node->next_edge;
            }
        }
    }
    printf("\n");
}

//打印邻接表图
void print_lgraph(LGraph G){
    int i,j;
    ENode* node;

    printf("领接表图:\n");
    for(i=0;i<G.vexnum;i++){
        printf("%d(%c):",i,G.vexs[i].data);
        node=G.vexs[i].first_edge;
        while(node!=NULL){
            printf("%d(%c)  ",node->ivex,G.vexs[node->ivex].data);
            node=node->next_edge;
        }
        printf("\n");
    }
}

int  main(){
    LGraph *pG;
    //自己创建图
    pG=creat_lgraph();
    //用已经有的图
    //pG=creat_example_lgraph();

    print_lgraph(*pG);
    DFSTraverse(*pG);
    BFS(*pG);
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值