1. 程式人生 > >圖->連通性->無向圖的連通分量和生成樹

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

文字描述

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

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

示意圖

 

演算法分析

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

程式碼實現

  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 }
無向圖的深度優先生成森林演算法

程式碼執行