zoukankan      html  css  js  c++  java
  • 图的深度优先和广度优先搜索算法

      本文取自《数据结构与算法》(C语言版)(第三版),出版社是清华大学出版社。

      1.图的深度优先搜索算法:

           图的深度优先搜索算法的基本思想是:从图G的某个顶点V0出发,访问V0,然后选择一个与V0相邻且未被访问过的顶点Vi访问,再从Vi出发选择一个与Vi相邻且未被访问的顶点Vj进行访问,依此下去,直到当前被访问过的顶点的所有邻接顶点都已被访问,则按相反顺序退回到已访问的顶点序列中,如果其中的顶点还存在未被访问的相邻顶点W,则从W出发,按相同的方法继续访问。直到图中的所有顶点均被访问。

           无向图的深度优先搜索过程示意图:

           

          其程序如下:

      1   #include<stdio.h>
      2   #include<stdlib.h>
      3   #include<string.h>
      4   #define MaxVertexNum 100
      5   int visited[MaxVertexNum];
      6 
      7   typedef struct node
      8   {
      9     int adjvex;
     10     struct node *nextrarc;
     11     int info;
     12   }EdgeNode;
     13 
     14   typedef struct vnode
     15   {
     16     char vexdate;
     17     EdgeNode *firstarc;
     18   }VertexNode;
     19 
     20   typedef VertexNode AdjList[MaxVertexNum];
     21 
     22   typedef struct
     23   {
     24     AdjList adjlist;
     25     int n,e;
     26   }ALGraph;
     27 
     28   int initGraph(ALGraph* aGraph);
     29   int mFind(char aChar, ALGraph* aGraph);
     30   int createHead(char aChar, ALGraph* aGraph);
     31   void addBody(char aChar, int aPos, ALGraph* aGraph);
     32   void showGraph(ALGraph* aGraph);
     33   void DFSTraverse(ALGraph* aGraph);
     34   void DFS(ALGraph* aGraph, int v);
     35 
     36   int main(void)
     37   {
     38     char a;
     39     char sep1;
     40     char sep2;
     41     int isBody=0;
     42     int isFinish=0;
     43     int headPos=-1;
     44     ALGraph g_graph;
     45     initGraph(&g_graph);
     46 
     47     printf("Input arcs like this ' a-> b c d',end with $
    ");
     48     while(isFinish==0)
     49     {
     50       isBody=0;
     51       while(1)
     52       {
     53         //a=getChar();
     54         scanf("%c",&a);
     55         if(a=='-'||a=='
    '||a==' '||a=='>')
     56         {
     57           if(a=='>')
     58             isBody=1;
     59           continue;
     60         }
     61         if(a=='$'||a=='#')
     62         {
     63           if(a=='#')
     64             isFinish=1;
     65           break;
     66         }
     67 
     68         if(a=='>')
     69         {
     70           isBody=1;
     71           continue;
     72         }
     73         if(isBody==1)
     74         {
     75           addBody(a,headPos,&g_graph);
     76         }
     77         else
     78         {
     79           if((headPos=mFind(a,&g_graph))==-1)
     80             headPos=createHead(a,&g_graph);
     81         }
     82       }
     83     }
     84     showGraph(&g_graph);
     85     printf("The DFS is:
    ");
     86     DFSTraverse(&g_graph);
     87     return 0;
     88   }
     89 
     90   void DFSTraverse(ALGraph* aGraph)
     91   {
     92     int i=0;
     93     for(i=0; i<aGraph->n; i++)
     94     {
     95       visited[i]=0;
     96     }
     97     for(i=0; i<aGraph->n; i++)
     98     {
     99       if(!visited[i])
    100         DFS(aGraph,i);
    101     }
    102   }
    103 
    104   void DFS(ALGraph* aGraph, int v)
    105   {
    106     EdgeNode* w;
    107     visited[v]=1;
    108     printf(" %c", aGraph->adjlist[v].vexdate);
    109     w=aGraph->adjlist[v].firstarc;
    110     for(w=aGraph->adjlist[v].firstarc; w; w=w->nextrarc)
    111     {
    112       if(!visited[w->adjvex])
    113         DFS(aGraph, w->adjvex);
    114     }
    115   }
    116 
    117   void showGraph(ALGraph* aGraph)
    118   {
    119     int i=0;
    120     for(i=0; i<aGraph->n; i++)
    121     {
    122       EdgeNode* pos;
    123       printf("%c->", aGraph->adjlist[i]);
    124       pos=aGraph->adjlist[i].firstarc;
    125       while(pos!=NULL)
    126       {
    127         printf("%d",pos->adjvex);
    128         pos=pos->nextrarc;
    129       }
    130       printf("
    ");
    131     }
    132   }
    133 
    134   void addBody(char aChar, int aPos, ALGraph* aGraph)
    135   {
    136     int inversePos;
    137     EdgeNode* node=(EdgeNode*) malloc(sizeof(EdgeNode));
    138     if((node->adjvex=mFind(aChar,aGraph))==-1)
    139       node->adjvex=createHead(aChar,aGraph);
    140     node->info=-1;
    141     node->nextrarc=NULL;
    142     if(aGraph->adjlist[aPos].firstarc==NULL)
    143     {
    144       aGraph->adjlist[aPos].firstarc=node;
    145     }
    146     else
    147     {
    148       EdgeNode* tail=aGraph->adjlist[aPos].firstarc;
    149       while(tail->nextrarc!=NULL)
    150         tail=tail->nextrarc;
    151       tail->nextrarc=node;
    152     }
    153     inversePos=node->adjvex;
    154     node=(EdgeNode*)malloc(sizeof(EdgeNode));
    155     node->adjvex=aPos;
    156     node->info=-1;
    157     node->nextrarc=NULL;
    158     if(aGraph->adjlist[inversePos].firstarc==NULL)
    159     {
    160       aGraph->adjlist[inversePos].firstarc=node;
    161     }
    162     else
    163     {
    164       EdgeNode* tail=aGraph->adjlist[inversePos].firstarc;
    165       while(tail->nextrarc!=NULL)
    166         tail=tail->nextrarc;
    167       tail->nextrarc=node;
    168     }
    169   }
    170 
    171   int createHead(char aChar, ALGraph* aGraph)
    172   {
    173     int currPos=aGraph->n;
    174     aGraph->adjlist[currPos].vexdate=aChar;
    175     aGraph->n++;
    176     return currPos;
    177   }
    178 
    179   int mFind(char aChar, ALGraph* aGraph)
    180   {
    181     int i=0;
    182     for(i=0; i<aGraph->n; i++)
    183     {
    184       if(aChar==aGraph->adjlist[i].vexdate)
    185         return i;
    186     }
    187     return -1;
    188   }
    189 
    190   int initGraph(ALGraph* aGraph)
    191   {
    192     int i=0;
    193     aGraph->e=0;
    194     aGraph->n=0;
    195     for(i=0; i<MaxVertexNum; i++)
    196     {
    197       aGraph->adjlist[i].firstarc=NULL;
    198     }
    199     return 0;
    200   }
    View Code

    在VC2010 C++控制台程序下的运行结果如下截图:

       

     2.图的广度优先遍历算法:

           图的广度优先遍历算法的基本思想是:从图G的某个顶点V0出发,访问V0,然后访问V0的所有未被访问过的邻接顶点V01,V02,...,V0i,接着再按照V01,V02,...,V0i的顺序访问每一个顶点的所有未被访问过的邻接顶点。依此下去,直到图中的所有顶点均被访问过。
          无向图的广度优先搜索示意图:
                          
          其程序如下:
      1   #include<stdio.h>
      2   #include<stdlib.h>
      3   #include<string.h>
      4   #define MaxVertexNum 100
      5 
      6   //队列的声明
      7   typedef struct Qnode
      8   {
      9     int data;
     10     struct Qnode* next;
     11     struct Qnode* prev;
     12   }Qnode;
     13 
     14   typedef struct queue
     15   {
     16     Qnode* first;
     17     Qnode* tail;
     18   }Queue;
     19 
     20   int isQueueEmpty(Queue* pQue)
     21   {
     22     if(pQue->first==pQue->tail)
     23       return 1;
     24     else
     25       return 0;
     26   }
     27 
     28   Queue* queueInit(Queue* pQue)
     29   {
     30     pQue->first=(Qnode*)malloc(sizeof(Queue));
     31     pQue->first->data=-1;
     32     pQue->tail=pQue->first;
     33     return pQue;
     34   }
     35 
     36   Qnode* queuePull(Queue* pQue)
     37   {
     38     pQue->tail=pQue->tail->prev;
     39     return pQue->tail->next;
     40   }
     41 
     42   void queuePush(Queue* pQue, Qnode* pNode)
     43   {
     44     pNode->next=pQue->first;
     45     pQue->first->prev=pNode;
     46     pQue->first=pNode;
     47   }
     48 
     49   Queue* queueEmpty(Queue* pQue)
     50   {
     51     while(pQue->first!=pQue->tail)
     52     {
     53       Qnode* pCurr=pQue->first;
     54       pQue->first=pQue->first->next;
     55       free(pQue->first);
     56     }
     57     return pQue;
     58   }
     59 
     60   int visited[MaxVertexNum];
     61 
     62   //图的声明
     63   typedef struct node
     64   {
     65     int adjvex;
     66     struct node *nextrarc;
     67     int info;
     68   }EdgeNode;
     69 
     70   typedef struct vnode
     71   {
     72     char vexdate;
     73     EdgeNode *firstarc;
     74   }VertexNode;
     75 
     76   typedef VertexNode AdjList[MaxVertexNum];
     77 
     78   typedef struct
     79   {
     80     AdjList adjlist;
     81     int n,e;
     82   }ALGraph;
     83 
     84   int initGraph(ALGraph* aGraph);
     85   int mFind(char aChar, ALGraph* aGraph);
     86   int createHead(char aChar, ALGraph* aGraph);
     87   void addBody(char aChar, int aPos, ALGraph* aGraph);
     88   void showGraph(ALGraph* aGraph);
     89   void BFSTraverse(ALGraph* aGraph);
     90   void BFS(ALGraph* aGraph, int i, Queue* pQue, int* visited);
     91 
     92   int main(void)
     93   {
     94     char a;
     95     //char sep1;
     96     //char sep2;
     97     int isBody=0;
     98     int isFinish=0;
     99     int headPos=-1;
    100     ALGraph g_graph;
    101     initGraph(&g_graph);
    102 
    103     printf("Input arcs like this 'a->b c d',end with $
    ");
    104     while(isFinish==0)
    105     {
    106       isBody=0;
    107       while(1)
    108       {
    109         a=getchar();
    110         //scanf("%c",&a);
    111         if(a=='-'||a=='
    '||a==' '||a=='>')
    112         {
    113           if(a=='>')
    114             isBody=1;
    115           continue;
    116         }
    117         if(a=='$'||a=='#')
    118         {
    119           if(a=='#')
    120             isFinish=1;
    121           break;
    122         }
    123 
    124         if(a=='>')
    125         {
    126           isBody=1;
    127           continue;
    128         }
    129         if(isBody==1)
    130         {
    131           addBody(a,headPos,&g_graph);
    132         }
    133         else
    134         {
    135           if((headPos=mFind(a,&g_graph))==-1)
    136             headPos=createHead(a,&g_graph);
    137         }
    138       }
    139     }
    140     showGraph(&g_graph);
    141     printf("The BFS is:
    ");
    142     BFSTraverse(&g_graph);
    143     return 0;
    144   }
    145 
    146   void BFS(ALGraph* aGraph, int i, Queue* pQue, int* visited)
    147   {
    148     Qnode* temNode=(Qnode*)malloc(sizeof(Qnode));
    149     temNode->data=i;
    150     queuePush(pQue,temNode);
    151     while(isQueueEmpty(pQue)==0)
    152     {
    153       Qnode* currNode=queuePull(pQue);
    154       if(visited[currNode->data]==0)
    155       {
    156         EdgeNode* temarc;
    157         printf("%c",aGraph->adjlist[currNode->data].vexdate);
    158         visited[currNode->data]=1;
    159         temarc=aGraph->adjlist[currNode->data].firstarc;
    160         while(temarc!=NULL)
    161         {
    162           Qnode* insertNode=(Qnode*)malloc(sizeof(Qnode));
    163           insertNode->data=temarc->adjvex;   //此处指针未初始化,导致错误
    164           if(visited[insertNode->data]==0)
    165             queuePush(pQue,insertNode);
    166           temarc=temarc->nextrarc;
    167         }
    168       }
    169     }
    170   }
    171 
    172   void BFSTraverse(ALGraph* aGraph)
    173   {
    174     Queue gQueue;
    175     int i=0;
    176     for(i=0; i<aGraph->n; i++)
    177     {
    178       visited[i]=0;
    179     }
    180     queueInit(&gQueue);
    181     for(i=0; i<aGraph->n; i++)
    182     {
    183       if(visited[i]==0)
    184         BFS(aGraph, i, &gQueue, visited);
    185     }
    186     printf("
    ");
    187   }
    188 
    189   void showGraph(ALGraph* aGraph)
    190   {
    191     int i=0;
    192     for(i=0; i<aGraph->n; i++)
    193     {
    194       EdgeNode* pos;
    195       printf("%c->", aGraph->adjlist[i]);
    196       pos=aGraph->adjlist[i].firstarc;
    197       while(pos!=NULL)
    198       {
    199         printf(" %c", pos->adjvex);
    200         pos=pos->nextrarc;
    201       }
    202       printf("
    ");
    203     }
    204   }
    205 
    206   void addBody(char aChar, int aPos, ALGraph* aGraph)
    207   {
    208     int inversePos;
    209     EdgeNode* node=(EdgeNode*)malloc(sizeof(EdgeNode));
    210     if((node->adjvex=mFind(aChar,aGraph))==-1)
    211       node->adjvex=createHead(aChar, aGraph);
    212     node->info=-1;
    213     node->nextrarc=NULL;
    214     if(aGraph->adjlist[aPos].firstarc==NULL)
    215       aGraph->adjlist[aPos].firstarc=node;
    216     else
    217     {
    218       EdgeNode* tail=aGraph->adjlist[aPos].firstarc;
    219       while(tail->nextrarc!=NULL)
    220         tail=tail->nextrarc;
    221       tail->nextrarc=node;
    222     }
    223 
    224     inversePos=node->adjvex;
    225     node=(EdgeNode*)malloc(sizeof(EdgeNode));
    226     node->adjvex=aPos;
    227     node->info=-1;
    228     node->nextrarc=NULL;
    229     if(aGraph->adjlist[inversePos].firstarc==NULL)
    230       aGraph->adjlist[inversePos].firstarc=node;
    231     else
    232     {
    233       EdgeNode* tail=aGraph->adjlist[inversePos].firstarc;
    234       while(tail->nextrarc!=NULL)
    235         tail=tail->nextrarc;
    236       tail->nextrarc=node;
    237     }
    238   }
    239 
    240   int createHead(char aChar, ALGraph* aGraph)
    241   {
    242     int currPos=aGraph->n;
    243     aGraph->adjlist[currPos].vexdate=aChar;
    244     aGraph->n++;
    245     return currPos;
    246   }
    247 
    248   int mFind(char aChar, ALGraph* aGraph)
    249   {
    250     int i=0;
    251     for(i=0; i<aGraph->n; i++)
    252     {
    253       if(aChar==aGraph->adjlist[i].vexdate)
    254         return i;
    255     }
    256     return -1;
    257   }
    258 
    259   int initGraph(ALGraph* aGraph)
    260   {
    261     int i=0;
    262     aGraph->e=0;
    263     aGraph->n=0;
    264     for(i=0; i<MaxVertexNum; i++)
    265     {
    266       aGraph->adjlist[i].firstarc=NULL;
    267     }
    268     return 0;
    269   }
    View Code
        以上程序输出结果为:
            
        Ctrl+F5执行时,出现错误!0xcccccccc内存不能read。
           
         Debug发现程序BFS函数:insertNode->data=temarc->adjvex;处指针未初始化,导致错误!
         
          Debug版中的堆栈中的局部变量(包括指针)在明确初始化之前都用0x0cc进行初始化,因此,未初始化时候的指针是指向地址0x0cccccccc的,而这段地址是处于内核地址空间,一般的应用程序是无权访问的,上面的报错就是这样产生的。因此,一旦遇到上述报错,基本可以认定程序中出现了野指针。

          另外一方面cc对应着int 3调试中断,堆栈中的存放的局部数据一般情况下是只读的,当发生意外执行堆栈里面的数据就会引发该调试中断。可以认为0x0cc就是有特殊含义的占位符,对于指针而言,它跟NULL是一个意思。

          其它具有特殊意义的占位符还有:

          0x00000000 - 一般是NULL, 也就是0, 空指针

          0xcdcdcdcd- Created but not initialized(创建但未初始化,当字符串看就是 “屯屯屯屯……”)

          0xdddddddd- Deleted(删除)

          0xfeeefeee- Freed memory set by NT's heap manager(堆管理器释放的内存区域。注:发现有值为0xfeeefeee的指针,就说明对应的内存已被释放掉了)

          0xcccccccc - Uninitialized locals in VC6 when you compile w/ /GZ (当编译时没有初始化的局部变量,即野指针,当作字符串看就是“烫烫烫烫……”)

          0xabababab - Memory following a block allocated by LocalAlloc()  (局部变量内存块)

         总结:C的指针真是让人头大,灵活代价就是复杂。自己还是一个小菜鸟啊,还得不断学习。

  • 相关阅读:
    bash 笔记
    lvs: linux virtual server
    学习html第一天
    学习c语言的第14天
    c语言学习的第13天2
    c语言学习的第13天1
    c语言学习的第12天
    c语言学习的第11天 指针
    移动端点击延迟300毫秒----FastClick用法
    H5移动端复制功能实现
  • 原文地址:https://www.cnblogs.com/wp5719/p/5378675.html
Copyright © 2011-2022 走看看