图的深度优先和广度优先搜索算法

  本文取自《数据结构与算法》(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的指针真是让人头大,灵活代价就是复杂。自己还是一个小菜鸟啊,还得不断学习。

原文地址:https://www.cnblogs.com/wp5719/p/5378675.html