[原创]无向图转换&遍历&MST
<P>请不吝赐教,多多指点...多谢了!<br>//"有向图"参见<a href="http://bbs.bc-cn.net/viewthread.php?tid=130955&extra=&page=1#130955" target="_blank" >http://bbs.bc-cn.net/viewthread.php?tid=130955&extra=&page=1#130955</A><br>//<a href="http://blog.bc-cn.net/user15/82588/index.shtml" target="_blank" >http://blog.bc-cn.net/user15/82588/index.shtml</A><br>#include <stdio.h><br>#include <stdlib.h><br>#include <string.h><br>#include <limits.h><br>#define MaxSize 250<br>#define MaxLine 20<br>typedef int Status;<br>typedef int ElemType;<br>typedef struct{<br> ElemType VNode;<br> }VexType;<br>typedef struct Arcs{<br> ElemType Adj;<br> unsigned int Weight;<br> struct Arcs *NextArc;<br> }ArcType;<br>typedef struct{<br> VexType Vex[MaxSize];<br> ArcType *FirstArc[MaxSize];<br> int VexNums;<br> }ALGraph; //定义图的无向邻接表;<br>typedef struct{<br> VexType Vex[MaxSize];<br> unsigned int Weight[MaxSize][MaxSize];<br> int VexNums;<br> }AMGraph; //定义图的邻接矩阵;<br>typedef struct{<br> ElemType head,tail;<br> unsigned int Weight;<br> }MST; //最小生成树辅助结构;<br>//=================================================================================<br>Status CreateALGraph(ALGraph *ALG,FILE *fp); //创立无向图的邻接表;<br>Status AL2AM(ALGraph ALG,AMGraph *AMG); //转换为图的邻接矩阵;<br>Status ALG_Travers(ALGraph ALG); //图的遍历;<br>Status ALG_DFS(ALGraph ALG,int v,int *Visited); //深度遍历(递 归);<br>Status ALG_DFS_Uni(ALGraph ALG,int v,int *Visited); //深度遍历(非递归);<br>Status ALG_BFS(ALGraph ALG,int v,int *Visited); //广度遍历;<br>Status CreateMST(ALGraph ALG,AMGraph AMG); //构造最小生成树;<br>Status AMG_Prim(AMGraph AMG,MST *MST_P); //(邻接矩阵)Prim;<br>Status ALG_Prim(ALGraph ALG,MST *MST_P); //(邻 接 表)Prim;<br>Status ALG_Kruskal(ALGraph ALG,MST *MST_K); //(邻 接 表)Kruskal;<br>Status AMG_Kruskal(AMGraph AMG,MST *MST_K); //(邻接矩阵)Kruskal;<br>Status FindVex(int *Vex,int v); //(Kruskal)查找顶点所在树的根结点在数组Vex中的序号;<br>Status Prn_ALGraph(ALGraph ALG); //输出邻接表;<br>Status Prn_AMGraph(AMGraph AMG); //输出邻接矩阵;<br>Status PrintMST(MST *MT); //输出最小生成树;<br>//=================================================================================<br>int main(void)<br>{<br> ALGraph ALG;<br> AMGraph AMG;<br> FILE *fp;<br> char FileName[MaxLine];<br> printf("\t\t<<<<<< 无向图的应用演示 >>>>>>\n创立无向图:\n");<br> printf("==============================================================\n");<br> printf(" 包含图信息的文本文件的格式为:\n第一行: 12\t<--- 顶点总数;\n");<br> printf("第二行: 1 6 16\n");<br> printf("\t ↑ ↑ ↑\n"); <br> printf("\t │ │ └─── AB边的权值Weight;\n");<br> printf("\t │ └──── A边所依附的另一顶点B;\n");<br> printf("\t └────── 某顶点A。\n第m行 :以后各行与第二行类似。\n");<br> printf("==============================================================\n");<br> printf("输入文本文件名(输入quit退出)。\n");<br> do{<br> printf(" 输入文件名:");<br> gets(FileName);<br> if(!strcmp(FileName,"quit")) exit (1);<br> }while(FileName[0] == '\0' || !(fp = fopen(FileName,"r")));</P><P> printf("\n\n 一、创立无向图的邻接表(Adjacency List):\n"); <br> CreateALGraph(&ALG,fp);<br> fclose(fp);<br> Prn_ALGraph(ALG);<br> printf("\n\n 二、邻接表的图的遍历(Traversing graph):\n"); <br> ALG_Travers(ALG);<br> printf("\n\n 三、图的邻接表转换为邻接矩阵(Adjacency Matrix):\n"); <br> AL2AM(ALG,&AMG);<br> Prn_AMGraph(AMG);<br> printf("\n\n 四、构建最小生成树MST(mininum cost spaning tree):\n"); <br> CreateMST(ALG,AMG);<br> printf("\n");system("pause");<br> return 0;<br>}</P>
[align=right][color=#000066][此贴子已经被作者于2007-4-21 21:35:26编辑过][/color][/align]
回复:(haroldi)无向图转换&遍历&MST
<P>Status CreateALGraph(ALGraph *ALG,FILE *fp)//创立无向图的邻接表;<BR>{<BR> ArcType *p = NULL;<BR> int i,j,w;<BR> <BR> fscanf(fp,"%d",&ALG->VexNums);<BR> for(i = 1;i <= ALG->VexNums;i++) //初始化;<BR> {<BR> ALG->Vex[i].VNode = i;<BR> ALG->FirstArc[i] = NULL;<BR> }<BR> while(fscanf(fp,"%d%d%d",&i,&j,&w) == 3)<BR> {<BR> if(!(p = (ArcType *)malloc(sizeof(ArcType))))<BR> {printf("\n内存溢出。");return 1;}<BR> p->Adj = j;<BR> p->Weight = w;<BR> p->NextArc = ALG->FirstArc[i];<BR> ALG->FirstArc[i] = p; <BR> if(!(p = (ArcType *)malloc(sizeof(ArcType))))<BR> {printf("\n内存溢出。");return 1;}<BR> p->Adj = i; //无向邻接表,反向赋值...:-(<BR> p->Weight = w;<BR> p->NextArc = ALG->FirstArc[j];<BR> ALG->FirstArc[j] = p;<BR> }<BR> return 0;<BR>}<BR>//=================================================================================<BR>Status AL2AM(ALGraph ALG,AMGraph *AMG) //转换为图的邻接矩阵;<BR>{<BR> int i,j;<BR> ArcType *p = NULL;<BR> AMG->VexNums = ALG.VexNums;<BR> for(i = 1;i <= AMG->VexNums;i++) //初始化;<BR> for(j = 1;j <= AMG->VexNums;j++)<BR> AMG->Weight[i][j] = INT_MAX;<BR> for(i = 1;i <= ALG.VexNums;i++)<BR> {<BR> AMG->Vex[i] = ALG.Vex[i];<BR> p = ALG.FirstArc[i];<BR> while(p != NULL)<BR> {<BR> AMG->Weight[i][p->Adj] = p->Weight;<BR> p = p->NextArc;<BR> }<BR> }<BR> return 0;<BR>}<BR>//=================================================================================<BR>Status ALG_Travers(ALGraph ALG) //图的遍历;<BR>{<BR> int i,Visited[MaxSize];<BR> printf("\n 1. 图的深度遍历:"); <BR> printf("\n递 归:");<BR> for(i = 1;i <= ALG.VexNums;i++) Visited[i] = 0;<BR> for(i = 1;i <= ALG.VexNums;i++)<BR> if(Visited[i] == 0) ALG_DFS(ALG,i,Visited);<BR> printf("\n非递归:");<BR> for(i = 1;i <= ALG.VexNums;i++) Visited[i] = 0;<BR> for(i = 1;i <= ALG.VexNums;i++)<BR> if(Visited[i] == 0) ALG_DFS_Uni(ALG,i,Visited);<BR> printf("\n\n 2. 图的广度遍历:\n\t"); <BR> for(i = 1;i <= ALG.VexNums;i++) Visited[i] = 0;<BR> for(i = 1;i <= ALG.VexNums;i++)<BR> if(Visited[i] == 0) ALG_BFS(ALG,i,Visited);<BR> return 0;<BR>}<BR>//=================================================================================<BR>Status ALG_DFS(ALGraph ALG,int v,int *Visited) //图的深度遍历(递 归);<BR>{<BR> ArcType *p = NULL;<BR> Visited[v] = 1;<BR> printf("%2d ->",v);<BR> p = ALG.FirstArc[v];<BR> while(p != NULL)<BR> {<BR> if(Visited[p->Adj] == 0) ALG_DFS(ALG,p->Adj,Visited);<BR> p = p->NextArc;<BR> }<BR> return 0;<BR>}<BR>//=================================================================================<BR>Status ALG_DFS_Uni(ALGraph ALG,int v,int *Visited)//图的深度遍历(非递归);<BR>{<BR> ElemType Stack[MaxSize];<BR> ArcType *p = NULL;<BR> int top = -1;<BR> Visited[v] = 1;<BR> printf("%2d ->",v);<BR> Stack[++top] = v;<BR> while(top != -1)<BR> {<BR> p = ALG.FirstArc[Stack[top]];<BR> while(p != NULL)<BR> {<BR> if(Visited[p->Adj] == 0)<BR> {<BR> Visited[p->Adj] = 1;<BR> printf("%2d ->",p->Adj);<BR> Stack[++top] = p->Adj;<BR> break;<BR> }<BR> p = p->NextArc;<BR> }<BR> if(p == NULL) --top;<BR> }<BR> return 0;<BR>}<BR>//=================================================================================<BR>Status ALG_BFS(ALGraph ALG,int v,int *Visited) //图的广度遍历;<BR>{<BR> int rear,front;<BR> ElemType Queue[MaxSize];<BR> ArcType *p = NULL;<BR> rear = front = 0;<BR> Visited[v] = 1;<BR> printf("%2d ->",v);<BR> rear =(rear + 1)%MaxSize;<BR> Queue[rear] = v;<BR> while(rear != front)<BR> {<BR> front = (front + 1)%MaxSize;<BR> p = ALG.FirstArc[Queue[front]];<BR> while(p != NULL)<BR> {<BR> if(Visited[p->Adj] == 0)<BR> {<BR> Visited[p->Adj] = 1;<BR> printf("%2d ->",p->Adj);<BR> rear =(rear + 1)%MaxSize;<BR> Queue[rear] = p->Adj;<BR> }<BR> p = p->NextArc;<BR> }<BR> }<BR> return 0;<BR>}<BR>//=================================================================================<BR>Status CreateMST(ALGraph ALG,AMGraph AMG)//构造最小生成树;<BR>{<BR> MST MST_MP[MaxSize],MST_LP[MaxSize],MST_MK[MaxSize],MST_LK[MaxSize]; <BR> printf("\n\n 1. Prim普里姆(图的邻接矩阵):\n"); <BR> AMG_Prim(AMG,MST_MP); PrintMST(MST_MP);<BR> printf("\n\n 2. Kruskal克鲁斯卡尔(图的邻接表):\n");<BR> ALG_Kruskal(ALG,MST_LK); PrintMST(MST_LK);<BR> printf("\n\n 3. Prim普里姆(图的邻接表):\n"); <BR> ALG_Prim(ALG,MST_LP); PrintMST(MST_LP);<BR> printf("\n\n 4. Kruskal克鲁斯卡尔(图的邻接矩阵):\n");<BR> AMG_Kruskal(AMG,MST_MK); PrintMST(MST_MK);<BR> return 0;<BR>}<BR>//=================================================================================<BR>Status AMG_Prim(AMGraph AMG,MST *MST_P) //Prim普里姆(邻接矩阵),适于稠密网;<BR>{<BR> int i,j,k,Vex[MaxSize]; //最小生成树结点;<BR> unsigned int min,lowcost[MaxSize]; //(由Vex[i]到i)权值;<BR> for(i = 2;i <= AMG.VexNums;i++)<BR> {<BR> Vex[i] = 1; //表示V-U中各点与U(当前仅含顶点1)的关系;<BR> lowcost[i] = AMG.Weight[1][i]; //各点对U的权值(1到各点的权值);<BR> }<BR>// Vex[1] = 1; //从顶点1开始遍历;<BR> lowcost[1] = 0; //U中仅包含顶点1; <BR> for(i = 1;i <= AMG.VexNums;i++)<BR> {<BR> k = i;<BR> min = INT_MAX;<BR> for(j = 1;j <= AMG.VexNums;j++)//得到与当前点i相临且权值最小min的顶点k;<BR> {<BR> if(lowcost[j] < min && lowcost[j] != 0)//找(V-U)各点对U中权值最小的;<BR> {<BR> min = lowcost[j];<BR> k = j;<BR> }<BR> }<BR> if(min == INT_MAX) break; //若U与V-U再没有边(不连通或V==U),退出循环;<BR> printf("[%2d,%2d];",Vex[k],k);<BR> MST_P[i].head = Vex[k]; //将得到的MST各点送入MST_P;<BR> MST_P[i].tail = k;<BR> MST_P[i].Weight = lowcost[k];<BR>// vex[k] = 0;<BR> lowcost[k] = 0; //顶点k并入U;</P><P> for(j = 1;j <= AMG.VexNums;j++) //重新计算U与V-U间各个权值;<BR> {<BR> if(AMG.Weight[k][j] < lowcost[j])<BR> {<BR> Vex[j] = k;<BR> lowcost[j] = AMG.Weight[k][j];<BR> }<BR> }<BR> }<BR> if(i == AMG.VexNums) MST_P[0].Weight = i - 1; <BR> else MST_P[0].Weight = 0;//MST结点数如与图中总数不等,则不能生成MST或有误;<BR> return 0;<BR>}<BR>//=================================================================================<BR>Status ALG_Prim(ALGraph ALG,MST *MST_P) //(图的邻接表)Prim普里姆,适于稠密网;<BR>{<BR>// struct {ElemType Vex; unsigned int lowcost;}closedge[MaxSize];<BR> int i,j,k,Vex[MaxSize];<BR> unsigned int min,lowcost[MaxSize];<BR> ArcType *p = NULL;<BR> for(i = 1;i <= ALG.VexNums;i++)<BR> {<BR> Vex[i] = 1;<BR> p = ALG.FirstArc[1]; //从[1]开始遍历;<BR> while(p != NULL)<BR> {<BR> if(p->Adj == i) lowcost[i] = p->Weight;<BR> p = p->NextArc;<BR> }<BR> }<BR>// Vex[1] = 1;<BR> lowcost[1] = 0;<BR> for(i = 1;i <= ALG.VexNums;i++)<BR> {<BR> k = i;<BR> min = INT_MAX;<BR> for(j = 1;j <= ALG.VexNums;j++)<BR> {<BR> if(lowcost[j] < min && lowcost[j] != 0)<BR> {<BR> min = lowcost[j];<BR> k = j;<BR> }<BR> }<BR> if(min == INT_MAX) break; //若U与V-U再没有边(不连通或V==U),退出循环;<BR> printf("[%2d,%2d];",Vex[k],k);<BR> MST_P[i].head = Vex[k]; //将得到的MST各点送入MST_P;<BR> MST_P[i].tail = k;<BR> MST_P[i].Weight = lowcost[k];<BR>// vex[k] = 0;<BR> lowcost[k] = 0; //顶点k并入U;</P>
<P> for(j = 1;j <= ALG.VexNums;j++)<BR> {<BR> p = ALG.FirstArc[k];<BR> while(p != NULL)<BR> {<BR> if(p->Adj == j && p->Weight < lowcost[j])<BR> {<BR> lowcost[j] = p->Weight;<BR> Vex[j] = k;<BR> }<BR> p = p->NextArc;<BR> }<BR> }<BR> }<BR> if(i == ALG.VexNums) MST_P[0].Weight = i - 1; <BR> else MST_P[0].Weight = 0;//MST结点数如与图中总数不等,则不能生成MST或有误;<BR> return 0;<BR>}<BR>//=================================================================================<BR>Status FindVex(int *Vex,int v)//(Kruskal)找顶点所在树的根结点在数组Vex中的序号;<BR>{<BR> int t;<BR> t = v;<BR> while(Vex[t] > 0)<BR> t = Vex[t];<BR> return t;<BR>}<BR>//=================================================================================<BR>Status AMG_Kruskal(AMGraph AMG,MST *MST_K)//Kruskal(邻接矩阵),适于稀疏网;<BR>{<BR>typedef struct{ ElemType v1,v2; unsigned int cost; }EdgeType;<BR> EdgeType Edgs[MaxSize];<BR> int i,j,k,vex1,vex2,Vex[MaxSize];<BR> ElemType tv;<BR> unsigned int tc;<BR> k = 1;<BR> Edgs[0].cost = 0; //记录总边数到Edgs[0].cost中;<BR> for(i = 1;i <= AMG.VexNums;i++) //将所有两点间关系初始化到Edgs中;<BR> {<BR> for(j = 1;j < i;j++)<BR> {<BR> Edgs[k].v1 = AMG.Vex[j].VNode; //j变化快,赋予v1(较小的坐标在前);<BR> Edgs[k].v2 = AMG.Vex[i].VNode;<BR> Edgs[k].cost = AMG.Weight[i][j];<BR> if(AMG.Weight[i][j] < INT_MAX) ++Edgs[0].cost;<BR> ++k;<BR> }<BR> }<BR> for(i = 1;i < AMG.VexNums*AMG.VexNums;i++) //Edgs按cost值,非递减排序;<BR> {<BR> k = i;<BR> for(j = i+1;j <= AMG.VexNums*AMG.VexNums;j++)<BR> if(Edgs[k].cost > Edgs[j].cost) k = j;<BR> if(k != i)<BR> {<BR> tv = Edgs[i].v1; Edgs[i].v1 = Edgs[k].v1; Edgs[k].v1 = tv;<BR> tv = Edgs[i].v2; Edgs[i].v2 = Edgs[k].v2; Edgs[k].v2 = tv;<BR> tc = Edgs[i].cost; Edgs[i].cost = Edgs[k].cost; Edgs[k].cost = tc;<BR> }<BR> }</P>
<P> for(i = 1;i <= AMG.VexNums;i++) Vex[i] = 0; //各点初始均独立;<BR> i = k = 1;<BR> while(k < AMG.VexNums)<BR> {<BR> vex1 = FindVex(Vex,Edgs[i].v1);<BR> vex2 = FindVex(Vex,Edgs[i].v2);<BR> if(vex1 != vex2)<BR> {<BR> Vex[vex2] = vex1;<BR> printf("[%2d,%2d];",Edgs[i].v1,Edgs[i].v2);<BR> MST_K[k].head = Edgs[i].v1; //将得到的MST各点送入MST_K;<BR> MST_K[k].tail = Edgs[i].v2;<BR> MST_K[k].Weight = Edgs[i].cost;<BR> if(++k >= (int)Edgs[0].cost - 1) break;<BR> }<BR> ++i;<BR> }<BR> if(k - 1 == AMG.VexNums - 1) MST_K[0].Weight = AMG.VexNums - 1;<BR> else MST_K[0].Weight = 0;<BR> return 0;<BR>}<BR>//=================================================================================<BR>Status ALG_Kruskal(ALGraph ALG,MST *MST_K)//Kruskal(邻接表),适于稀疏网;<BR>{<BR>typedef struct{ElemType v1,v2;unsigned int cost;} EdgeType;<BR> int i,j,k;<BR> ElemType Vex[MaxSize],v1,v2,tv;<BR> unsigned int tc;<BR> ArcType *p = NULL;<BR> EdgeType Edge[MaxSize];<BR> <BR> for(j = 1,i = 1;i <= ALG.VexNums;i++) //将所有两点间关系初始化到Edgs中;<BR> {<BR> Edge[j].v1 = ALG.Vex[i].VNode;<BR> p = ALG.FirstArc[i];<BR> while(p != NULL)<BR> {<BR> Edge[j].v2 = p->Adj;<BR> Edge[j].cost = p->Weight;<BR> p = p->NextArc;<BR> Edge[j].v1 = ALG.Vex[i].VNode;<BR> if(Edge[j].v1 < Edge[j].v2) ++j;<BR> }<BR> }<BR> if(Edge[j].v1 > Edge[j].v2) Edge[0].cost = j - 1;<BR> else Edge[0].cost = j; //记录总边数到Edgs[0].cost中;<BR> <BR> for(i = 1;i < (int)Edge[0].cost;i++) //Edgs按cost值,非递减排序;<BR> {<BR> k = i;<BR> for(j = i + 1;j <= (int)Edge[0].cost;j++)<BR> if(Edge[k].cost > Edge[j].cost) k = j;<BR> if(k != i)<BR> {<BR> tv = Edge[i].v1; Edge[i].v1 = Edge[k].v1; Edge[k].v1 = tv;<BR> tv = Edge[i].v2; Edge[i].v2 = Edge[k].v2; Edge[k].v2 = tv;<BR> tc = Edge[i].cost; Edge[i].cost = Edge[k].cost; Edge[k].cost = tc;<BR> }<BR> }<BR> <BR> for(i = 1;i <= (int)Edge[0].cost;i++) Vex[i] = 0;<BR> for(k = 1,i = 1;i <= (int)Edge[0].cost;i++)<BR> {<BR> v1 = FindVex(Vex,Edge[i].v1);<BR> v2 = FindVex(Vex,Edge[i].v2);<BR> if(v1 != v2)<BR> {<BR> Vex[v2] = v1;<BR> printf("[%2d,%2d];",Edge[i].v1,Edge[i].v2);<BR> MST_K[k].head = Edge[i].v1;<BR> MST_K[k].tail = Edge[i].v2;<BR> MST_K[k].Weight = Edge[i].cost;<BR> ++k;<BR> }<BR> }<BR> if(k - 1 == ALG.VexNums - 1) MST_K[0].Weight = ALG.VexNums - 1;<BR> else MST_K[0].Weight = 0;<BR> return 0;<BR>}<BR>//================================================================================<BR>Status Prn_ALGraph(ALGraph ALG) //输出邻接表;<BR>{<BR> int i;<BR> ArcType *p = NULL;<BR> for(i = 1;i <= ALG.VexNums;i++)<BR> {<BR> printf("\n %2d ==> ",i);<BR> p = ALG.FirstArc[i];<BR> while(p != NULL)<BR> {<BR> printf("%2d(%3d) ->",p->Adj,p->Weight);<BR> p = p->NextArc;<BR> }<BR> }<BR> printf("\n");<BR> return 0;<BR>}<BR>//=================================================================================<BR>Status Prn_AMGraph(AMGraph AMG) //输出邻接矩阵;<BR>{<BR> int i,j;<BR> for(i = 1;i <= AMG.VexNums;i++)<BR> {<BR> printf("\n\t");<BR> for(j = 1;j <= AMG.VexNums;j++)<BR> {<BR> if(AMG.Weight[i][j] < INT_MAX) printf(" %3d ",AMG.Weight[i][j]);<BR> else printf(" ∞ ");<BR> } <BR> printf("\n");<BR> }<BR> return 0;<BR>}<BR>//=================================================================================<BR>Status PrintMST(MST *MT) //输出最小生成树;<BR>{<BR> unsigned int i = 1;<BR> if(MT[0].Weight == 0) {printf("\n\t不能生成最小生成树。\n");return 1;}<BR> printf("\n\t边 信 息\t权 值");<BR> for(i = 1;i <= MT[0].Weight;i++)<BR> printf("\n\t(%2d,%2d)\t\t[%4d]",MT[i].head,MT[i].tail,MT[i].Weight);<BR> return 0;<BR>}<BR></P> [tk01] [tk02]
页:
[1]
