無向圖的連通分量和生成樹
阿新 • • 發佈:2019-01-27
//名詞解釋: //一個連通圖(對於無向圖)的生成樹是一個極小的連通子圖,它含有途中所有的頂點,但只有足以構成一個樹的n-1條邊。 //下面的程式為通過DFS深度優先遍歷一個非連通圖(會生成>1的生成樹,用孩子兄弟鏈作為生成森林的儲存結構)。 #include "stdio.h" #include "string.h" #include "stdlib.h" #define MAX_VERTEX_NUM 20//最大的頂點數 //邊結點 typedef struct Edge { struct Edge *next;//指向下一個邊的指標 int index;//該邊所依賴的頂點的位置 }Edge; //頂點 typedef struct { char name[10];//頂點的名字 Edge * first;//指向依賴該頂點的第一條邊 }Vertex; typedef struct { int ver_num;//頂點的數 int edge_num;//邊數 Vertex vertexs[MAX_VERTEX_NUM]; }Undigraph; //根據名字找到頂點的位置 int get_location (Undigraph *ud,char * name) { int i; for (i = 0;i < ud->ver_num;i++) { if (0 == strcmp(name,ud->vertexs[i].name)) { return i; } } return -1; } //建立一個邊 Edge* new_edge () { Edge *edge = (Edge*)malloc(sizeof(Edge)); if (NULL == edge) { exit(-1); } edge->next = NULL; return edge; } //建立無向圖 void create_undigraph (Undigraph * ud) { int k,i,j; char v1[10],v2[10]; Edge *edge = NULL; scanf ("%d%d",&(ud->ver_num),&(ud->edge_num));//輸入頂點數和邊的數量 //初始化頂點 for (k = 0;k < ud->ver_num;k++) { scanf("%s",ud->vertexs[k].name); ud->vertexs[k].first = NULL; } //初始化邊 for (k = 0; k < ud->edge_num;k++) { scanf ("%s %s",v1,v2); i = get_location (ud,v1); j = get_location (ud,v2); edge = new_edge (); edge->index = j; edge->next = ud->vertexs[i].first; ud->vertexs[i].first = edge; edge = new_edge (); edge->index = i; edge->next = ud->vertexs[j].first; ud->vertexs[j].first = edge; } } //返回下標為v的頂點的第一個鄰接點,有返回,沒有返回NULL Edge* first_adjacent_vertex (Undigraph *ud,int v) { if (v < 0 || v >= ud->ver_num) { return NULL; } return ud->vertexs[v].first; } //返回edge後的第一個鄰接點,有返回,沒有返回NULL Edge* next_adjacent_vertex (Edge *edge ) { if (NULL == edge) { return NULL; } return edge->next; } //用於記錄頂點是否被訪問過的標誌陣列 int visited[MAX_VERTEX_NUM]; //------樹的二叉連結串列(孩子-兄弟)儲存表示--------- typedef struct CSNode { char name[10];//圖中頂點的名字 struct CSNode *first_child,*next_sibling; }CSNode,*Tree; CSNode * create_CSNode (){ CSNode * node = (CSNode*)malloc(sizeof(CSNode)); if (NULL == node) { exit(-1); } node->first_child = NULL; node->next_sibling = NULL; return node; } // void dfs_tree (Undigraph *ud,int v,Tree *t) { Edge *edge = NULL; CSNode *p = NULL; strcpy((*t)->name,ud->vertexs[v].name); visited[v] = 1; edge = first_adjacent_vertex (ud,v); while (NULL != edge) { if (0 == visited[edge->index]) { CSNode *node = create_CSNode (); if (NULL == (*t)->first_child) { (*t)->first_child = node; }else { p->next_sibling = node; } p = node; dfs_tree (ud,edge->index,&p); } edge = edge->next; } } void dfs_forest (Undigraph *ud,Tree *t) { int i; CSNode *node = NULL; CSNode *p = NULL; memset (visited,0,sizeof(visited)); for (i = 0;i < ud->ver_num;i++) { if (0 == visited[i]) { node = create_CSNode (); if (NULL == (*t)) {//根節點 (*t) = node; }else { p->next_sibling = node;//其他生成樹的根 } p = node; dfs_tree (ud,i,&p); } } } //遍歷二叉樹 void traverse (Tree tree) { if (tree != NULL) { printf ("%s-",tree->name); traverse (tree->first_child); traverse (tree->next_sibling); } } int main () { Undigraph ud; Tree tree = NULL; create_undigraph (&ud); dfs_forest (&ud,&tree); traverse (tree); return 0; }