圖->連通性->無向圖的連通分量和生成樹


文字描述

  對無向圖進行遍歷時,對於連通圖,僅需從圖中任一頂點出發,進行深度優先搜索或廣度優先搜索,便可訪問到圖中所有頂點。但對非連通圖,則需從多個頂點出發搜索,每一次從一個新的起始點出發進行搜索過程得到的頂點訪問序列恰為其各個連通分量中的頂點集。

  對於非連通圖,每個連通分量中的頂點集,和遍歷時走過的邊一起構成若干棵生成樹,這些連通分量的生成樹組成非連通圖的生成森林.

示意圖

 

算法分析

求無向圖的連通分量的生成森林的算法時間復雜度和遍歷相同.

代碼實現

  1 //1.建立無向圖
  2 //2.建立無向圖的深度優先生成森林, 森林轉換成二叉樹結構,並采用孩子兄弟鏈表存儲
  3 //https://www.cnblogs.com/tgycoder/p/5048898.html
  4 //https://blog.csdn.net/qq_16234613/article/details/77431043
  5 
  6 #include <stdio.h>
  7 #include <stdlib.h>
  8 #include <string.h>
  9 
 10 ///for debug start///
 11 #include <stdarg.h>
 12 #define DEBUG(args...) debug_(__FILE__, __FUNCTION__, __LINE__, ##args)
 13 void debug_(const char* file, const char* function, const int line, const char *format, ...)
 14 {
 15     char buf[1024] = {0};
 16     sprintf(buf, "[%s,%s,%d]", file, function, line);
 17 
 18     va_list list;
 19     va_start(list, format);
 20     vsprintf(buf+strlen(buf), format, list);
 21     va_end(list);
 22 
 23     printf("%s\n", buf);
 24 
 25 }
 26 ///for debug end///
 27 
 28 #define INFINITY        100000
 29 #define MAX_VERTEX_NUM    20
 30 #define None -1
 31 typedef enum {DG, DN, UDG, UDN} GraphKind;
 32 typedef char VertexType;
 33 typedef struct{char note[10];}InfoType;
 34 //弧結點
 35 typedef struct ArcNode{
 36     int adjvex;//該弧所指向的頂點的位置
 37     struct ArcNode *nextarc;//指向下一條弧的結點
 38     InfoType *info;//與該弧相關的其他信息
 39 }ArcNode;
 40 typedef struct VNode{
 41     VertexType data;//頂點信息
 42     ArcNode *firstarc;//指向第一條依附該頂點的弧的指針
 43 }VNode, AdjList[MAX_VERTEX_NUM];
 44 
 45 typedef struct{
 46     AdjList vertices;//存放圖的頭結點的鏈表
 47     int vexnum;//圖的頂點數
 48     int arcnum;//圖的弧數
 49     int kind;//圖類型
 50 }ALGraph;
 51 
 52 //返回圖G中頂點信息委v的頂點位置
 53 int LocateVex(ALGraph G, VertexType v)
 54 {
 55     int i = 0;
 56     for(i=0; i<G.vexnum; i++){
 57         if(G.vertices[i].data == v){
 58             return i;
 59         }
 60     }
 61     return -1;
 62 }
 63 
 64 //返回圖G的頂點位置為loc的頂點信息
 65 VertexType GetVex(ALGraph G, int loc)
 66 {
 67     return G.vertices[loc].data;
 68 }
 69 
 70 //在鏈表L的頭部插入頂點v
 71 int InsFirst(ArcNode *L, int v)
 72 {
 73     ArcNode *n = (ArcNode *)malloc(sizeof(struct ArcNode));
 74     n->adjvex = v;
 75     n->nextarc = L->nextarc;
 76     L->nextarc = n;
 77     return 0;
 78 }
 79 
 80 //返回圖G中與頂點v相連的第一個頂點在圖中的位置
 81 int FirstAdjVex(ALGraph G, int v)
 82 {
 83     return G.vertices[v].firstarc->nextarc->adjvex;
 84 }
 85 
 86 //返回圖G中與頂點v相鄰的w的下一個相鄰的定點在圖中的位置
 87 int NextAdjVex(ALGraph G, int v, int w)
 88 {
 89     ArcNode *arc = G.vertices[v].firstarc;
 90     while(arc && arc->adjvex != w){
 91         arc = arc->nextarc;
 92     }
 93     if(arc && arc->nextarc){
 94         return arc->nextarc->adjvex;
 95     }
 96     return None;
 97 }
 98 
 99 //創建一個無向圖
100 int CreateUDG(ALGraph *G){
101     printf("!以鄰接表作為圖的存儲結構創建無向圖!\n");
102     G->kind = UDG;
103     int i = 0, j = 0, k = 0, IncInfo = 0;
104     int v1 = 0, v2 = 0;
105     char tmp[10] = {0};
106     printf("輸入頂點數,弧數:");
107     scanf("%d,%d", &G->vexnum, &G->arcnum);
108     for(i=0; i<G->vexnum; i++){
109         printf("輸入第%d個頂點: ", i+1);
110         memset(tmp, 0, sizeof(tmp));
111         scanf("%s", tmp);
112         G->vertices[i].data = tmp[0];
113         G->vertices[i].firstarc = malloc(sizeof(struct ArcNode));
114         G->vertices[i].firstarc->adjvex = None;
115         G->vertices[i].firstarc->nextarc = NULL;
116     }
117     for(k=0; k<G->arcnum; k++){
118         printf("輸入第%d條弧(頂點1, 頂點2): ", k+1);
119         memset(tmp, 0, sizeof(tmp));
120         scanf("%s", tmp);
121         sscanf(tmp, "%c,%c", (char *)&v1, (char *)&v2);
122         i = LocateVex(*G, v1);
123         j = LocateVex(*G, v2);
124         InsFirst(G->vertices[i].firstarc, j);
125         InsFirst(G->vertices[j].firstarc, i);
126         if(IncInfo){}
127     }
128     return 0;
129 }
130 
131 //打印無向圖G的鄰接表信息
132 void printALG(ALGraph G)
133 {
134     int i = 0;
135     ArcNode *p = NULL;
136     for(i=0; i<G.vexnum; i++){
137         printf("%c\t", G.vertices[i].data);
138         p = G.vertices[i].firstarc;
139         while(p){
140             if(p->adjvex != None){
141                 printf("%d\t", p->adjvex);
142             }
143             p = p->nextarc;
144         }
145         printf("\n");
146     }
147     return;
148 }
149 
150 typedef VertexType TElemType;
151 //采用孩子兄弟鏈表存儲結構
152 typedef struct{
153     TElemType data;
154     struct CSNode *firstchild;
155     struct CSNode *nextsibling;
156 }CSNode, *CSTree;
157 
158 //先根遍歷樹T
159 void PreOrderTraverse(CSTree T){
160     if(T){
161         printf("%c\t", T->data);
162         PreOrderTraverse((CSTree)T->firstchild);
163         PreOrderTraverse((CSTree)T->nextsibling);
164         return ;
165     }else{
166         return ;
167     }
168 }
169 
170 //中根遍歷樹T
171 void InOrderTraverse(CSTree T){
172     if(T){
173         InOrderTraverse((CSTree)T->firstchild);
174         printf("%c\t", T->data);
175         InOrderTraverse((CSTree)T->nextsibling);
176         return ;
177     }else{
178         return ;
179     }
180 }
181 
182 int visited[MAX_VERTEX_NUM];
183 CSTree DFSTree_q = NULL;
184 int ISFirst = 1;
185 //從第v個頂點出發深度優先遍歷圖G,建立以T為根的生成樹
186 void DFSTree(ALGraph G, int V, CSTree *T)
187 {
188     int w = 0;
189     CSTree p = NULL;
190     visited[V] = 1;
191     for(w=FirstAdjVex(G, V); w>=0; w=NextAdjVex(G, V, w)){
192         if(!visited[w]){
193             //分配孩子結點
194             p = (CSTree)malloc(sizeof(CSNode));
195             p->data = GetVex(G, w);
196             p->firstchild = NULL;
197             p->nextsibling = NULL;
198             if(ISFirst){
199                 //w是v的第一個未被訪問的鄰接頂點
200                 ISFirst = 0;
201                 (*T)->firstchild = (struct CSNode *)p;
202             }else{
203                 //w是v的其它未被訪問的鄰接頂點
204                 //是上一個鄰接頂點的右兄弟結點 
205                 DFSTree_q->nextsibling = (struct CSNode *)p;
206             }
207             DFSTree_q = p;
208             //從第w個頂點出發深度優先遍歷圖G,建立子生成樹DFSTree_q
209             DFSTree(G, w, &DFSTree_q);
210         }
211     }
212 }
213 
214 //建立無向圖G的深度優先生成森林的孩子兄弟鏈表T
215 void DFSForest(ALGraph G, CSTree *T)
216 {
217     CSTree p = NULL;
218     CSTree q = NULL;
219     *T = NULL;
220     int v = 0;
221     for(v=0; v<G.vexnum; v++){
222         visited[v] = 0;
223     }
224     for(v=0; v<G.vexnum; v++){
225         if(!visited[v]){
226             //第v個頂點為新的生成樹的根結點
227             p = (CSTree)malloc(sizeof(CSNode));
228             p->data = GetVex(G, v);
229             p->firstchild = NULL;
230             p->nextsibling = NULL;
231             if(!(*T)){
232                 //是第一顆生成樹的根
233                 *T = p;
234             }else{
235                 //是其他生成樹的根(前一顆的根的“兄弟”)
236                 q->nextsibling = (struct CSNode *)p;
237             }
238             //q指示當前生成樹的根
239             q = p;
240             //建立以p為根的生成樹
241             ISFirst = 1;
242             DFSTree(G, v, &p);
243         }
244     }
245 }
246 
247 int main(int argc, char *argv[])
248 {
249     ALGraph G;
250     //創建一個無向圖
251     CreateUDG(&G);
252     //打印無向圖中的信息
253     printALG(G);
254     
255     CSTree T;
256     //依照無向圖G,建立一顆生成森林,並將其轉換成成二叉樹存儲,二叉樹以孩子兄弟鏈表存儲結構存儲
257     DFSForest(G, &T);
258     //先根遍歷該生成樹
259     PreOrderTraverse(T);printf("\n");
260     //中根遍歷該生成樹
261     InOrderTraverse(T);printf("\n");
262     return 0;
263 }
無向圖的深度優先生成森林算法

代碼運行

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM