图的遍历


一、图的邻接表法            http://blog.csdn.net/akof1314/article/details/4388722
     图的邻接表表示法类似于树的孩子链表表示法。对于图G中的每个顶点v i  ,该方法把所有邻接于v i  的顶点v j  链成一个带头结点的单链表,这个单链表就称为顶点v i  的邻接表(Adjacency List)。


顶点表通常以顺序结构的方式存储


以下代码测试过,为图的邻接表表示方式。

[cpp]  view plain copy
  1. /************************************************************************/  
  2. /* 图的邻接表存储结构                                                    */  
  3. /************************************************************************/  
  4. #include <stdio.h>  
  5. #define MaxVertexNum 100  
  6. #define QueueSize 30   
  7. typedef enum{FALSE,TRUE}Boolean;     
  8. Boolean visited[MaxVertexNum];    
  9. typedef char VertexType;  
  10. typedef int EdgeType;  
  11. typedef struct node     //边表结点  
  12. {  
  13.     int adjvex;         //邻接点域  
  14.     struct node *next;  //域链  
  15.     //若是要表示边上的权,则应增加一个数据域  
  16. }EdgeNode;  
  17. typedef struct vnode    //顶点边结点  
  18. {  
  19.     VertexType vertex;  //顶点域  
  20.     EdgeNode *firstedge;//边表头指针  
  21. }VertexNode;  
  22. typedef VertexNode AdjList[MaxVertexNum];   //AdjList是邻接表类型  
  23. typedef struct   
  24. {  
  25.     AdjList adjlist;    //邻接表  
  26.     int n,e;            //图中当前顶点数和边数  
  27. }ALGraph;               //对于简单的应用,无须定义此类型,可直接使用AdjList类型  
  28. /************************************************************************/  
  29. /* 建立无向图的邻接表算法                                               */  
  30. /************************************************************************/  
  31. void CreateGraphAL (ALGraph *G)     
  32. {     
  33.     int i,j,k;     
  34.     EdgeNode * s;     
  35.     printf("请输入顶点数和边数(输入格式为:顶点数,边数):/n");     
  36.     scanf("%d,%d",&(G->n),&(G->e));       // 读入顶点数和边数     
  37.     printf("请输入顶点信息(输入格式为:顶点号<CR>)每个顶点以回车作为结束:/n");     
  38.     for (i=0;i<G->n;i++)              // 立有n个顶点的顶点表     
  39.     {      
  40.         scanf("/n%c",&(G->adjlist[i].vertex)); // 读入顶点信息     
  41.         G->adjlist[i].firstedge=NULL;            // 点的边表头指针设为空     
  42.     }     
  43.     printf("请输入边的信息(输入格式为:i,j):/n");     
  44.     for (k=0;k<G->e;k++)      // 建立边表     
  45.     {      
  46.         scanf("/n%d,%d",&i,&j); // 读入边<Vi,Vj>的顶点对应序号     
  47.         s=new EdgeNode;         // 生成新边表结点s     
  48.         s->adjvex=j;         // 邻接点序号为j     
  49.         s->next=G->adjlist[i].firstedge; // 将新边表结点s插入到顶点Vi的边表头部     
  50.         G->adjlist[i].firstedge=s;     
  51.         s=new EdgeNode;  
  52.         s->adjvex=i;  
  53.         s->next=G->adjlist[j].firstedge;  
  54.         G->adjlist[j].firstedge=s;  
  55.     }     
  56. }    
  57. /************************************************************************/  
  58. /* 深度优先遍历                                                         */  
  59. /************************************************************************/   
  60. void DFS(ALGraph *G,int i)  
  61. {   
  62.     //以vi为出发点对邻接表表示的图G进行深度优先搜索  
  63.     EdgeNode *p;  
  64.     printf("visit vertex:%c/n",G->adjlist[i].vertex);  // 访问顶点vi  
  65.     visited[i]=TRUE;                //标记vi已访问  
  66.     p=G->adjlist[i].firstedge;       //取vi边表的头指针  
  67.     while(p)  
  68.     {                               //依次搜索vi的邻接点vj,这里j=p->adjvex  
  69.         if (!visited[p->adjvex]) //若vi尚未被访问  
  70.             DFS(G,p->adjvex);        //则以Vj为出发点向纵深搜索  
  71.         p=p->next;                    //找vi的下一邻接点  
  72.     }  
  73. }  
  74. void DFSTraverseM(ALGraph *G)     
  75. {     
  76.     int i;     
  77.     for(i=0;i<G->n;i++)     
  78.         visited[i]=FALSE;        
  79.     for(i=0;i<G->n;i++)     
  80.         if(!visited[i])      
  81.             DFS(G,i);     
  82. }   
  83. /************************************************************************/  
  84. /* 广度优先遍历                                                         */  
  85. /************************************************************************/  
  86. typedef struct    
  87. {     
  88.     int front;     
  89.     int rear;     
  90.     int count;     
  91.     int data[QueueSize];     
  92. }CirQueue;     
  93. void InitQueue(CirQueue *Q)     
  94. {     
  95.     Q->front=Q->rear=0;     
  96.     Q->count=0;     
  97. }     
  98. int QueueEmpty(CirQueue *Q)     
  99. {     
  100.     return Q->count=QueueSize;     
  101. }     
  102. int QueueFull(CirQueue *Q)     
  103. {     
  104.     return Q->count==QueueSize;     
  105. }     
  106. void EnQueue(CirQueue *Q,int x)     
  107. {      
  108.     if (QueueFull(Q))     
  109.         printf("Queue overflow");     
  110.     else    
  111.     {      
  112.         Q->count++;     
  113.         Q->data[Q->rear]=x;     
  114.         Q->rear=(Q->rear+1)%QueueSize;     
  115.     }     
  116. }     
  117. int DeQueue(CirQueue *Q)     
  118. {     
  119.     int temp;     
  120.     if(QueueEmpty(Q))     
  121.     {      
  122.         printf("Queue underflow");     
  123.         return NULL;     
  124.     }     
  125.     else    
  126.     {     
  127.         temp=Q->data[Q->front];     
  128.         Q->count--;     
  129.         Q->front=(Q->front+1)%QueueSize;     
  130.         return temp;     
  131.     }     
  132. }     
  133. void BFS(ALGraph*G,int k)  
  134. {   // 以vk为源点对用邻接表表示的图G进行广度优先搜索  
  135.     int i;  
  136.     CirQueue Q;             //须将队列定义中DataType改为int  
  137.     EdgeNode *p;  
  138.     InitQueue(&Q);          //队列初始化  
  139.     printf("visit vertex:%c/n",G->adjlist[k].vertex);        //访问源点vk  
  140.         visited[k]=TRUE;   
  141.     EnQueue(&Q,k);          //vk已访问,将其人队。(实际上是将其序号人队)  
  142.     while(!QueueEmpty(&Q))  
  143.     {                                   //队非空则执行  
  144.         i=DeQueue(&Q);                  //相当于vi出队  
  145.         p=G->adjlist[i].firstedge;       //取vi的边表头指针  
  146.         while(p)  
  147.         {                               //依次搜索vi的邻接点vj(令p->adjvex=j)  
  148.             if(!visited[p->adjvex])  
  149.             {                           //若vj未访问过  
  150.                 printf("visit vertex:%c",G->adjlist[p->adjvex].vertex);       //访问vj  
  151.                 visited[p->adjvex]=TRUE;   
  152.                 EnQueue(&Q,p->adjvex);   //访问过的vj人队  
  153.             }  
  154.             p=p->next;                   //找vi的下一邻接点  
  155.         }  
  156.     }  
  157. }  
  158. void BFSTraverseM(ALGraph *G)     
  159. {     
  160.     int i;     
  161.     for (i=0;i<G->n;i++)     
  162.         visited[i]=FALSE;     
  163.     for (i=0;i<G->n;i++)     
  164.         if (!visited[i])      
  165.             BFS(G,i);     
  166. }     
  167. /************************************************************************/  
  168. /* 主函数调用                                                           */  
  169. /************************************************************************/  
  170. int main()  
  171. {  
  172.     ALGraph G;  
  173.     CreateGraphAL(&G);  
  174.     printf("深度优先遍历:/n");  
  175.     DFSTraverseM(&G);  
  176.     printf("广度优先遍历:/n");  
  177.     BFSTraverseM(&G);  
  178.     return 0;  
  179. }  

测试结果如下:

 

如果测试有误,若是代码有错,请指出,共同学习,呵呵。


二、图的邻接矩阵法         http://www.cnblogs.com/dolphin0520/archive/2011/07/13/2105236.html

         图的遍历有两种遍历方式:深度优先遍历(depth-first search)和广度优先遍历(breadth-first search)。

1.深度优先遍历

   基本思想:首先从图中某个顶点v0出发,访问此顶点,然后依次从v0相邻的顶点出发深度优先遍历,直至图中所有与v0路径相通的顶点都被访问了;若此时尚有顶点未被访问,则从中选一个顶点作为起始点,重复上述过程,直到所有的顶点都被访问。可以看出深度优先遍历是一个递归的过程。

   如下图中的一个无向图

   

  其深度优先遍历得到的序列为:

  0->1->3->7->4->2->5->6

2.广度优先遍历

   基本思想:首先,从图的某个顶点v0出发,访问了v0之后,依次访问与v0相邻的未被访问的顶点,然后分别从这些顶点出发,广度优先遍历,直至所有的顶点都被访问完。

   如上面图中

   其广度优先遍历得到的序列为:

   0->1->2->3->4->5->6->7

实现代码

复制代码
#include<iostream>
#include<queue>
#include<stack>
#include<stdlib.h>
#define MAX 100
using namespace std;

typedef struct 
{
    int edges[MAX][MAX];    //邻接矩阵
    int n;                  //顶点数
    int e;                  //边数
}MGraph;

bool visited[MAX];          //标记顶点是否被访问过

void creatMGraph(MGraph &G)    //用引用作参数
{
    int i,j;
    int s,t;                 //存储顶点编号
    int v;                   //存储边的权值
    for(i=0;i<G.n;i++)       //初始化
    {
        for(j=0;j<G.n;j++)
        {
            G.edges[i][j]=0;
        }
        visited[i]=false;
    }
    for(i=0;i<G.e;i++)      //对矩阵相邻的边赋权值
    {
        scanf("%d %d %d",&s,&t,&v);   //输入边的顶点编号以及权值
        G.edges[s][t]=v;
    }
}

void DFS(MGraph G,int v)      //深度优先搜索
{
    int i;
    printf("%d ",v);          //访问结点v
    visited[v]=true;
    for(i=0;i<G.n;i++)       //访问与v相邻的未被访问过的结点
    {
        if(G.edges[v][i]!=0&&visited[i]==false)
        {
            DFS(G,i);
        }
    }
}

void DFS1(MGraph G,int v)   //非递归实现
{
    stack<int> s;
    printf("%d ",v);        //访问初始结点
    visited[v]=true;
    s.push(v);              //入栈
    while(!s.empty())
    {
        int i,j;
        i=s.top();          //取栈顶顶点
        for(j=0;j<G.n;j++)  //访问与顶点i相邻的顶点
        {
            if(G.edges[i][j]!=0&&visited[j]==false)
            {
                printf("%d ",j);     //访问
                visited[j]=true;
                s.push(j);           //访问完后入栈
                break;               //找到一个相邻未访问的顶点,访问之后则跳出循环
            }
        }
        if(j==G.n)                   //如果与i相邻的顶点都被访问过,则将顶点i出栈
            s.pop();
    }
}

void BFS(MGraph G,int v)      //广度优先搜索
{
    queue<int> Q;             //STL模板中的queue
    printf("%d ",v);
    visited[v]=true;
    Q.push(v);
    while(!Q.empty()) 
    {
        int i,j;
        i=Q.front();         //取队首顶点
        Q.pop();
        for(j=0;j<G.n;j++)   //广度遍历
        {
            if(G.edges[i][j]!=0&&visited[j]==false)
            {
                printf("%d ",j);
                visited[j]=true;
                Q.push(j);
            }
        }
    }
}

int main(void)
{
    int n,e;    //建立的图的顶点数和边数
    while(scanf("%d %d",&n,&e)==2&&n>0)
    {
        MGraph G;
        G.n=n;
        G.e=e;
        creatMGraph(G);
        DFS(G,0);
        printf("\n");
    //    DFS1(G,0);
    //    printf("\n");
    //    BFS(G,0);
    //    printf("\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值