图
//图 //储存结构:邻接矩阵 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include "queue.cpp" using namespace std; #define INF 1000000 #define MAX_NAME 12 #define MAX_INFO 26 #define MAX_VERTEX_NUM 26 enum GraphKind{DG,DN,UDG,UDN}; typedef int VRType; typedef char VertexType[12]; bool vis[MAX_VERTEX_NUM]; typedef struct { VRType adj; //顶点关系类型。 //InfoType *info; //该弧相关信息指针 }ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; struct MGraph { VertexType vexs[MAX_VERTEX_NUM]; //顶点向量 AdjMatrix arcs; //邻接矩阵 int vexnum,arcnum;//顶点数,弧数 GraphKind kind;//图的种类标志 }; int LocateVex(MGraph G, VertexType u) { //初始条件:图G存在,u和G中顶点有相同特征 //操作结构:若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 int i; for(i = 0; i < G.vexnum; i++){ if(strcmp(u,G.vexs[i]) == 0) return i; } return -1; } void Degree(MGraph G) { //求顶点的度 VertexType u; int ans = 0; printf("请输入相应顶点,来计算该顶点的度:"); scanf("%s",u); int i = LocateVex(G,u); if(i == -1){ printf("该顶点不存在\n"); } else{ for(int k = 0; k < G.vexnum; k++){ if(G.arcs[i][k].adj){ ans++; } if(G.arcs[k][i].adj && G.kind == DG){ ans++; } } printf("Degree:%d\n",ans); } } int FirstAdjVex(MGraph G,VertexType v) { //返回v的第一个邻接顶点的序号。若顶点在G中没有邻接顶点,返回-1 int i,j = 0,k; k = LocateVex(G,v); //if(G.kind % 2){ ////网 //j = INFINITY; //} for(i = 0; i < G.vexnum; i++){ if(G.arcs[k][i].adj != j){ return i; } } return -1; } int NextAdjVex(MGraph G,VertexType v,VertexType w) { //返回v的(相对于w)下一个邻接顶点的序号,若w是v的最后一个邻接顶点,则返回-1 int i,j = 0,k1,k2; k1 = LocateVex(G,v); k2 = LocateVex(G,w); //if(G.kind % 2){ ////网 //j = INFINITY; //} for(i = k2 + 1; i < G.vexnum; i++){ if(G.arcs[k1][i].adj != j){ return i; } } return -1; } void DFS(MGraph G,int v) //深度优先搜索 { int w; vis[v] = true; printf("%s ",G.vexs[v]); w = FirstAdjVex(G,G.vexs[v]); while(w >= 0){ if(!vis[w]){ DFS(G,w); } w = NextAdjVex(G,G.vexs[v],G.vexs[w]); } } void DFSTraverse(MGraph G) { int v; memset(vis,false,sizeof(vis)); for(v = 0; v < G.vexnum; v++){ if(!vis[v]){ DFS(G,v); } } printf("\n"); } void BFSTraverse(MGraph G) { int v,u,w; LinkQueue Q; InitQueue(Q); memset(vis,false,sizeof(vis)); for(v = 0; v < G.vexnum; v++){ //如果是连通图,v = 0就遍历全图 if(!vis[v]){ vis[v] = true; printf("%s ",G.vexs[v]); } EnQueue(Q,v); while(!QueueEmpty(Q)){ DeQueue(Q,u); w = FirstAdjVex(G,G.vexs[u]); while(w >= 0){ if(!vis[w]){ vis[w] = true; printf("%s ",G.vexs[w]); EnQueue(Q,w); } w = NextAdjVex(G,G.vexs[u],G.vexs[w]); } } } printf("\n"); } void CreateUDG(MGraph &G) //构造无向图 { int i,j,k,l;//IncInfo; char s[MAX_INFO]; VertexType va,vb; printf("请输入无向图G的顶点数,边数。\n"); scanf("%d%d",&G.vexnum,&G.arcnum); printf("请输入%d个顶点的值(小于%d个字符):\n",G.vexnum,MAX_NAME); for(i = 0; i < G.vexnum; i++){ scanf("%s",G.vexs[i]); } for(i = 0; i < G.vexnum; i++){ for(j = 0; j < G.vexnum; j++){ G.arcs[i][j].adj = 0; //G.arcs[i][j].info = NULL; } } printf("请输入%d条边的顶点1,顶点2:\n",G.arcnum); for(k = 0; k < G.arcnum; k++){ printf("Case %d:",k + 1); scanf("%s %s",va,vb); i = LocateVex(G,va); j = LocateVex(G,vb); G.arcs[i][j].adj = G.arcs[j][i].adj = 1; //if(IncoInfo){} } G.kind = UDG; } void CreateDG(MGraph &G) //构造有向图 { int i,j,k,l;//IncInfo; char s[MAX_INFO]; VertexType va,vb; printf("请输入有向图G的顶点数,边数。\n"); scanf("%d%d",&G.vexnum,&G.arcnum); printf("请输入%d个顶点的值(小于%d个字符):\n",G.vexnum,MAX_NAME); for(i = 0; i < G.vexnum; i++){ scanf("%s",G.vexs[i]); } for(i = 0; i < G.vexnum; i++){ for(j = 0; j < G.vexnum; j++){ G.arcs[i][j].adj = 0; //G.arcs[i][j].info = NULL; } } printf("请输入每条弧的弧尾和弧头:\n"); for(k = 0; k < G.arcnum; k++){ printf("Case %d:",k + 1); scanf("%s %s",va,vb); i = LocateVex(G,va); j = LocateVex(G,vb); G.arcs[i][j].adj = 1; //if(IncoInfo){} } G.kind = DG; } void Prt(MGraph G){ int i,j; printf("vexnum :%d, arcnum :%d.\n\n",G.vexnum,G.arcnum); printf("Vexlist:\n"); for(i = 0; i < G.vexnum; i++){ printf(" v(%d):%s\n",i,G.vexs[i]); } //Matrix printf("\nMatrix:\n "); for(i = 0; i < G.vexnum; i++){ printf("(%d) ",i); } printf("\n"); for(i = 0; i < G.vexnum; i++){ printf("(%d) ",i); for(j = 0; j < G.vexnum; j++){ printf("%d ",G.arcs[i][j].adj); } printf("\n"); } } int main() { MGraph G; //CreateDG(G);//创建有向图 CreateUDG(G); //创建无向图 Prt(G); //Degree(G); //DFSTraverse(G); BFSTraverse(G); return 0; }
//图 //储存方式:邻接表 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include "queue.cpp" using namespace std; #define MAX_NAME 12 #define MAX_INFO 20 #define MAX_VERTEX_NUM 20 int deg[MAX_VERTEX_NUM]; //存各顶点度 bool vis[MAX_VERTEX_NUM]; //dfs遍历标记 enum GraphKind{DG,DN,UDG,UDN}; typedef char VertexType[12]; struct ArcNode { int adjvex; //该弧所指向的顶点的位置 ArcNode *nextarc; //指向下一条弧的指针 //InfoType *info; //网的权值指针 };//表节点 typedef struct { VertexType data; //顶点信息 ArcNode *firstarc; //第一个表节点的地址,指向第一条依附该顶点的弧指针 }VNode,AdjList[MAX_VERTEX_NUM]; //头节点 struct ALGraph { AdjList vertices; int vexnum,arcnum; //图的当点顶点数和弧数 int kind; //图的种类标志 }; //返回u的顶点序号,若图中不含u,返回-1 int LocateVex(ALGraph G,VertexType u) { int i; for(i = 0; i < G.vexnum; i++){ if(strcmp(u,G.vertices[i].data) == 0) return i; } return -1; } //返回v的第一个邻接顶点的序号,若图中无邻接顶点,返回-1 int FirstAdjVex(ALGraph G,VertexType v){ int i = LocateVex(G,v); ArcNode *p = G.vertices[i].firstarc; if(p){ return p->adjvex; } else{ return -1; } } //返回v的(相对于w的)下一个邻接顶点的序号。若w是v的最后一个邻接顶点,则返回-1 int NextAdjVex(ALGraph G,VertexType v,VertexType w){ int i = LocateVex(G,v); int j = LocateVex(G,w); ArcNode *p = G.vertices[i].firstarc; while(p){ if(p->adjvex == j) break; p = p->nextarc; } if(!p || !p->nextarc){ //没找到w或w是最后一个邻接点 return -1; } else{ return (p->nextarc)->adjvex; } } void ListInsert(VNode &p,ArcNode e) //头插法 { ArcNode *q = (ArcNode *)malloc(sizeof(ArcNode)); q->adjvex = e.adjvex; q->nextarc = p.firstarc; p.firstarc = q; } //求图中各顶点的度 void Degree(ALGraph G){ int i; VertexType u; memset(deg,0,sizeof(deg)); for(i = 0; i < G.vexnum; i++){ ArcNode *p = G.vertices[i].firstarc; while(p){ deg[i]++; deg[p->adjvex]++; p = p->nextarc; } } printf("请输入相应顶点,来计算该顶点的度:"); scanf("%s",u); i = LocateVex(G,u); if(G.kind == UDG){ printf("Degree:%d\n",deg[i] / 2); } else{ printf("Degree:%d\n",deg[i]); } } //DG DN UDG UDN 有向图 有向网 无向图 无向网 //创建有向图 void CreateDG(ALGraph &G){ int i,j,k; VertexType va,vb; ArcNode e; printf("-----建立有向图-----\n"); printf("请输入图的顶点数,边数:"); scanf("%d%d",&G.vexnum,&G.arcnum); printf("请输入%d个顶点的值(小于%d个字符):\n",G.vexnum,MAX_NAME); for(i = 0; i < G.vexnum; i++){ scanf("%s",G.vertices[i].data); G.vertices[i].firstarc = NULL; } printf("请输入每条弧的弧尾和弧头:\n"); for(k = 0; k < G.arcnum; k++){ printf("Case %d:",k + 1); scanf("%s%s",va,vb); i = LocateVex(G,va); j = LocateVex(G,vb); //e.info = NULL; //图无权 e.adjvex = j; ListInsert(G.vertices[i],e); } G.kind = DG; } //创建无向图 void CreateUDN(ALGraph &G){ int i,j,k; VertexType va,vb; ArcNode e; printf("-----建立无向图-----\n"); printf("请输入图的顶点数,边数:"); scanf("%d%d",&G.vexnum,&G.arcnum); printf("请输入%d个顶点的值(小于%d个字符):\n",G.vexnum,MAX_NAME); for(i = 0; i < G.vexnum; i++){ scanf("%s",G.vertices[i].data); G.vertices[i].firstarc = NULL; } printf("请输入每条弧的两个顶点:\n"); for(k = 0; k < G.arcnum; k++){ printf("Case %d:",k + 1); scanf("%s%s",va,vb); i = LocateVex(G,va); j = LocateVex(G,vb); //e.info = NULL; //图无权 e.adjvex = i; ListInsert(G.vertices[j],e); e.adjvex = j; ListInsert(G.vertices[i],e); } G.kind = UDG; } //深度优先搜索 void DFS(ALGraph G,int v){ int w; vis[v] = true; printf("%s ",G.vertices[v].data); //访问第v个顶点 w = FirstAdjVex(G,G.vertices[v].data); while(w >= 0){ if(!vis[w]){ DFS(G,w); } w = NextAdjVex(G,G.vertices[v].data,G.vertices[w].data); } //for(w = FirstAdjVex(G,G.vertices[v].data); w >= 0; w = NextAdjVex(G,G.vertices[v].data,G.vertices[w].data));{ //if(!vis[w]){ //DFS(G,w); //} //} } //对图做深度优先遍历 void DFSTraverse(ALGraph G){ int v; memset(vis,false,sizeof(vis)); for(v = 0; v < G.vexnum; v++){ if(!vis[v]){ DFS(G,v);//对尚未访问的顶点调用DFS } } printf("\n"); } //对图做广度优先搜索 void BFSTraverse(ALGraph G) { int v,u,w; LinkQueue Q; InitQueue(Q); memset(vis,false,sizeof(vis)); for(v = 0; v < G.vexnum; v++){ //如果是连通图,v = 0就遍历全图 if(!vis[v]){ vis[v] = true; printf("%s ",G.vertices[v].data); } EnQueue(Q,v); while(!QueueEmpty(Q)){ DeQueue(Q,u); //队头元素出队,并置为u w = FirstAdjVex(G,G.vertices[u].data); while(w >= 0){ if(!vis[w]){ vis[w] = true; printf("%s ",G.vertices[w].data); EnQueue(Q,w);//入队 } w = NextAdjVex(G,G.vertices[u].data,G.vertices[w].data); } } } printf("\n"); } //打印该图的储存形式 void Prt(ALGraph G) { int i; printf("vexnum :%d, arcnum :%d.\n\n",G.vexnum,G.arcnum); printf("VexList:\n"); for(i = 0; i < G.vexnum; i++){ printf(" v(%d):%s|",i,G.vertices[i].data); ArcNode *p = G.vertices[i].firstarc; while(p){ printf("->%d",p->adjvex); p = p->nextarc; } printf("\n"); } } int main() { ALGraph G; //CreateDG(G); //建立有向图 CreateUDN(G); //建立无向图 Prt(G); //Degree(G); //DFSTraverse(G); BFSTraverse(G); return 0; }
//图 //储存结构:邻接矩阵 //功能:prim算法求最小生成树 #define INF 1000000 #define MAX_NAME 12 #define MAX_INFO 26 #define MAX_VERTEX_NUM 26 enum GraphKind {DG,DN,UDG,UDN}; typedef int VRType; //typedef char VertexType[12]; typedef int VertexType; typedef struct { VRType adj; //顶点关系类型。 //InfoType *info; //该弧相关信息指针 } ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; struct MGraph { VertexType vexs[MAX_VERTEX_NUM]; //顶点向量 AdjMatrix arcs; //邻接矩阵 int vexnum,arcnum;//顶点数,弧数 GraphKind kind;//图的种类标志 }; //记录从顶点集U到V-U的代价最小的边的辅助数组定义 typedef struct { VertexType adjvex; VRType lowcost; } mid,minside[MAX_VERTEX_NUM]; int LocateVex(MGraph G, VertexType u) { //初始条件:图G存在,u和G中顶点有相同特征 //操作结构:若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 int i; for(i = 0; i < G.vexnum; i++) { //if(strcmp(u,G.vexs[i]) == 0) if(u == G.vexs[i]) return i; } return -1; } //求SZ.lowcost的最小正值,并返回其在SZ中的序号 int minimum(minside SZ,MGraph G) { int i = 0,j,k,min; while(!SZ[i].lowcost) { i++; } min = SZ[i].lowcost; k = i; for(j = i + 1; j < G.vexnum; j++) { if(SZ[j].lowcost > 0 && min > SZ[j].lowcost) { min = SZ[j].lowcost; k = j; } } return k; } void MiniSpanTree_PRIM(MGraph G,VertexType u) { int i,j,k,ans = 0; minside closedge; k = LocateVex(G,u); for(j = 0; j < G.vexnum; ++j) { //strcpy(closedge[j].adjvex,u); closedge[j].adjvex = u; closedge[j].lowcost = G.arcs[k][j].adj; } closedge[k].lowcost = 0; //printf("最小生成树的各条边为\n"); int p,q; for(i = 1; i < G.vexnum; ++i) { k = minimum(closedge,G); //printf("(%d-%d)\n",closedge[k].adjvex,G.vexs[k]); p = closedge[k].adjvex - 1; q = G.vexs[k] - 1; ans += G.arcs[p][q].adj; closedge[k].lowcost = 0; for(j = 0; j < G.vexnum; ++j) { if(G.arcs[k][j].adj < closedge[j].lowcost) { //strcpy(closedge[j].adjvex,G.vexs[k]); closedge[j].adjvex = G.vexs[k]; closedge[j].lowcost = G.arcs[k][j].adj; } } } printf("%d\n",ans); } //构建无向网,n个顶点,m条边 void CreateUDG(MGraph &G,int n,int m) { int i,j,k,l;//IncInfo; char s[MAX_INFO]; VertexType va,vb; //printf("请输入无向图G的顶点数,边数。\n"); //scanf("%d%d",&G.vexnum,&G.arcnum); G.vexnum = n; G.arcnum = m; //printf("请输入%d个顶点的值(小于%d个字符):\n",G.vexnum,MAX_NAME); for(i = 0; i < G.vexnum; i++) { G.vexs[i] = i + 1; //scanf("%s",G.vexs[i]); } for(i = 0; i < G.vexnum; i++) { for(j = 0; j < G.vexnum; j++) { G.arcs[i][j].adj = INF; } } //printf("请输入%d条边的顶点1,顶点2:\n",G.arcnum); for(k = 0; k < G.arcnum; k++) { //printf("Case %d:",k + 1); scanf("%d %d %d",&va,&vb,&l); i = LocateVex(G,va); j = LocateVex(G,vb); G.arcs[i][j].adj = G.arcs[j][i].adj = l; } G.kind = UDG; } int main() { int n,m; MGraph G; while(scanf("%d%d",&n,&m) != EOF){ CreateUDG(G,n,m); //创建无向图 //Prt(G); MiniSpanTree_PRIM(G,G.vexs[0]); } return 0; }
//图 //储存结构:邻接矩阵 //功能:Dijkstra算法求最短路 enum GraphKind {DG,DN,UDG,UDN}; typedef int VRType; //typedef char VertexType[12]; typedef int VertexType; typedef int PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //路径矩阵 typedef int ShortPathTable[MAX_VERTEX_NUM]; //最短距离表 typedef struct { VRType adj; //顶点关系类型。 //InfoType *info; //该弧相关信息指针 } ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; struct MGraph { VertexType vexs[MAX_VERTEX_NUM]; //顶点向量 AdjMatrix arcs; //邻接矩阵 int vexnum,arcnum;//顶点数,弧数 GraphKind kind;//图的种类标志 }; int LocateVex(MGraph G, VertexType u) { //初始条件:图G存在,u和G中顶点有相同特征 //操作结构:若G中存在顶点u,则返回该顶点在图中位置;否则返回-1 int i; for(i = 0; i < G.vexnum; i++) { //if(strcmp(u,G.vexs[i]) == 0) if(u == G.vexs[i]) return i; } return -1; } void ShortestPath_DIJ(MGraph G,int v0,PathMatrix P,ShortPathTable D) { int v,w,i,j,min; int final[MAX_VERTEX_NUM]; for(v = 0; v < G.vexnum; ++v){ final[v] = FALSE; D[v] = G.arcs[v0][v].adj; for(w = 0; w < G.vexnum; ++w) P[v][w] = FALSE; if(D[v] < INF) P[v][v0] = P[v][v] = TRUE; } D[v0] = 0; final[v0] = TRUE; for(i = 1; i < G.vexnum; ++i){ min = INF; for(w = 0; w < G.vexnum; ++w){ if(!final[w] && D[w] < min){ v = w; min = D[w]; } } final[v] = TRUE; for(w = 0; w < G.vexnum; ++w){ if(!final[w] && min < INF && G.arcs[v][w].adj < INF && (min + G.arcs[v][w].adj < D[w])) { D[w] = min + G.arcs[v][w].adj; for(j = 0; j < G.vexnum; ++j) P[w][j] = P[v][j]; P[w][w] = TRUE; } } } } //构建无向网,n个顶点,m条边 void CreateUDG(MGraph &G,int n,int m) { int i,j,k,l;//IncInfo; char s[MAX_INFO]; VertexType va,vb; //printf("请输入无向图G的顶点数,边数。\n"); //scanf("%d%d",&G.vexnum,&G.arcnum); G.vexnum = n; G.arcnum = m; //printf("请输入%d个顶点的值(小于%d个字符):\n",G.vexnum,MAX_NAME); for(i = 0; i < G.vexnum; i++) { G.vexs[i] = i + 1; //scanf("%s",G.vexs[i]); } for(i = 0; i < G.vexnum; i++) { for(j = 0; j < G.vexnum; j++) { G.arcs[i][j].adj = INF; } } //printf("请输入%d条边的顶点1,顶点2:\n",G.arcnum); for(k = 0; k < G.arcnum; k++) { //printf("Case %d:",k + 1); scanf("%d %d %d",&va,&vb,&l); i = LocateVex(G,va); j = LocateVex(G,vb); G.arcs[i][j].adj = G.arcs[j][i].adj = l; } G.kind = UDG; } int main() { int n,m; MGraph G; PathMatrix p; ShortPathTable d; while(scanf("%d%d",&n,&m) != EOF){ memset(p,0,sizeof(p)); memset(d,0,sizeof(d)); CreateUDG(G,n,m); //创建无向图 ShortestPath_DIJ(G,0,p,d); printf("%d\n",d[n - 1]); } return 0; }
//图 //存储方式:邻接表 //功能:拓扑排序,判断是否存在回路 //存储各顶点入度 int indegree[MAX_VERTEX_NUM]; enum GraphKind{DG,DN,UDG,UDN}; typedef char VertexType[12]; struct ArcNode { int adjvex; //该弧所指向的顶点的位置 ArcNode *nextarc; //指向下一条弧的指针 //InfoType *info; //网的权值指针 };//表节点 typedef struct { VertexType data; //顶点信息 ArcNode *firstarc; //第一个表节点的地址,指向第一条依附该顶点的弧指针 }VNode,AdjList[MAX_VERTEX_NUM]; //头节点 struct ALGraph { AdjList vertices; int vexnum,arcnum; //图的当点顶点数和弧数 int kind; //图的种类标志 }; //返回u的顶点序号,若图中不含u,返回-1 int LocateVex(ALGraph G,VertexType u) { int i; for(i = 0; i < G.vexnum; i++){ if(strcmp(u,G.vertices[i].data) == 0) return i; } return -1; } void ListInsert(VNode &p,ArcNode e) //头插法 { ArcNode *q = (ArcNode *)malloc(sizeof(ArcNode)); q->adjvex = e.adjvex; q->nextarc = p.firstarc; p.firstarc = q; } //创建有向图 void CreateDG(ALGraph &G){ int i,j,k; VertexType va,vb; ArcNode e; printf("-----建立有向图-----\n"); printf("请输入图的顶点数,边数:"); scanf("%d%d",&G.vexnum,&G.arcnum); printf("请输入%d个顶点的值(小于%d个字符):\n",G.vexnum,MAX_NAME); for(i = 0; i < G.vexnum; i++){ scanf("%s",G.vertices[i].data); G.vertices[i].firstarc = NULL; } printf("请输入每条弧的弧尾和弧头:\n"); for(k = 0; k < G.arcnum; k++){ printf("Case %d:",k + 1); scanf("%s%s",va,vb); i = LocateVex(G,va); j = LocateVex(G,vb); //e.info = NULL; //图无权 e.adjvex = j; ListInsert(G.vertices[i],e); } G.kind = DG; } //求图中各顶点入度,并存在indegree数组中 void FindInDegree(ALGraph G) { int i; memset(indegree,0,sizeof(indegree)); for(i = 0; i < G.vexnum; i++){ ArcNode *p = G.vertices[i].firstarc; while(p){ indegree[p->adjvex]++; p = p->nextarc; } } } //有向图G采用邻接表存储结构 //若G无回路,则输出G的顶点的拓扑序列并返回true,否则返回false bool TopologicalSort(ALGraph G) { int i,k; FindInDegree(G); //对各顶点求入度 stack<int>s; //0入度顶点栈 for(i = 0; i < G.vexnum; ++i){ if(!indegree[i]) //入度为0 s.push(i); } ArcNode *p; int count = 0;//对输出顶点计数 while(!s.empty()){ i =s.top(); s.pop(); printf("%d %s\n",i,G.vertices[i].data); count++;//输出i号顶点,并计数 for(p = G.vertices[i].firstarc; p; p = p->nextarc){ k = p->adjvex; //对i号顶点的每个邻接点的入度减1 if(!(--indegree[k])) s.push(k); //若入度减为0,则入栈 } } if(count < G.vexnum) return false; //该图有回路 else return true; //该图无回路 } int main() { ALGraph G; CreateDG(G);//创建有向图 if(TopologicalSort(G)) printf("无回路\n"); else printf("有回路\n"); return 0; }