C++: 图算法综合
(邻接矩阵,邻接表,深度优先搜索,广度优先搜索,拓扑排序,最小生成树)
下面的源程序可以对一个给出的图形进行求邻接表、邻接矩阵、深度优先搜索、广度优先搜索、拓扑排序、最小生成树六种运算。
#define true 1 #define false 0 #define ok 1 #define error 0 #define overflow -2 #define null 0 typedef int status; #include <stdio.h> #include <stdlib.h> #include <conio.h> #define maxlen 10 #define large 999 typedef struct { int a[maxlen],b[maxlen],h[maxlen]; /*第K边的起点,终点,权值*/ char vexs[maxlen]; /*顶点信息集合*/ int vexnum,arcnum; /*顶点数和边数*/ int kind; /*图的类型*/ int arcs[maxlen][maxlen]; /*邻接矩阵*/ }graph; typedef struct node /*表结点结构*/ { int adjvex; /*存放与头结点相邻接的顶点在数组中的序号*/ int info; /*权值*/ struct node *next; /*指向与头结点相邻接下一个顶点的表结点*/ }edgenode; typedef struct /*头结点结构*/ { int id; /*顶点入度*/ char data; /*顶点信息*/ edgenode *link; /*指向与头结点相邻接的顶点在数组中的序号*/ }vexnode; typedef struct /*邻接表结构*/ { vexnode adjs[maxlen]; /*邻接表的头结点集合*/ int vexnum,arcnum; /*顶点数,边数*/ int kind; }adjlist; typedef struct qnode /*队列存储结构*/ { int data; struct qnode *next; }linkqlist; typedef struct { linkqlist *front; /*队头指针*/ linkqlist *rear; /*队尾指针*/ }linkqueue; typedef struct /*栈结构*/ { int stack[maxlen]; int top; }stackstru; int cnull=-1; graph g; adjlist adjl; stackstru *t; /*拓扑序列顶点栈*/ stackstru *s; /*零入度顶点栈*/ linkqueue *q; graph printf_adjmatrix(graph g) /*输出邻接矩阵*/ { int i, j; printf("邻接矩阵:\n"); printf("vertex\t"); for(i=0; i<g.vexnum; i++){ printf("%4c", g.vexs[i]); } printf("\n"); for(i=0; i<g.vexnum; i++){ printf("% 4c \t", g.vexs[i]); for(j=0; j<g.vexnum; j++){ printf("%4d", g.arcs[i][j]); } printf("\n"); } return g; } void create_1(graph g) /*以邻接矩阵建有向图*/ { int i, j, k, c=0; for(i=0; i<g.vexnum; i++){ for(j=0; j<g.vexnum; j++){ g.arcs[i][j]=c; } } for(k=0; k<g.arcnum; k++){ g.arcs[g.a[k]-1][g.b[k]-1]=1; } printf_adjmatrix(g); } void create_2(graph g) /*以邻接矩阵建无向图*/ { int i, j, k, c=0; for(i=0; i<g.vexnum; i++){ for(j=0; j<g.vexnum; j++){ g.arcs[i][j]=c; } } for(k=0; k<g.arcnum; k++){ g.arcs[g.a[k]-1][g.b[k]-1]=1; g.arcs[g.b[k]-1][g.a[k]-1]=1; } printf_adjmatrix(g); } graph create_3(graph g) /*以邻接矩阵建有向网*/ { int i, j, k, c=999; for(i=0; i<g.vexnum; i++){ for(j=0; j<g.vexnum; j++){ g.arcs[i][j]=c; } } for(k=0; k<g.arcnum; k++){ g.arcs[g.a[k]-1][g.b[k]-1]=g.h[k]; } printf_adjmatrix(g); return g; } graph create_4(graph g) /*以邻接矩阵建无向网*/ { int i, j, k, c=999; for(i=0; i<g.vexnum; i++){ for(j=0; j<g.vexnum; j++){ g.arcs[i][j]=c; } } for(k=0; k<g.arcnum; k++){ g.arcs[g.a[k]-1][g.b[k]-1]=g.h[k]; g.arcs[g.b[k]-1][g.a[k]-1]=g.h[k]; } printf_adjmatrix(g); return g; } void creategraph(graph g) /*邻接矩阵*/ { switch(g.kind) { case 1:create_1(g); break; case 2:create_2(g); break; case 3:create_3(g); break; case 4:create_4(g); break; default:printf("Error\n"); } } adjlist createlist(graph g, adjlist adjl) /*邻接表*/ { int i; edgenode *p; if(g.kind==1||g.kind==3){ for(i=0; i<adjl.arcnum; i++){ p=(edgenode*)malloc(sizeof(edgenode)); p->adjvex=g.b[i]; p->info=g.h[i]; p->next=adjl.adjs[g.a[i]-1].link; adjl.adjs[g.a[i]-1].link=p; } } if(g.kind==2||g.kind==4){ for(i=0; i<adjl.arcnum; i++){ p=(edgenode*)malloc(sizeof(edgenode)); p->adjvex=g.b[i]; p->info=g.h[i]; p->next=adjl.adjs[g.a[i]-1].link; adjl.adjs[g.a[i]-1].link=p; p=(edgenode*)malloc(sizeof(edgenode)); p->adjvex=g.a[i]; p->info=g.h[i]; p->next=adjl.adjs[g.b[i]-1].link; adjl.adjs[g.b[i]-1].link=p; } } printf("邻接表为:\n"); for(i=0; i<g.vexnum; i++){ printf("[%d,%c]=>", i+1, adjl.adjs[i].data); p=adjl.adjs[i].link; while(p!=cnull){ printf("[%c,%d]-->", adjl.adjs[(p->adjvex)-1].data, p->info); p=p->next; } printf("^\n"); } return adjl; } void initqueue(linkqueue *p) /*初始化队列*/ { p->front=(linkqlist *)malloc(sizeof(linkqlist)); p->rear=p->front; (p->front)->next=null; } status empty(linkqueue *q) /*判断队列是否为空队列*/ { int v; if(q->front==q->rear){ v=true; } else{ v=false; } return v; } status addqueue(linkqueue *q, int e) /*入队列*/ { q->rear->next=(linkqlist *)malloc(sizeof(linkqlist)); q->rear=q->rear->next; if(!q->rear){ return -1; } q->rear->data=e; q->rear->next=null; } status delqueue(linkqueue *q) /*出队列*/ { linkqlist *p; int e; if(q->front==q->rear){ printf("the linklist is overflow"); }else{ p=(q->front)->next; (q->front)->next=p->next; e=p->data; } if(q->rear==p){ q->rear=q->front; } free(p); /*释放p所指的内存区*/ return(e); } void DFS(int i, adjlist adjl) /*深度优先搜索*/ { edgenode *p; int j; int visited[maxlen]; /*访问标志数组,访问过为1,未访问过为0*/ for(j=0; j<adjl.vexnum; j++){ /*初始化,所有点都未访问*/ visited[j]=0; } printf("%4c->", adjl.adjs[i-1].data); visited[i-1]=1; p=adjl.adjs[i-1].link; while(p!=cnull){ if(visited[(p->adjvex)-1]!=1){ DFS((p->adjvex),adjl); } p=p->next; } } void BFS(int i, adjlist adjl) /*广度优先搜索*/ { edgenode *p; int j; int visited[maxlen]; for(j=0; j<adjl.vexnum; j++){ /*初始化所有点*/ visited[j]=0; } initqueue(q); printf("%4c->", adjl.adjs[i-1].data); visited[i-1]=1; addqueue(q,i); while(!empty(q)){ i=delqueue(q); p=adjl.adjs[i-1].link; while(p!=cnull){ if(visited[(p->adjvex)-1]==0){ printf("%4c->", adjl.adjs[p->adjvex-1].data); visited[(p->adjvex)-1]=1; addqueue(q,p->adjvex); p=p->next; } } } } status initstack(stackstru *s) /*构造空栈*/ { s->top=0; return ok; } status push(stackstru *s, int x) /*入栈*/ { if(s->top==maxlen){ printf("the stack is overflow!\n"); }else{ s->top=s->top+1; s->stack[s->top]=x; } } status pop(stackstru *s) /*出栈*/ { int y; if(s->top==0){ printf("the stack is empty!\n"); }else{ y=s->stack[s->top]; s->top=s->top-1; } return y; } status stackempty(stackstru *s) /*判栈空*/ { if(s->top==0){ return (true); }else{ return (false); } } status topsort(adjlist adjl) /*拓扑排序*/ { int i, k, count; edgenode *p; printf("拓扑排序序列为:\n"); initstack(s); for(i=0; i<adjl.vexnum; i++){ if(adjl.adjs[i].id==0){ push(s, adjl.adjs[i].data); } } count=0; while(!stackempty(s)){ i=pop(s); printf("%4c->", adjl.adjs[i].data); ++count; for(p=adjl.adjs[i].link; p; p=p->next){ k=p->adjvex; if(!(--adjl.adjs[k-1].id)){ push(s,k-1); } } } if(count<adjl.vexnum){ printf("\n网中有环!\n"); /*拓扑排序输出的顶点数<图中的顶点数*/ return error; }else{ return ok; } } void prim(graph g) /*最小生成树*/ { int i, j, k, min; int lowcost[maxlen]; /*权值*/ int closet[maxlen]; /*最小生成树结点*/ printf("最小生成树的边为:\n"); for(i=1; i<g.vexnum; i++){ lowcost[i]=g.arcs[0][i]; closet[i]=1; } closet[1]=0; j=1; for(i=1; i<g.vexnum; i++){ min=lowcost[j]; k=i; for(j=1; j<g.vexnum; j++){ if(lowcost[j]<min&&closet[j]!=0){ min=lowcost[j]; k=j; } } printf("(%c,%c),", g.vexs[k-1], g.vexs[closet[k-1]]); closet[k]=0; for(j=1; j<g.vexnum; j++){ if(g.acrs[k][j]<lowcost[j]&&closet[j]!=0){ lowcost[j]=g.arcs[k][j]; closet[j]=k; } } } } void shortpath_floyd(graph g) /*最短路径*/ { int path[maxlen][maxlen]; int short3[maxlen][maxlen]; /*权值*/ int i, j, k; for(i=0; i<g.vexnum; i++){ for(j=0; j<g.vexnum; j++){ short3[i][j]=g.arcs[i][j]; path[i][j]=0; } } printf("\n各顶点间的最短路径为:\n"); for(k=0; k<g.vexnum; k++){ for(i=0; i<g.vexnum; i++){ for(j=0; j<g.vexnum; j++){ if(short3[i][j]>(short3[i][k]+short3[k][j])){ short3[i][j]=short3[i][k]+short3[k][j]; path[i][j]=k; } printf("(%4c->%4c):%d", g.vexs[i-1], g.vexs[j-1], short3[i][j]); } } } } main() { int a, i, j, k, h; printf("\n请输入图的类型(1:有向图 2:无向图 3:有向网 4:无向网):"); scanf("%d",&i); g.kind=i; adjl.kind=i; printf("请输入顶点数,边数:"); scanf("%d,%d",&i,&j); g.vexnum=i; adjl.vexnum=i; g.arcnum=j; adjl.arcnum=j; for(i=0; i<g.vexnum; i++){ printf("第%d个顶点的信息:",i+1); scanf("%s",&g.vexs[i]); adjl.adjs[i].data=g.vexs[i]; adjl.adjs[i].link=cnull; adjl.adjs[i].id=0; } for(k=1; k<=g.arcnum; k++){ label:if(g.kind==1||g.kind==3){ printf("第%d条边的起点编号,终点编号:",k); }else{ printf("第%d条边两个顶点的编号:",k); } scanf("%d,%d",&i,&j); g.a[k-1]=i; g.b[k-1]=j; while(i<1||i>g.vexnum||j<1||j>g.vexnum){ printf("编号超出范围,重新输入"); goto label; /*老实说,此处用goto语句有点不符规范(一 一+)*/ } if(g.kind==3||g.kind==4){ printf("\t该边的权值:"); scanf("%d",&h); g.h[k-1]=h; }else{ g.h[k-1]=null; } adjl.adjs[i].id++; } loop:printf("\n1_邻接矩阵\n"); printf("2_邻接表\n"); printf("3_深度优先搜索\n"); printf("4_广度优先搜索\n"); printf("5_最小生成树\n"); printf("6_拓扑排序\n"); printf("请选择图的实现:\t"); sacnf("%d",&a); switch(a) { case 1: creategraph(g); break; case 2: createlist(g,adjl); break; case 3: printf("请输入出发点编号:"); sacnf("%d",&k); createlist(g,adjl); printf("\n从第%d点出发深度优先搜索遍历序列:",k); DFS(k,adjl);break; case 4: printf("请输入出发点编号:"); sacnf("%d",&k); createlist(g,adjl); printf("\n从第%d点出发广度优先搜索遍历序列:",k); BFS(k,adjl);break; case 5: if(g.kind==4){ create_4(g); prim(g); }else{ printf("\t不能构造最小生成树,请重新选择:\n"); goto loop; } break; case 6: if(g.kind==1||g.kind==3){ createlist(g,adjl); topsort(adjl); }else{ printf("\t不能拓扑排序,请重新选择:\n"); goto loop; } break; default: printf("\n\t *** wrong ***\n"); } }