图的应用(深度优先搜索和广度优先搜索)

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<conio.h>
#define MAXSIZE 100
int vis[MAXSIZE];///这个是访问数组
typedef struct arcnode
{
    int adjvex;///该弧所指向的顶点位置,邻接点域
    struct arcnode *nextarc;///指向下一条弧的指针域
}ArcNode;
typedef struct VNode
{
    int data;///顶点信息
    ArcNode *firstarc;///指向第一条依附该顶点的弧的指针
}AdjList[MAXSIZE];
typedef struct graph///这个结构图是图的整个信息,包括了它的顶点数和弧数,以及各个弧的信息
{
    AdjList vertices;
    int vexnum,arcnum;
}ALGraph;
typedef struct queue///循环队列的结构体
{
    int *base;///存数据的
    int front,rear;///队首和队尾
}Queue;
int LocateVex(ALGraph G,int v);///定位顶点的位置
void creat_graph(ALGraph *G);///创建图
void dfs(ALGraph G,int v);///深搜
void DFSTraverse(ALGraph G);///深度优先搜索
void Init_Queue(Queue *Q);///初始化队列
int empty_Queue(Queue Q);///判断队列是否为空
void push_Queue(Queue *Q,int e);///入队
void pop_Queue(Queue *Q,int *e);///出队
void BFSTraverse(ALGraph G);///广度优先搜索
void clear();///清屏
int main()
{
    ALGraph G;///定义一个图
    int choose;///菜单选择
    do{///页面设计
        printf("\t\t\t****************\n");
        printf("\t\t\t*1.图的创建    *\n");
        printf("\t\t\t*2.深度优先遍历*\n");
        printf("\t\t\t*3.广度优先遍历*\n");
        printf("\t\t\t*0.退出        *\n");
        printf("\t\t\t****************\n");
        printf("请输入你需要操作的菜单:");
        scanf("%d",&choose);
        if(choose==0)
        {
            printf("\t\t\t欢迎下次再使用!\n");
            break;
        }
        switch(choose)
        {
            case 1:creat_graph(&G);break;///创建图
            case 2:puts("深度优先遍历如下:");DFSTraverse(G);puts("");break;///深度优先搜索
            case 3:puts("广度优先遍历如下:");BFSTraverse(G);puts("");break;///广度优先搜索
            default:printf("输入错误,请重新输入\n");break;
        }
        clear();///清屏
    }while(1);
    return 0;
}
///定位顶点的位置
int LocateVex(ALGraph G,int v)
{
    int i;
    for(i=0;i<G.vexnum;i++)///遍历去查找
    {
        if(G.vertices[i].data==v)///找到该位置
            return i;///查找到就返回它的位置
    }
    return -1;///查找不到就返回-1
}


///创建图
void creat_graph(ALGraph *G)
{
    ArcNode *p,*t;///p的作用是创建弧的时候要申请的空间,而t是用来遍历的
    int i,j,k;
    int v1,v2;///头,尾
    printf("请输入顶点数和弧数:");
    scanf("%d%d",&G->vexnum,&G->arcnum);
    printf("请输入顶点:");
    for(i=0;i<G->vexnum;i++)
    {
        scanf("%d",&G->vertices[i].data);///先创建每个顶点,然后初始化他们的弧都是空的
        G->vertices[i].firstarc=NULL;
    }
    printf("请输入弧:\n");
    for(k=0;k<G->arcnum;k++)///输入弧的信息
    {
        scanf("%d%d",&v1,&v2);
        i=LocateVex(*G,v1);///这个是定位顶点的位置,因为我开的是数组形式存储,也就是要先找到顶点的位置
        j=LocateVex(*G,v2);///然后这个箭头所指的顶点,那么我这个也要找到这个的位置是在哪里,它同样也是一个顶点
        p=(ArcNode *)malloc(sizeof(ArcNode));///申请一个弧的空间
        p->nextarc=NULL;///让它的next先指向空的,
        p->adjvex=j;///然后把这个箭头所指向的顶点存在这个弧里面,接下来就是衔接了
        if(G->vertices[i].firstarc==NULL)///如果我们创建的顶点还没有任何指向,那么它的firstarc就直接指向这个头
            G->vertices[i].firstarc=p;
        else
        {
            t=G->vertices[i].firstarc;///如果它的firstarc已经有指向的顶点了,那么我们就需要去遍历到它的末尾,也就是还没有指向的位置,然后进行衔接过去
            while(t->nextarc)///如果它的nextarc是空的,那么也就是到这个顶点的末尾了,进行指向
                t=t->nextarc;
            t->nextarc=p;///进行指向,让它指向刚才申请的弧空间
        }
    }
    puts("操作成功!");
}


///深搜
void dfs(ALGraph G,int v)
{
ArcNode *p;///这个是暂时的弧结构体,用在接下来的遍历
printf("%d ",G.vertices[v].data);///输出顶点信息
vis[v]=1;///访问完这个顶点,就赋值1,代表它已经被访问过了
for(p=G.vertices[v].firstarc;p;p=p->nextarc)///遍历这个从这个顶点出发,去遍历它所有指向的顶点,并去搜索
if(!vis[p->adjvex])///这个前提还要是未访问的
dfs(G,p->adjvex);///这个顶点没被访问过就进行搜索
}




///深度优先搜索
void DFSTraverse(ALGraph G)
{
    int i;
    for(i=0;i<G.vexnum;i++)
        vis[i]=0;///先把访问数组都进行初始化为0
    for(i=0;i<G.vexnum;i++)///然后从第一个顶点开始搜索
        if(!vis[i])///没访问过的就可以进行搜索,如果访问过就不需要再进行搜索
            dfs(G,i);///进行搜索
}


///初始化队列
void Init_Queue(Queue *Q)
{
    Q->base=(int *)malloc(MAXSIZE*sizeof(int));///申请一个maxsize的数组空间
    Q->front=Q->rear=0;///循环队列一开始都是指向初始位置0,队首和队尾指在同一位置
}


///队列是否为空的
int empty_Queue(Queue Q)
{
    if(Q.rear==Q.front)///如果队首和队尾指在同一位置就说明是空的
        return 1;///返回1,说明队列是空的
    return 0;///否则就是0,说明不是空的
}




///入队
void push_Queue(Queue *Q,int e)
{
    if((Q->rear+1)%MAXSIZE==Q->front)///每次入队之后,rear都会先指向下一个,所以先判断rear+1是不是到了front的位置,是的话说明队列满了
        return ;///满了就说明无法进行入队了
    Q->base[Q->rear]=e;///空间足够就入队
    Q->rear=(Q->rear+1)%MAXSIZE;///入队之后,rear要指向下一个,模它的最大空间,因为是循环队列
}


///出队
void pop_Queue(Queue *Q,int *e)
{
    if(Q->rear==Q->front)///在出队之前先判断front和rear都指向同一个位置,如果是就跟初始化一样,也就是队列是空的
        return ;
    *e=Q->base[Q->front];///把出队的值赋值给e,e返回的时候进行输出
    Q->front=(Q->front+1)%MAXSIZE;///出队之后要指向下一个,因为循环队列,要取模MAXSIZE
}


///广度优先搜索
void BFSTraverse(ALGraph G)
{
int u,v;
Queue Q;///定义一个循环队列
ArcNode *p;
for(v=0;v<G.vexnum;v++)
vis[v]=0;///在广度搜索之前先把访问数组进行初始化为0
Init_Queue(&Q);///初始化队列
for(v=0;v<G.vexnum;v++)///遍历每个顶点,这样就不会漏掉,而且都是优先序号小的先访问
if(!vis[v])///该顶点没有被访问就进行操作
        {
printf("%d ",G.vertices[v].data);///并输出该顶点
vis[v]=1;///访问了该顶点之后就把这个顶点的访问数组赋值为1
push_Queue(&Q,v);///然后就让这个顶点入队,因为我们不是进行深搜,是把该层的顶点都进行输出之后再访问下一层的
while(!empty_Queue(Q))///如果不是空的话就进下这一层的其他的顶点的输出
{
pop_Queue(&Q,&u);///u就是刚才那个顶点,然后这样就可以找到这个顶点的层里还有其他的顶点,没有就进行下一层
for(p=G.vertices[u].firstarc;p;p=p->nextarc)///这个就是把这个下一层的顶点都进行输出,并入队,不会直接进入下一层
if(!vis[p->adjvex])///没被访问过就进行输出,并入队
{
printf("%d ",G.vertices[p->adjvex].data);
vis[p->adjvex]=1;///访问了该顶点之后就把这个顶点的访问数组赋值为1
push_Queue(&Q,p->adjvex);///入队
}
}
}
}


///清屏
void clear()
{
    printf("请按任意键继续......");
    getch();
    system("cls");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值