数据结构——图—图的遍历

来源:互联网 发布:bioedit软件下载 编辑:程序博客网 时间:2024/06/05 02:03

首先传送门(图的概念和图的储存)http://blog.csdn.net/qq_33329316/article/details/53560874

图的遍历


前面了解了图的基本概念和图的储存那么得了解一下怎么来遍历一个图了


图的两种遍历方式

1.深度优先遍历

2.广度优先遍历


深度优先遍历

这里写图片描述
先看看这两个图,那么下面就来具体介绍一下图的深度优先遍历吧
1.说通俗一点我感觉深度优先遍历就是 ——一条路走到死;
脑子里面想着这句话来开始想深度优先遍历吧,首先我们选取A为初始点给走过的顶点做上记号,A下面有两个点 B,F。那我们该怎么选呢?
2.一条路走到死对就是这样,我们就选左边的这个B 然后B下面又有了3个节点继续选最左边的走,后面的一直选最右边的走 最后我们会发现 我们走了A -B-C-D-G-F-A回到A了?
3.回到A了怎么办,还有许多没有走呢?而且A上面我们已经标记A走过了,那么我们就退回F。记住要是走过了我们就退回。
4.既然退回了就走F(如果F下面的顶点都走了就继续退回退带G依次类推)中哪个没有走的顶点,走E然后在坚持一条路走到死的原理+走过就退回原理,我们走着走着回发现突然退回到A了那么恭喜这个图我们遍历结束了。
总之就是坚持一条路走到死原理+走过退回原理‘
如果看了上面的我们还不太的了解就对照的图慢慢了解吧。


代码实现


邻接矩阵的遍历(深度)


/*
函数大概解释
首先这个walks[]数组是我们定义的一个主函数用来表示某个顶点是否已经遍历过了数组的序号代表第几个顶点 0和1代表未遍历或者已经遍历;
1.第一个函数,我们首先初始化数组并且让数组的个数等于顶点的个数;然后开始从第一个顶点遍历;
如果他对应的walks[]数组walks[i] =0 表示他没有被遍历过所以我们就对这个未访问过的顶点调用DFS函数
2.DFS函数;他采取了一个很简单的递归操作,首先输入传入的顶点的值,然后把它标记为已经遍历
3.然后开始遍历和这个顶点有关系的所有顶点,想想邻接矩阵是不是有关系的连个顶点他的权值都不是无穷大,然后判断如果他的权值不是无穷大而且他所对应的顶点没有walk[j]是否等于0.如果满足就是没有遍历过的有效点
4.当他满足这连个条件,那就递归运算这个顶点在输出这个顶点。然后继续这样走,有没有感觉和上面的一条路走到死有惊人的相似呢?

*/

void DFSTraverse(M_g *x){    int i;    for(i = 0; i < x->N_v;i++)    {       walks[i] = 0;//设置顶点都没有走过    }    for(i = 0;i < x->N_v;i++)    {        if(walks[i] == 0)//对未访问过的节点给他调用DFS        {            DFS(x,i);        }    }}void  DFS (M_g *x,int i){     int j;     walks[i] = 1;     printf("%5d",x->vexs[i]);//打印节点信息,     for( j = 0; j < x->N_v; j++)     {         if(x->arc[i][j] ==!9999 && !walks[i])//判断如果他的权值不是无穷大而且他所对应的顶点没有walk[j]是否等于0            DFS(x,j);                  }}

邻接矩阵的实现和遍历全部函数


#include<stdio.h>#include<stdlib.h>#define MAXSIZE 100#define M 20int walks[M];#define FALL 99999//用99999来代表无穷大typedef struct{    char vexs[MAXSIZE];//顶点表    int arc[MAXSIZE][MAXSIZE];//领接矩阵可以看成边表    int N_v,N_e ;  //定义顶点数字和边数}M_g;//实现void onCreateM_g(M_g *x){    int i,j,k,w;    printf("请输入顶点数和边数\n");    scanf("%d%d",&x->N_v,&x->N_e);    printf("请依次各输入顶点\n");    for(i=0;i < x->N_v;i++)    {        scanf("%d",&x->vexs[i]);//        puts("sdsdsds");    }//    for(i = 0;i < x->N_v;i++){       for(j = 0;j < x->N_v;j++)        {          x->arc[i][j] = FALL;        }    }    for( k = 0; k < x->N_e;k++)          {              printf("请输入(vi,vj)的上标i,下标j 和权 w \n");              scanf("%d%d%d",&i,&j,&w);              x->arc[i][j] = w;              x->arc[j][i] = x->arc[i][j];          }}void  DFS (M_g *x,int i){     int j;     walks[i] = 1;     printf("%5d",x->vexs[i]);//打印节点信息,     for( j = 0; j < x->N_v; j++)     {         if(x->arc[i][j] ==!9999 && !walks[i])            DFS(x,j);                  }}void DFSTraverse(M_g *x){    int i;    for(i = 0; i < x->N_v;i++)    {       walks[i] = 0;    }    for(i = 0;i < x->N_v;i++)    {        if(walks[i] == 0)        {            DFS(x,i);        }    }}int main(){    M_g *p;    p = (M_g*)malloc(sizeof(M_g));    onCreateM_g(p);    DFSTraverse (p);return 0;}/*4 40 1 2 30 1 560 2 340 3 782 3 25*/

邻接表的遍历(深度)


/*领接表的遍历和邻接矩阵的遍历大同小异;基本的大差别就是在DFS函数中的判断有了变化1. while(p)判断他是否为空要是空了就跳出2. if(walks[q -> adjvex] == 0)            {                DFS(p,q->adjvex);            }            q = q->next; 和链表相似里面那句不用我解释了吧q->adjvex就是邻接表中边表的顶点,顶点的数字是一样的怎么都可以.walks[]数组中的数组序号同样表示各个顶点因为初始化他的时候让他的数量和邻接表中顶点数一样 1.如果walks[i] == 0 说明他没有被遍历那就继续走他这条路上的 用它递归操作调用DFS函数 想想那句坚持一条路走到死的原理+走过就退回原理。仔细体会一下 2.如果walks[i] != 0  那么说明这个顶点已经遍历的我们就不用管它了让他指向下一个继续查看果walks[i] 值是多少直到查找到空为止;    void  DFS(LinkdeGraph *p,int i)    {         EdgeNode *q;        walks[i] = 1;        printf("%5",p->adjlist[i].data);        q = p->adjlist[i].first_v;        while(p)        {            if(walks[q -> adjvex] == 0)            {                DFS(p,q->adjvex);            }            q = q->next;        }    }    void DFSTraverse(LinkdeGraph *p)    {        int i;        for(i = 0;i < p->n_v;i++ )        {            walks[i] = 0;        }        for(i = 0;i < p->n_v;i++)            if(walks[i] == 0)            {                DFS(p,i);            }    }

邻接表的实现和遍历全部函数


#include<stdio.h>#include<stdlib.h>#define M 20int walks[M];typedef int VertexType;/*顶点类型有用户定义*/typedef struct EdgeNode//定义边表{    int adjvex;//邻接点域 里面放各个和顶点表对应节点有关的顶点    int weight;//权值    struct EdgeNode *next;}EdgeNode;typedef struct VertexNode /*定义顶点表*/{    VertexType data;//顶点域,存储顶点信息     EdgeNode *first_v;//边表的头指针}VertexNode;typedef struct   //邻接表{   VertexNode adjlist[M]; //用于存放头结点和顶点的顺序表;   int n_v,n_e;}LinkdeGraph;//创建邻接表void onCreate_L(LinkdeGraph *p,int c)//等于0表示建立为无向图{    int i,j,k;    EdgeNode *e;    printf("请输入顶点数和边数:\n");    scanf("%d%d",&p->n_v,&p->n_e);    printf("请依次输入顶点\n");    for(i = 0; i < p->n_v; i++ )//输入顶点信息,建立顶点表    {        scanf("%d",&p->adjlist[i].data);//输入顶点信息        p->adjlist[i].first_v = NULL;   //初始状态默认边表为空    }    for(k = 0 ; k < p->n_e;k++)//建立边表    {        printf("请输入边(vi,vj)上的顶点序号:\n");        scanf("%d%d",&i,&j);//输入边vivj上的顶点序号        e = (EdgeNode*)malloc(sizeof(EdgeNode));//开辟边表的空间        /*                头插法        */        e->adjvex = j; //顶点为j        e->next = p->adjlist[i].first_v;//将边表e作为头指针放进顶点表的first域        p->adjlist[i].first_v = e;        if(c == 0)            {                 e = (EdgeNode*)malloc(sizeof(EdgeNode));                 e ->adjvex = i;                 e->next = p->adjlist[j].first_v;                 p->adjlist[j].first_v = e;            }    }}    void  DFS(LinkdeGraph *p,int i)    {        EdgeNode *q;        walks[i] = 1;        printf("%5",p->adjlist[i].data);        q = p->adjlist[i].first_v;        while(p)        {            if(walks[q -> adjvex] == 0)            {                DFS(p,q->adjvex);            }            q = q->next;        }    }    void DFSTraverse(LinkdeGraph *p)    {        int i;        for(i = 0;i < p->n_v;i++ )        {            walks[i] = 0;        }        for(i = 0;i < p->n_v;i++)            if(walks[i] == 0)            {                DFS(p,i);            }    }int main(){    int c = 0;    LinkdeGraph *p;    p = (LinkdeGraph*)malloc(sizeof(LinkdeGraph));    onCreate_L(p,c);return 0;}

广度优选遍历

1 0
原创粉丝点击