数据结构 图论

来源:互联网 发布:java action是什么 编辑:程序博客网 时间:2024/06/17 01:24


1.邻接矩阵的创建

#include<stdio.h> #define MAXVEX 100 /* 最大顶点数,应由用户定义 */#define INFINITY -1typedef char VertexType; /* 顶点类型应由用户定义  */typedef int EdgeType; /* 边上的权值类型应由用户定义 */typedef struct{VertexType vexs[MAXVEX]; /* 顶点表 */EdgeType arc[MAXVEX][MAXVEX];/* 邻接矩阵,可看作边表 */int numNodes, numEdges; /* 图中当前的顶点数和边数  */}MGraph;/* 建立无向网图的邻接矩阵表示 */void CreateMGraph(MGraph *G){int i,j,k,w;printf("输入顶点数和边数:\n");scanf("%d%d",&G->numNodes,&G->numEdges); /* 输入顶点数和边数 */for(i = 0;i < G->numNodes;i++) /* 读入顶点信息,建立顶点表 */scanf(&G->vexs[i]);for(i = 0;i < G->numNodes;i++)for(j = 0;j < G->numNodes;j++)G->arc[i][j]=INFINITY;/* 邻接矩阵初始化 */for(k = 0;k < G->numEdges;k++) /* 读入numEdges条边,建立邻接矩阵 */{printf("输入边(vi,vj)上的下标i,下标j和权w:\n");scanf("%d%d%d",&i,&j,&w); /* 输入边(vi,vj)上的权w */G->arc[i][j]=w; G->arc[j][i]= G->arc[i][j]; /* 因为是无向图,矩阵对称 */}printf("输出形成的邻接矩阵:\n");for(i = 0; i < G->numNodes; i++){for(j = 0; j < G->numNodes; j++){printf("%3d",G->arc[i][j]);}printf("\n");}}int main(void){    MGraph G;    CreateMGraph(&G);return 0;}

2.邻接表的创建

#include<stdio.h>#define MAXVEX 100 /* 最大顶点数,应由用户定义 */typedef char VertexType; /* 顶点类型应由用户定义 */typedef int EdgeType; /* 边上的权值类型应由用户定义 */typedef struct EdgeNode /* 边表结点  */{int adjvex;    /* 邻接点域,存储该顶点对应的下标 */EdgeType info;/* 用于存储权值,对于非网图可以不需要 */struct EdgeNode *next; /* 链域,指向下一个邻接点 */}EdgeNode;typedef struct VertexNode /* 顶点表结点 */{VertexType data; /* 顶点域,存储顶点信息 */EdgeNode *firstedge;/* 边表头指针 */}VertexNode, AdjList[MAXVEX];typedef struct{AdjList adjList; int numNodes,numEdges; /* 图中当前顶点数和边数 */}GraphAdjList;/* 建立图的邻接表结构 */void  CreateALGraph(GraphAdjList *G){int i,j,k;EdgeNode *e;printf("输入顶点数和边数:\n");scanf("%d,%d",&G->numNodes,&G->numEdges); /* 输入顶点数和边数 */for(i = 0;i < G->numNodes;i++) /* 读入顶点信息,建立顶点表 */{scanf(&G->adjList[i].data); /* 输入顶点信息 */G->adjList[i].firstedge=NULL; /* 将边表置为空表 */}for(k = 0;k < G->numEdges;k++)/* 建立边表 */{printf("输入边(vi,vj)上的顶点序号:\n");scanf("%d%d",&i,&j); /* 输入边(vi,vj)上的顶点序号 */e=(EdgeNode *)malloc(sizeof(EdgeNode)); /* 向内存申请空间,生成边表结点 */e->adjvex=j;/* 邻接序号为j */                         e->next=G->adjList[i].firstedge;/* 将e的指针指向当前顶点上指向的结点 */G->adjList[i].firstedge=e;/* 将当前顶点的指针指向e */               e=(EdgeNode *)malloc(sizeof(EdgeNode)); /* 向内存申请空间,生成边表结点 */e->adjvex=i;/* 邻接序号为i */                         e->next=G->adjList[j].firstedge;/* 将e的指针指向当前顶点上指向的结点 */G->adjList[j].firstedge=e;/* 将当前顶点的指针指向e */               }}int main(void){    GraphAdjList G;    CreateALGraph(&G);return 0;}

3.邻接矩阵—深度遍历和广度遍历

#include "stdio.h"    #include "stdlib.h"   #include "io.h"  #include "math.h"  #include "time.h"#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */  typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */typedef char VertexType; /* 顶点类型应由用户定义 */typedef int EdgeType; /* 边上的权值类型应由用户定义 */#define MAXSIZE 9 /* 存储空间初始分配量 */#define MAXEDGE 15#define MAXVEX 9#define INFINITY 65535typedef struct{VertexType vexs[MAXVEX]; /* 顶点表 */EdgeType arc[MAXVEX][MAXVEX];/* 邻接矩阵,可看作边表 */int numVertexes, numEdges; /* 图中当前的顶点数和边数 */ }MGraph;/* 用到的队列结构与函数********************************** *//* 循环队列的顺序存储结构 */typedef struct{int data[MAXSIZE];int front;    /* 头指针 */int rear;/* 尾指针,若队列不空,指向队列尾元素的下一个位置 */}Queue;/* 初始化一个空队列Q */Status InitQueue(Queue *Q){Q->front=0;Q->rear=0;return  OK;}/* 若队列Q为空队列,则返回TRUE,否则返回FALSE */Status QueueEmpty(Queue Q){ if(Q.front==Q.rear) /* 队列空的标志 */return TRUE;elsereturn FALSE;}/* 若队列未满,则插入元素e为Q新的队尾元素 */Status EnQueue(Queue *Q,int e){if ((Q->rear+1)%MAXSIZE == Q->front)/* 队列满的判断 */return ERROR;Q->data[Q->rear]=e;/* 将元素e赋值给队尾 */Q->rear=(Q->rear+1)%MAXSIZE;/* rear指针向后移一位置, *//* 若到最后则转到数组头部 */return  OK;}/* 若队列不空,则删除Q中队头元素,用e返回其值 */Status DeQueue(Queue *Q,int *e){if (Q->front == Q->rear)/* 队列空的判断 */return ERROR;*e=Q->data[Q->front];/* 将队头元素赋值给e */Q->front=(Q->front+1)%MAXSIZE;/* front指针向后移一位置, *//* 若到最后则转到数组头部 */return  OK;}/* ****************************************************** */void CreateMGraph(MGraph *G){int i, j;G->numEdges=15;G->numVertexes=9;/* 读入顶点信息,建立顶点表 */G->vexs[0]='A';G->vexs[1]='B';G->vexs[2]='C';G->vexs[3]='D';G->vexs[4]='E';G->vexs[5]='F';G->vexs[6]='G';G->vexs[7]='H';G->vexs[8]='I';for (i = 0; i < G->numVertexes; i++)/* 初始化图 */{for ( j = 0; j < G->numVertexes; j++){G->arc[i][j]=0;}}G->arc[0][1]=1;G->arc[0][5]=1;G->arc[1][2]=1; G->arc[1][8]=1; G->arc[1][6]=1; G->arc[2][3]=1; G->arc[2][8]=1; G->arc[3][4]=1;G->arc[3][7]=1;G->arc[3][6]=1;G->arc[3][8]=1;G->arc[4][5]=1;G->arc[4][7]=1;G->arc[5][6]=1; G->arc[6][7]=1; for(i = 0; i < G->numVertexes; i++){for(j = i; j < G->numVertexes; j++){G->arc[j][i] =G->arc[i][j];}}for(i = 0; i < G->numVertexes; i++){for(j = 0; j < G->numVertexes; j++){printf("%d ",G->arc[i][j]); }printf("\n");}} Boolean visited[MAXVEX]; /* 访问标志的数组 *//* 邻接矩阵的深度优先递归算法 */void DFS(MGraph G, int i){int j; visited[i] = TRUE; printf("%c ", G.vexs[i]);/* 打印顶点,也可以其它操作 */for(j = 0; j < G.numVertexes; j++)if(G.arc[i][j] == 1 && !visited[j]) DFS(G, j);/* 对为访问的邻接顶点递归调用 */}/* 邻接矩阵的深度遍历操作 */void DFSTraverse(MGraph G){int i; for(i = 0; i < G.numVertexes; i++) visited[i] = FALSE; /* 初始所有顶点状态都是未访问过状态 */for(i = 0; i < G.numVertexes; i++) if(!visited[i]) /* 对未访问过的顶点调用DFS,若是连通图,只会执行一次 */ DFS(G, i);}/* 邻接矩阵的广度遍历算法 */void BFSTraverse(MGraph G){int i, j;Queue Q;for(i = 0; i < G.numVertexes; i++)       visited[i] = FALSE;    InitQueue(&Q);/* 初始化一辅助用的队列 */    for(i = 0; i < G.numVertexes; i++)  /* 对每一个顶点做循环 */    {if (!visited[i])/* 若是未访问过就处理 */{visited[i]=TRUE;/* 设置当前顶点访问过 */printf("%c ", G.vexs[i]);/* 打印顶点,也可以其它操作 */EnQueue(&Q,i);/* 将此顶点入队列 */while(!QueueEmpty(Q))/* 若当前队列不为空 */{DeQueue(&Q,&i);/* 将队对元素出队列,赋值给i */for(j=0;j<G.numVertexes;j++) { /* 判断其它顶点若与当前顶点存在边且未访问过  */if(G.arc[i][j] == 1 && !visited[j]) {  visited[j]=TRUE;/* 将找到的此顶点标记为已访问 */printf("%c ", G.vexs[j]);/* 打印顶点 */EnQueue(&Q,j);/* 将找到的此顶点入队列  */} } }}}}int main(void){    MGraph G;CreateMGraph(&G);printf("\n深度遍历:");DFSTraverse(G);printf("\n广度遍历:");BFSTraverse(G);return 0;}

4.邻接表—深度遍历和广度遍历

#include "stdio.h"    #include "stdlib.h"   #include "io.h"  #include "math.h"  #include "time.h"#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define MAXSIZE 9 /* 存储空间初始分配量 */#define MAXEDGE 15#define MAXVEX 9#define INFINITY 65535typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */typedef int Boolean; /* Boolean是布尔类型,其值是TRUE或FALSE */typedef char VertexType; /* 顶点类型应由用户定义 */   typedef int EdgeType; /* 边上的权值类型应由用户定义 *//* 邻接矩阵结构 */typedef struct{VertexType vexs[MAXVEX]; /* 顶点表 */EdgeType arc[MAXVEX][MAXVEX];/* 邻接矩阵,可看作边表 */int numVertexes, numEdges; /* 图中当前的顶点数和边数 */ }MGraph;/* 邻接表结构****************** */typedef struct EdgeNode /* 边表结点 */ {int adjvex;    /* 邻接点域,存储该顶点对应的下标 */int weight;/* 用于存储权值,对于非网图可以不需要 */struct EdgeNode *next; /* 链域,指向下一个邻接点 */ }EdgeNode;typedef struct VertexNode /* 顶点表结点 */ {int in;/* 顶点入度 */char data; /* 顶点域,存储顶点信息 */EdgeNode *firstedge;/* 边表头指针 */   }VertexNode, AdjList[MAXVEX];typedef struct{AdjList adjList; int numVertexes,numEdges; /* 图中当前顶点数和边数 */}graphAdjList,*GraphAdjList;/* **************************** *//* 用到的队列结构与函数********************************** *//* 循环队列的顺序存储结构 */typedef struct{int data[MAXSIZE];int front;    /* 头指针 */int rear;/* 尾指针,若队列不空,指向队列尾元素的下一个位置 */}Queue;/* 初始化一个空队列Q */Status InitQueue(Queue *Q){Q->front=0;Q->rear=0;return  OK;}/* 若队列Q为空队列,则返回TRUE,否则返回FALSE */Status QueueEmpty(Queue Q){ if(Q.front==Q.rear) /* 队列空的标志 */return TRUE;elsereturn FALSE;}/* 若队列未满,则插入元素e为Q新的队尾元素 */Status EnQueue(Queue *Q,int e){if ((Q->rear+1)%MAXSIZE == Q->front)/* 队列满的判断 */return ERROR;Q->data[Q->rear]=e;/* 将元素e赋值给队尾 */Q->rear=(Q->rear+1)%MAXSIZE;/* rear指针向后移一位置, *//* 若到最后则转到数组头部 */return  OK;}/* 若队列不空,则删除Q中队头元素,用e返回其值 */Status DeQueue(Queue *Q,int *e){if (Q->front == Q->rear)/* 队列空的判断 */return ERROR;*e=Q->data[Q->front];/* 将队头元素赋值给e */Q->front=(Q->front+1)%MAXSIZE;/* front指针向后移一位置, *//* 若到最后则转到数组头部 */return  OK;}/* ****************************************************** */void CreateMGraph(MGraph *G){int i, j;G->numEdges=15;G->numVertexes=9;/* 读入顶点信息,建立顶点表 */ G->vexs[0]='A';G->vexs[1]='B';G->vexs[2]='C';G->vexs[3]='D';G->vexs[4]='E';G->vexs[5]='F';G->vexs[6]='G';G->vexs[7]='H';G->vexs[8]='I';for (i = 0; i < G->numVertexes; i++)/* 初始化图 */{for ( j = 0; j < G->numVertexes; j++){G->arc[i][j]=0;}}G->arc[0][1]=1;G->arc[0][5]=1;G->arc[1][2]=1; G->arc[1][8]=1; G->arc[1][6]=1; G->arc[2][3]=1; G->arc[2][8]=1; G->arc[3][4]=1;G->arc[3][7]=1;G->arc[3][6]=1;G->arc[3][8]=1;G->arc[4][5]=1;G->arc[4][7]=1;G->arc[5][6]=1; G->arc[6][7]=1; for(i = 0; i < G->numVertexes; i++){for(j = i; j < G->numVertexes; j++){G->arc[j][i] =G->arc[i][j];}}} /* 利用邻接矩阵构建邻接表 */void CreateALGraph(MGraph G,GraphAdjList *GL){int i,j;EdgeNode *e;*GL = (GraphAdjList)malloc(sizeof(graphAdjList));(*GL)->numVertexes=G.numVertexes;(*GL)->numEdges=G.numEdges;for(i= 0;i <G.numVertexes;i++) /* 读入顶点信息,建立顶点表 */   {(*GL)->adjList[i].in=0;(*GL)->adjList[i].data=G.vexs[i];(*GL)->adjList[i].firstedge=NULL; /* 将边表置为空表 */}for(i=0;i<G.numVertexes;i++) /* 建立边表 */{ for(j=0;j<G.numVertexes;j++){if (G.arc[i][j]==1){e=(EdgeNode *)malloc(sizeof(EdgeNode));e->adjvex=j;/* 邻接序号为j */                         e->next=(*GL)->adjList[i].firstedge;/* 将当前顶点上的指向的结点指针赋值给e */(*GL)->adjList[i].firstedge=e;/* 将当前顶点的指针指向e */   (*GL)->adjList[j].in++;}}}}Boolean visited[MAXSIZE]; /* 访问标志的数组 *//* 邻接表的深度优先递归算法 */void DFS(GraphAdjList GL, int i){EdgeNode *p; visited[i] = TRUE; printf("%c ",GL->adjList[i].data);/* 打印顶点,也可以其它操作 */p = GL->adjList[i].firstedge;while(p){ if(!visited[p->adjvex]) DFS(GL, p->adjvex);/* 对为访问的邻接顶点递归调用 */p = p->next; }}/* 邻接表的深度遍历操作 */void DFSTraverse(GraphAdjList GL){int i; for(i = 0; i < GL->numVertexes; i++) visited[i] = FALSE; /* 初始所有顶点状态都是未访问过状态 */for(i = 0; i < GL->numVertexes; i++) if(!visited[i]) /* 对未访问过的顶点调用DFS,若是连通图,只会执行一次 */ DFS(GL, i);}/* 邻接表的广度遍历算法 */void BFSTraverse(GraphAdjList GL){int i;    EdgeNode *p;Queue Q;for(i = 0; i < GL->numVertexes; i++)       visited[i] = FALSE;    InitQueue(&Q);   for(i = 0; i < GL->numVertexes; i++)   {if (!visited[i]){visited[i]=TRUE;printf("%c ",GL->adjList[i].data);/* 打印顶点,也可以其它操作 */EnQueue(&Q,i);while(!QueueEmpty(Q)){DeQueue(&Q,&i);p = GL->adjList[i].firstedge;/* 找到当前顶点的边表链表头指针 */while(p){if(!visited[p->adjvex])/* 若此顶点未被访问 */ { visited[p->adjvex]=TRUE;printf("%c ",GL->adjList[p->adjvex].data);EnQueue(&Q,p->adjvex);/* 将此顶点入队列 */}p = p->next;/* 指针指向下一个邻接点 */}}}}}int main(void){    MGraph G;  GraphAdjList GL;    CreateMGraph(&G);CreateALGraph(G,&GL);printf("\n深度遍历:");DFSTraverse(GL);printf("\n广度遍历:");BFSTraverse(GL);return 0;}
5.最小生成树—Prim

#include "stdio.h"    #include "stdlib.h"   #include "io.h"  #include "math.h"  #include "time.h"#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define MAXEDGE 20#define MAXVEX 20#define INFINITY 65535typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */typedef struct{int arc[MAXVEX][MAXVEX];int numVertexes, numEdges;}MGraph;void CreateMGraph(MGraph *G)/* 构件图 */{int i, j;/* printf("请输入边数和顶点数:"); */G->numEdges=15;G->numVertexes=9;for (i = 0; i < G->numVertexes; i++)/* 初始化图 */{for ( j = 0; j < G->numVertexes; j++){if (i==j)G->arc[i][j]=0;elseG->arc[i][j] = G->arc[j][i] = INFINITY;}}G->arc[0][1]=10;G->arc[0][5]=11; G->arc[1][2]=18; G->arc[1][8]=12; G->arc[1][6]=16; G->arc[2][8]=8; G->arc[2][3]=22; G->arc[3][8]=21; G->arc[3][6]=24; G->arc[3][7]=16;G->arc[3][4]=20;G->arc[4][7]=7; G->arc[4][5]=26; G->arc[5][6]=17; G->arc[6][7]=19; for(i = 0; i < G->numVertexes; i++){for(j = i; j < G->numVertexes; j++){G->arc[j][i] =G->arc[i][j];}}}/* Prim算法生成最小生成树  */void MiniSpanTree_Prim(MGraph G){int min, i, j, k;int adjvex[MAXVEX];/* 保存相关顶点下标 */int lowcost[MAXVEX];/* 保存相关顶点间边的权值 */lowcost[0] = 0;/* 初始化第一个权值为0,即v0加入生成树 *//* lowcost的值为0,在这里就是此下标的顶点已经加入生成树 */adjvex[0] = 0;/* 初始化第一个顶点下标为0 */for(i = 1; i < G.numVertexes; i++)/* 循环除下标为0外的全部顶点 */{lowcost[i] = G.arc[0][i];/* 将v0顶点与之有边的权值存入数组 */adjvex[i] = 0;/* 初始化都为v0的下标 */}for(i = 1; i < G.numVertexes; i++){min = INFINITY;/* 初始化最小权值为∞, *//* 通常设置为不可能的大数字如32767、65535等 */j = 1;k = 0;while(j < G.numVertexes)/* 循环全部顶点 */{if(lowcost[j]!=0 && lowcost[j] < min)/* 如果权值不为0且权值小于min */{min = lowcost[j];/* 则让当前权值成为最小值 */k = j;/* 将当前最小值的下标存入k */}j++;}printf("(%d, %d)\n", adjvex[k], k);/* 打印当前顶点边中权值最小的边 */lowcost[k] = 0;/* 将当前顶点的权值设置为0,表示此顶点已经完成任务 */for(j = 1; j < G.numVertexes; j++)/* 循环所有顶点 */{if(lowcost[j]!=0 && G.arc[k][j] < lowcost[j]) {/* 如果下标为k顶点各边权值小于此前这些顶点未被加入生成树权值 */lowcost[j] = G.arc[k][j];/* 将较小的权值存入lowcost相应位置 */adjvex[j] = k;/* 将下标为k的顶点存入adjvex */}}}}int main(void){MGraph G;CreateMGraph(&G);MiniSpanTree_Prim(G);  return 0; }
6.最小生成树—Kruskal

#include "stdio.h"    #include "stdlib.h"   #include "io.h"  #include "math.h"  #include "time.h"#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */#define MAXEDGE 20#define MAXVEX 20#define INFINITY 65535typedef struct{int arc[MAXVEX][MAXVEX];int numVertexes, numEdges;}MGraph;typedef struct{int begin;int end;int weight;}Edge;   /* 对边集数组Edge结构的定义 *//* 构件图 */void CreateMGraph(MGraph *G){int i, j;/* printf("请输入边数和顶点数:"); */G->numEdges=15;G->numVertexes=9;for (i = 0; i < G->numVertexes; i++)/* 初始化图 */{for ( j = 0; j < G->numVertexes; j++){if (i==j)G->arc[i][j]=0;elseG->arc[i][j] = G->arc[j][i] = INFINITY;}}G->arc[0][1]=10;G->arc[0][5]=11; G->arc[1][2]=18; G->arc[1][8]=12; G->arc[1][6]=16; G->arc[2][8]=8; G->arc[2][3]=22; G->arc[3][8]=21; G->arc[3][6]=24; G->arc[3][7]=16;G->arc[3][4]=20;G->arc[4][7]=7; G->arc[4][5]=26; G->arc[5][6]=17; G->arc[6][7]=19; for(i = 0; i < G->numVertexes; i++){for(j = i; j < G->numVertexes; j++){G->arc[j][i] =G->arc[i][j];}}}/* 交换权值 以及头和尾 */void Swapn(Edge *edges,int i, int j){int temp;temp = edges[i].begin;edges[i].begin = edges[j].begin;edges[j].begin = temp;temp = edges[i].end;edges[i].end = edges[j].end;edges[j].end = temp;temp = edges[i].weight;edges[i].weight = edges[j].weight;edges[j].weight = temp;}/* 对权值进行排序 */void sort(Edge edges[],MGraph *G){int i, j;for ( i = 0; i < G->numEdges; i++){for ( j = i + 1; j < G->numEdges; j++){if (edges[i].weight > edges[j].weight){Swapn(edges, i, j);}}}printf("权排序之后的为:\n");for (i = 0; i < G->numEdges; i++){printf("(%d, %d) %d\n", edges[i].begin, edges[i].end, edges[i].weight);}}/* 查找连线顶点的尾部下标 */int Find(int *parent, int f){while ( parent[f] > 0){f = parent[f];}return f;}/* 生成最小生成树 */void MiniSpanTree_Kruskal(MGraph G){int i, j, n, m;int k = 0;int parent[MAXVEX];/* 定义一数组用来判断边与边是否形成环路 */Edge edges[MAXEDGE];/* 定义边集数组,edge的结构为begin,end,weight,均为整型 *//* 用来构建边集数组并排序********************* */for ( i = 0; i < G.numVertexes-1; i++){for (j = i + 1; j < G.numVertexes; j++){if (G.arc[i][j]<INFINITY){edges[k].begin = i;edges[k].end = j;edges[k].weight = G.arc[i][j];k++;}}}sort(edges, &G);/* ******************************************* */for (i = 0; i < G.numVertexes; i++)parent[i] = 0;/* 初始化数组值为0 */printf("打印最小生成树:\n");for (i = 0; i < G.numEdges; i++)/* 循环每一条边 */{n = Find(parent,edges[i].begin);m = Find(parent,edges[i].end);if (n != m) /* 假如n与m不等,说明此边没有与现有的生成树形成环路 */{parent[n] = m;/* 将此边的结尾顶点放入下标为起点的parent中。 *//* 表示此顶点已经在生成树集合中 */printf("(%d, %d) %d\n", edges[i].begin, edges[i].end, edges[i].weight);}}}int main(void){MGraph G;CreateMGraph(&G);MiniSpanTree_Kruskal(G);return 0;}
7.最短路径—Dijkstra

#include "stdio.h"    #include "stdlib.h"   #include "io.h"  #include "math.h"  #include "time.h"#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define MAXEDGE 20#define MAXVEX 20#define INFINITY 65535typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */ typedef struct{int vexs[MAXVEX];int arc[MAXVEX][MAXVEX];int numVertexes, numEdges;}MGraph;typedef int Patharc[MAXVEX];    /* 用于存储最短路径下标的数组 */typedef int ShortPathTable[MAXVEX];/* 用于存储到各点最短路径的权值和 *//* 构件图 */void CreateMGraph(MGraph *G){int i, j;/* printf("请输入边数和顶点数:"); */G->numEdges=16;G->numVertexes=9;for (i = 0; i < G->numVertexes; i++)/* 初始化图 */{G->vexs[i]=i;}for (i = 0; i < G->numVertexes; i++)/* 初始化图 */{for ( j = 0; j < G->numVertexes; j++){if (i==j)G->arc[i][j]=0;elseG->arc[i][j] = G->arc[j][i] = INFINITY;}}G->arc[0][1]=1;G->arc[0][2]=5; G->arc[1][2]=3; G->arc[1][3]=7; G->arc[1][4]=5; G->arc[2][4]=1; G->arc[2][5]=7; G->arc[3][4]=2; G->arc[3][6]=3; G->arc[4][5]=3;G->arc[4][6]=6;G->arc[4][7]=9; G->arc[5][7]=5; G->arc[6][7]=2; G->arc[6][8]=7;G->arc[7][8]=4;for(i = 0; i < G->numVertexes; i++){for(j = i; j < G->numVertexes; j++){G->arc[j][i] =G->arc[i][j];}}}/*  Dijkstra算法,求有向网G的v0顶点到其余顶点v的最短路径P[v]及带权长度D[v] */    /*  P[v]的值为前驱顶点下标,D[v]表示v0到v的最短路径长度和 */  void ShortestPath_Dijkstra(MGraph G, int v0, Patharc *P, ShortPathTable *D){    int v,w,k,min;    int final[MAXVEX];/* final[w]=1表示求得顶点v0至vw的最短路径 */for(v=0; v<G.numVertexes; v++)    /* 初始化数据 */{        final[v] = 0;/* 全部顶点初始化为未知最短路径状态 */(*D)[v] = G.arc[v0][v];/* 将与v0点有连线的顶点加上权值 */(*P)[v] = 0;/* 初始化路径数组P为0  */       }(*D)[v0] = 0;  /* v0至v0路径为0 */  final[v0] = 1;    /* v0至v0不需要求路径 */        /* 开始主循环,每次求得v0到某个v顶点的最短路径 */   for(v=1; v<G.numVertexes; v++)   {min=INFINITY;    /* 当前所知离v0顶点的最近距离 */        for(w=0; w<G.numVertexes; w++) /* 寻找离v0最近的顶点 */    {            if(!final[w] && (*D)[w]<min)             {                   k=w;                    min = (*D)[w];    /* w顶点离v0顶点更近 */            }        }        final[k] = 1;    /* 将目前找到的最近的顶点置为1 */for(w=0; w<G.numVertexes; w++) /* 修正当前最短路径及距离 */{/* 如果经过v顶点的路径比现在这条路径的长度短的话 */if(!final[w] && (min+G.arc[k][w]<(*D)[w]))   { /*  说明找到了更短的路径,修改D[w]和P[w] */(*D)[w] = min + G.arc[k][w];  /* 修改当前路径长度 */               (*P)[w]=k;        }       }   }}int main(void){   int i,j,v0;MGraph G;    Patharc P;    ShortPathTable D; /* 求某点到其余各点的最短路径 */   v0=0;CreateMGraph(&G);ShortestPath_Dijkstra(G, v0, &P, &D);  printf("最短路径倒序如下:\n");    for(i=1;i<G.numVertexes;++i)   {       printf("v%d - v%d : ",v0,i);j=i;while(P[j]!=0){printf("%d ",P[j]);j=P[j];}printf("\n");}    printf("\n源点到各顶点的最短路径长度为:\n");  for(i=1;i<G.numVertexes;++i)        printf("v%d - v%d : %d \n",G.vexs[0],G.vexs[i],D[i]);     return 0;}

8.最短路径—Floyd

#include "stdio.h"    #include "stdlib.h"   #include "io.h"  #include "math.h"  #include "time.h"#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define MAXEDGE 20#define MAXVEX 20#define INFINITY 65535typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */typedef struct{int vexs[MAXVEX];int arc[MAXVEX][MAXVEX];int numVertexes, numEdges;}MGraph;typedef int Patharc[MAXVEX][MAXVEX];typedef int ShortPathTable[MAXVEX][MAXVEX];/* 构件图 */void CreateMGraph(MGraph *G){int i, j;/* printf("请输入边数和顶点数:"); */G->numEdges=16;G->numVertexes=9;for (i = 0; i < G->numVertexes; i++)/* 初始化图 */{G->vexs[i]=i;}for (i = 0; i < G->numVertexes; i++)/* 初始化图 */{for ( j = 0; j < G->numVertexes; j++){if (i==j)G->arc[i][j]=0;elseG->arc[i][j] = G->arc[j][i] = INFINITY;}}G->arc[0][1]=1;G->arc[0][2]=5; G->arc[1][2]=3; G->arc[1][3]=7; G->arc[1][4]=5; G->arc[2][4]=1; G->arc[2][5]=7; G->arc[3][4]=2; G->arc[3][6]=3; G->arc[4][5]=3;G->arc[4][6]=6;G->arc[4][7]=9; G->arc[5][7]=5; G->arc[6][7]=2; G->arc[6][8]=7;G->arc[7][8]=4;for(i = 0; i < G->numVertexes; i++){for(j = i; j < G->numVertexes; j++){G->arc[j][i] =G->arc[i][j];}}}/* Floyd算法,求网图G中各顶点v到其余顶点w的最短路径P[v][w]及带权长度D[v][w]。 */    void ShortestPath_Floyd(MGraph G, Patharc *P, ShortPathTable *D){    int v,w,k;    for(v=0; v<G.numVertexes; ++v) /* 初始化D与P */  {        for(w=0; w<G.numVertexes; ++w)  {(*D)[v][w]=G.arc[v][w];/* D[v][w]值即为对应点间的权值 */(*P)[v][w]=w;/* 初始化P */}}for(k=0; k<G.numVertexes; ++k)   {for(v=0; v<G.numVertexes; ++v)  {        for(w=0; w<G.numVertexes; ++w)    {if ((*D)[v][w]>(*D)[v][k]+(*D)[k][w]){/* 如果经过下标为k顶点路径比原两点间路径更短 */(*D)[v][w]=(*D)[v][k]+(*D)[k][w];/* 将当前两点间权值设为更小的一个 */(*P)[v][w]=(*P)[v][k];/* 路径设置为经过下标为k的顶点 */}}}}}int main(void){    int v,w,k;  MGraph G;    Patharc P;    ShortPathTable D; /* 求某点到其余各点的最短路径 */   CreateMGraph(&G);ShortestPath_Floyd(G,&P,&D);  printf("各顶点间最短路径如下:\n");    for(v=0; v<G.numVertexes; ++v)   {        for(w=v+1; w<G.numVertexes; w++)  {printf("v%d-v%d weight: %d ",v,w,D[v][w]);k=P[v][w];/* 获得第一个路径顶点下标 */printf(" path: %d",v);/* 打印源点 */while(k!=w)/* 如果路径顶点下标不是终点 */{printf(" -> %d",k);/* 打印路径顶点 */k=P[k][w];/* 获得下一个路径顶点下标 */}printf(" -> %d\n",w);/* 打印终点 */}printf("\n");}printf("最短路径D\n");for(v=0; v<G.numVertexes; ++v)  {        for(w=0; w<G.numVertexes; ++w)    {printf("%d\t",D[v][w]);}printf("\n");}printf("最短路径P\n");for(v=0; v<G.numVertexes; ++v)  {        for(w=0; w<G.numVertexes; ++w)    {printf("%d ",P[v][w]);}printf("\n");}return 0;}

9.拓扑排序

#include "stdio.h"    #include "stdlib.h"   #include "io.h"  #include "math.h"  #include "time.h"#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define MAXEDGE 20#define MAXVEX 14#define INFINITY 65535typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 *//* 邻接矩阵结构 */typedef struct{int vexs[MAXVEX];int arc[MAXVEX][MAXVEX];int numVertexes, numEdges;}MGraph;/* 邻接表结构****************** */typedef struct EdgeNode /* 边表结点  */{int adjvex;    /* 邻接点域,存储该顶点对应的下标 */int weight;/* 用于存储权值,对于非网图可以不需要 */struct EdgeNode *next; /* 链域,指向下一个邻接点 */}EdgeNode;typedef struct VertexNode /* 顶点表结点 */{int in;/* 顶点入度 */int data; /* 顶点域,存储顶点信息 */EdgeNode *firstedge;/* 边表头指针 */}VertexNode, AdjList[MAXVEX];typedef struct{AdjList adjList; int numVertexes,numEdges; /* 图中当前顶点数和边数 */}graphAdjList,*GraphAdjList;/* **************************** */void CreateMGraph(MGraph *G)/* 构件图 */{int i, j;/* printf("请输入边数和顶点数:"); */G->numEdges=MAXEDGE;G->numVertexes=MAXVEX;for (i = 0; i < G->numVertexes; i++)/* 初始化图 */{G->vexs[i]=i;}for (i = 0; i < G->numVertexes; i++)/* 初始化图 */{for ( j = 0; j < G->numVertexes; j++){G->arc[i][j]=0;}}G->arc[0][4]=1;G->arc[0][5]=1; G->arc[0][11]=1; G->arc[1][2]=1; G->arc[1][4]=1; G->arc[1][8]=1; G->arc[2][5]=1; G->arc[2][6]=1;G->arc[2][9]=1;G->arc[3][2]=1; G->arc[3][13]=1;G->arc[4][7]=1;G->arc[5][8]=1;G->arc[5][12]=1; G->arc[6][5]=1; G->arc[8][7]=1;G->arc[9][10]=1;G->arc[9][11]=1;G->arc[10][13]=1;G->arc[12][9]=1;}/* 利用邻接矩阵构建邻接表 */void CreateALGraph(MGraph G,GraphAdjList *GL){int i,j;EdgeNode *e;*GL = (GraphAdjList)malloc(sizeof(graphAdjList));(*GL)->numVertexes=G.numVertexes;(*GL)->numEdges=G.numEdges;for(i= 0;i <G.numVertexes;i++) /* 读入顶点信息,建立顶点表 */{(*GL)->adjList[i].in=0;(*GL)->adjList[i].data=G.vexs[i];(*GL)->adjList[i].firstedge=NULL; /* 将边表置为空表 */}for(i=0;i<G.numVertexes;i++) /* 建立边表 */{ for(j=0;j<G.numVertexes;j++){if (G.arc[i][j]==1){e=(EdgeNode *)malloc(sizeof(EdgeNode));e->adjvex=j;/* 邻接序号为j  */                        e->next=(*GL)->adjList[i].firstedge;/* 将当前顶点上的指向的结点指针赋值给e */(*GL)->adjList[i].firstedge=e;/* 将当前顶点的指针指向e  */  (*GL)->adjList[j].in++;}}}}/* 拓扑排序,若GL无回路,则输出拓扑排序序列并返回1,若有回路返回0。 */Status TopologicalSort(GraphAdjList GL){    EdgeNode *e;    int i,k,gettop;   int top=0;  /* 用于栈指针下标  */int count=0;/* 用于统计输出顶点的个数  */    int *stack;/* 建栈将入度为0的顶点入栈  */   stack=(int *)malloc(GL->numVertexes * sizeof(int) );    for(i = 0; i<GL->numVertexes; i++)                if(0 == GL->adjList[i].in) /* 将入度为0的顶点入栈 */         stack[++top]=i;    while(top!=0)    {        gettop=stack[top--];        printf("%d -> ",GL->adjList[gettop].data);        count++;        /* 输出i号顶点,并计数 */        for(e = GL->adjList[gettop].firstedge; e; e = e->next)        {            k=e->adjvex;            if( !(--GL->adjList[k].in) )  /* 将i号顶点的邻接点的入度减1,如果减1后为0,则入栈 */                stack[++top]=k;        }}   printf("\n");   if(count < GL->numVertexes)        return ERROR;    else       return OK;}int main(void){    MGraph G;  GraphAdjList GL; int result;   CreateMGraph(&G);CreateALGraph(G,&GL);result=TopologicalSort(GL);printf("result:%d",result);return 0;}

10.关键路径

#include "stdio.h"    #include "stdlib.h"   #include "io.h"  #include "math.h"  #include "time.h"#define OK 1#define ERROR 0#define TRUE 1#define FALSE 0#define MAXEDGE 30#define MAXVEX 30#define INFINITY 65535typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */  int *etv,*ltv; /* 事件最早发生时间和最迟发生时间数组,全局变量 */int *stack2;   /* 用于存储拓扑序列的栈 */int top2;   /* 用于stack2的指针 *//* 邻接矩阵结构 */typedef struct{int vexs[MAXVEX];int arc[MAXVEX][MAXVEX];int numVertexes, numEdges;}MGraph;/* 邻接表结构****************** */typedef struct EdgeNode /* 边表结点  */{int adjvex;    /* 邻接点域,存储该顶点对应的下标 */int weight;/* 用于存储权值,对于非网图可以不需要 */struct EdgeNode *next; /* 链域,指向下一个邻接点 */}EdgeNode;typedef struct VertexNode /* 顶点表结点 */{int in;/* 顶点入度 */int data; /* 顶点域,存储顶点信息 */EdgeNode *firstedge;/* 边表头指针 */}VertexNode, AdjList[MAXVEX];typedef struct{AdjList adjList; int numVertexes,numEdges; /* 图中当前顶点数和边数 */}graphAdjList,*GraphAdjList;/* **************************** */void CreateMGraph(MGraph *G)/* 构件图 */{int i, j;/* printf("请输入边数和顶点数:"); */G->numEdges=13;G->numVertexes=10;for (i = 0; i < G->numVertexes; i++)/* 初始化图 */{G->vexs[i]=i;}for (i = 0; i < G->numVertexes; i++)/* 初始化图 */{for ( j = 0; j < G->numVertexes; j++){if (i==j)G->arc[i][j]=0;elseG->arc[i][j]=INFINITY;}}G->arc[0][1]=3;G->arc[0][2]=4; G->arc[1][3]=5; G->arc[1][4]=6; G->arc[2][3]=8; G->arc[2][5]=7; G->arc[3][4]=3;G->arc[4][6]=9; G->arc[4][7]=4;G->arc[5][7]=6; G->arc[6][9]=2;G->arc[7][8]=5;G->arc[8][9]=3;}/* 利用邻接矩阵构建邻接表 */void CreateALGraph(MGraph G,GraphAdjList *GL){int i,j;EdgeNode *e;*GL = (GraphAdjList)malloc(sizeof(graphAdjList));(*GL)->numVertexes=G.numVertexes;(*GL)->numEdges=G.numEdges;for(i= 0;i <G.numVertexes;i++) /* 读入顶点信息,建立顶点表 */{(*GL)->adjList[i].in=0;(*GL)->adjList[i].data=G.vexs[i];(*GL)->adjList[i].firstedge=NULL; /* 将边表置为空表 */}for(i=0;i<G.numVertexes;i++) /* 建立边表 */{ for(j=0;j<G.numVertexes;j++){if (G.arc[i][j]!=0 && G.arc[i][j]<INFINITY){e=(EdgeNode *)malloc(sizeof(EdgeNode));e->adjvex=j;/* 邻接序号为j */   e->weight=G.arc[i][j];e->next=(*GL)->adjList[i].firstedge;/* 将当前顶点上的指向的结点指针赋值给e */(*GL)->adjList[i].firstedge=e;/* 将当前顶点的指针指向e  */  (*GL)->adjList[j].in++;}}}}/* 拓扑排序 */Status TopologicalSort(GraphAdjList GL){    /* 若GL无回路,则输出拓扑排序序列并返回1,若有回路返回0。 */    EdgeNode *e;    int i,k,gettop;   int top=0;  /* 用于栈指针下标  */int count=0;/* 用于统计输出顶点的个数 */   int *stack;/* 建栈将入度为0的顶点入栈  */   stack=(int *)malloc(GL->numVertexes * sizeof(int) );    for(i = 0; i<GL->numVertexes; i++)                if(0 == GL->adjList[i].in) /* 将入度为0的顶点入栈 */           stack[++top]=i;    top2=0;    etv=(int *)malloc(GL->numVertexes * sizeof(int) ); /* 事件最早发生时间数组 */    for(i=0; i<GL->numVertexes; i++)        etv[i]=0;    /* 初始化 */stack2=(int *)malloc(GL->numVertexes * sizeof(int) );/* 初始化拓扑序列栈 */printf("TopologicalSort:\t");while(top!=0)    {        gettop=stack[top--];        printf("%d -> ",GL->adjList[gettop].data);        count++;        /* 输出i号顶点,并计数 */ stack2[++top2]=gettop;        /* 将弹出的顶点序号压入拓扑序列的栈 */for(e = GL->adjList[gettop].firstedge; e; e = e->next)        {            k=e->adjvex;            if( !(--GL->adjList[k].in) )        /* 将i号顶点的邻接点的入度减1,如果减1后为0,则入栈 */                stack[++top]=k; if((etv[gettop] + e->weight)>etv[k])    /* 求各顶点事件的最早发生时间etv值 */                etv[k] = etv[gettop] + e->weight;}    }    printf("\n");   if(count < GL->numVertexes)        return ERROR;    else       return OK;}/* 求关键路径,GL为有向网,输出G的各项关键活动 */void CriticalPath(GraphAdjList GL) {    EdgeNode *e;    int i,gettop,k,j;    int ete,lte;  /* 声明活动最早发生时间和最迟发生时间变量 */        TopologicalSort(GL);   /* 求拓扑序列,计算数组etv和stack2的值 */ ltv=(int *)malloc(GL->numVertexes*sizeof(int));/* 事件最早发生时间数组 */   for(i=0; i<GL->numVertexes; i++)        ltv[i]=etv[GL->numVertexes-1];    /* 初始化 */        printf("etv:\t");   for(i=0; i<GL->numVertexes; i++)        printf("%d -> ",etv[i]);    printf("\n"); while(top2!=0)    /* 出栈是求ltv */    {        gettop=stack2[top2--];        for(e = GL->adjList[gettop].firstedge; e; e = e->next)        /* 求各顶点事件的最迟发生时间ltv值 */        {            k=e->adjvex;            if(ltv[k] - e->weight < ltv[gettop])               ltv[gettop] = ltv[k] - e->weight;        }   }    printf("ltv:\t");   for(i=0; i<GL->numVertexes; i++)        printf("%d -> ",ltv[i]);    printf("\n"); for(j=0; j<GL->numVertexes; j++)        /* 求ete,lte和关键活动 */        {            for(e = GL->adjList[j].firstedge; e; e = e->next)            {                k=e->adjvex;                ete = etv[j];        /* 活动最早发生时间 */                lte = ltv[k] - e->weight; /* 活动最迟发生时间 */               if(ete == lte)    /* 两者相等即在关键路径上 */                    printf("<v%d - v%d> length: %d \n",GL->adjList[j].data,GL->adjList[k].data,e->weight);}        }}int main(void){    MGraph G;    GraphAdjList GL;    CreateMGraph(&G);CreateALGraph(G,&GL);CriticalPath(GL);return 0;}