1.1图的数组表示法
//无向图
#include<stdio.h>
#include<stdlib.h>
#define INFINITY 999
#define MAX_VERTEX 20
typedef char VertexType; //顶点类型
typedef int EdgeType; //边上的权值类型
typedef int Boolean;
Boolean visited[MAX_VERTEX];
typedef struct
{
VertexType vexs[MAX_VERTEX];//顶点表
EdgeType arc[MAX_VERTEX][MAX_VERTEX];
int vexnum, arcnum;//顶点数和边数
}MGraph;
void Creat(MGraph *G)
{
int i, j, k, w;
printf("输入顶点数和边数\n");
scanf("%d %d", &G->vexnum, &G->arcnum);
printf("输入顶点信息\n");
for (i = 0; i < G->vexnum; i++) //输入顶点信息,简历顶点表
{
getchar();
scanf("%c", &G->vexs[i]);
}
for (i = 0; i<G->vexnum; i++)//邻接矩阵初始化
for (j = 0; j<G->vexnum; j++)
G->arc[i][j] = INFINITY;
for (k = 0; k<G->arcnum; k++)//读入arcnum条边,建立邻接矩阵
{
printf("输入边(vi,vj)的i j 权值w\n");
scanf("%d %d %d", &i, &j, &w);
G->arc[i][j] = w;
G->arc[j][i] = G->arc[i][j];//无向图,邻接矩阵对称
}
}
void DFS(MGraph G, int i)
{
int j;
visited[i] = 1;
printf(" %c ", G.vexs[i]);
for (j = 0; j < G.vexnum;j++)
if (G.arc[i][j] == 1 && visited[j] == 0)
DFS(G, j);
}
void DFSTraverse(MGraph G)
{
int i;
for (i = 0; i < G.vexnum; i++)
visited[i] = 0;
for (i = 0; i < G.vexnum;i++)
if (visited[i] == 0)
DFS(G, i);
}
int main()
{
MGraph G;
Creat(&G);
DFSTraverse(G);
return 0;
}
1.2邻接矩阵
//无向图
#include<stdio.h>
#include<stdlib.h>
#define MAXVEX 20
typedef char VertexType;//顶点类型
typedef int EdgeType; //边上的权值类型
typedef int Boolean;
Boolean visited[MAXVEX];
typedef struct ArcNode //编表结点
{
int adjevx; //该弧所指向的顶点位置
EdgeType weight;//存储权值
struct ArcNode *nextarc; //指向下一条弧的指针
}ArcNode;
typedef struct //顶点表结点
{
VertexType data;//顶点信息
ArcNode *firstarc;//边表头指针
}VNode, AdjList[MAXVEX];
typedef struct
{
AdjList vertices;
int vexnum, arcnum;
}ALGraph;
void Creat(ALGraph *G)
{
int i, j, k;
ArcNode *e;
printf("输入顶点数 边数:\n");
scanf("%d %d", &G->vexnum, &G->arcnum);
printf("输入顶点信息\n");
for (i = 0; i < G->vexnum; i++)
{
getchar();
scanf("%c", &G->vertices[i].data);
G->vertices[i].firstarc = NULL;//将边表置为空表
}
for (k = 0; k < G->arcnum; k++)//建立边表
{
printf("输入边(v1,v2)的顶点下标\n");
scanf("%d %d", &i, &j);
//头插法
e = (ArcNode *)malloc(sizeof(ArcNode));
e->adjevx = j;//顶点下标为j
e->nextarc = G->vertices[i].firstarc;
G->vertices[i].firstarc = e;
//无向图,一条边对应两个结点
e = (ArcNode *)malloc(sizeof(ArcNode));
e->adjevx = i;
e->nextarc = G->vertices[j].firstarc;
G->vertices[j].firstarc = e;
}
}
void DFS(ALGraph G, int i)
{
ArcNode *p;
visited[i] = 1;
printf(" %c ", G.vertices[i].data);
p = G.vertices[i].firstarc;
while (p)
{
if (visited[p->adjevx] == 0)
DFS(G, p->adjevx);
p = p->nextarc;
}
}
void DFSTraverse(ALGraph G)
{
int i;
for (i = 0; i < G.vexnum; i++)
visited[i] = 0;
for (i = 0; i < G.vexnum;i++)
if (visited[i] == 0)
DFS(G, i);
}
2.1拓扑排序
#include<stdio.h>
#include<stdlib.h>
#include"stack.h"
#define Status int
#define ERROR 0
#define OK 1
typedef struct ArcNode
{
int adjvex;//顶点下标
struct ArcNode *nextarc;
}ArcNode;
typedef struct VNode
{
char data;
ArcNode *firstarc;
}VNode,Adjlist[20];
typedef struct
{
Adjlist vertices;
int vexnum, arcnum;//当前的的顶点数和弧数
}AlGraph;
void Creat(AlGraph *G)
{//建立邻接表
int i, j, k;
ArcNode *e;
printf("输入顶点数 边数:\n");
scanf("%d %d", &G->vexnum, &G->arcnum);
for (i = 0; i < G->vexnum; i++)
{
printf("输入顶点信息\n");
getchar();
scanf("%c", &G->vertices[i].data);
G->vertices[i].firstarc = NULL;
}
for (k = 0; k < G->arcnum; k++)//建立边表
{
printf("第%d条边顶点下标\n",k+1);
scanf("%d %d", &i, &j);
//头插法建立单向邻接表
e = (ArcNode *)malloc(sizeof(ArcNode));
e->adjvex = j;
e->nextarc = G->vertices[i].firstarc;
G->vertices[i].firstarc = e;
}
}
void FindInDegree(AlGraph *G, int *InDegree)
{//求顶点入度
int i;
ArcNode *p;
for (i = 0; i < G->vexnum; i++)
{//顶点入度初始化
InDegree[i] = 0;
}
for (i = 0; i < G->vexnum; i++)
{
p = G->vertices[i].firstarc;
while (p)
{
InDegree[p->adjvex]++;
p = p->nextarc;
}
}
}
void TopologicalSort(AlGraph *G,SqStack S)
{//求拓扑排序
int indegree[20],count=1,i,k;
//保存顶点入度数组,count为对出栈的顶点计数
char a[20];//保存拓扑序列的数组
ArcNode *p;
FindInDegree(G, indegree);
for (i = 0; i < G->vexnum;i++)
if (!indegree[i])
Push(&S, i);//入度为0者进栈
while (S.top>-1)//栈不空
{
Pop(&S, &i);
a[count++] = G->vertices[i].data;
for (p = G->vertices[i].firstarc; p; p = p->nextarc)
{
indegree[p->adjvex]--;
if (!(indegree[p->adjvex]))
Push(&S, p->adjvex);
}
}//while
if (count < G->vexnum)
{
printf("error"); return ERROR;
}
else
{
printf("拓扑序列为:");
for (i = 1; i <count-1; i++)
printf("%c->",a[i]);
printf("%c", a[i]);
return OK;
}
}
int main()
{
AlGraph G;
SqStack S;
Creat(&G);
InitStack(&S);
TopologicalSort(&G, S);
}
//stack.h
#include<stdlib.h>
#include<stdio.h>
#define MAX 20
typedef struct SqStack
{
int elem[MAX];
int top;//栈顶指针
}SqStack;
int InitStack(SqStack *S)
{
S->top = -1;
return 1;
}
int Push(SqStack *S,int x)
{
//在栈顶插入新元素x,返回1表示入栈成功,返回0表示失败
int n;
if (S->top == MAX - 1){ printf("栈满不能入栈\n"); return 0; }
else
{
S->top++;
S->elem[S->top] = x;
return 1;
}
}
int Get_SqStack(SqStack *S, int *e)
{
//用e栈顶元素,成功返回1,失败返回0
if (S->top == -1){ printf("栈是空的"); return 0; }
else
*e = S->elem[S->top];
return 1;
}
int Pop(SqStack *S, int *e)
{
//删除栈顶元素,用tmp返回其值,返回值为1表示出栈成功,为0表示出栈失败
if (S->top == -1){ printf("栈是空的"); return 0; }
else (*e = S->elem[S->top]);
S->top--;
return 1;
}
void outline(SqStack *S)
{
for (int i = S->top; i >= 0; i--)
printf("%2d", S->elem[i]);
}
2.2关键路径
#include<stdio.h>
#include<stdlib.h>
#include"stack.h"
#define Status int
#define ERROR 0
#define OK 1
typedef struct ArcNode
{
int adjvex;//顶点下标
int weight;
struct ArcNode *nextarc;
}ArcNode;
typedef struct VNode
{
char data;
ArcNode *firstarc;
}VNode,Adjlist[20];
typedef struct
{
Adjlist vertices;
int vexnum, arcnum;//当前的的顶点数和弧数
}AlGraph;
void Creat(AlGraph *G)
{//建立邻接表
int i, j, k,w;
ArcNode *e;
printf("输入顶点数 边数:\n");
scanf("%d %d", &G->vexnum, &G->arcnum);
for (i = 0; i < G->vexnum; i++)
{
printf("输入顶点信息\n");
getchar();
scanf("%c", &G->vertices[i].data);
G->vertices[i].firstarc = NULL;
}
for (k = 0; k < G->arcnum; k++)//建立边表
{
printf("第%d条边的两个顶点下标及权值(空格隔开)\n",k+1);
scanf("%d %d %d", &i, &j,&w);
//头插法建立单向邻接表
e = (ArcNode *)malloc(sizeof(ArcNode));
e->adjvex = j;
e->weight = w;
e->nextarc = G->vertices[i].firstarc;
G->vertices[i].firstarc = e;
}
}
void FindInDegree(AlGraph *G, int *InDegree)
{//求顶点入度
int i;
ArcNode *p;
for (i = 0; i < G->vexnum; i++)
{//顶点入度初始化
InDegree[i] = 0;
}
for (i = 0; i < G->vexnum; i++)
{
p = G->vertices[i].firstarc;
while (p)
{
InDegree[p->adjvex]++;
p = p->nextarc;
}
}
}
int TopologicalSort(AlGraph *G,SqStack S,int *a)
{//求拓扑排序
int indegree[20],count=0,i;
//保存顶点入度数组,count为对出栈的顶点计数
ArcNode *p;
FindInDegree(G, indegree);
for (i = 0; i < G->vexnum;i++)
if (!indegree[i])
Push(&S, i);//入度为0者进栈
while (S.top>-1)//栈不空
{
Pop(&S, &i);
a[count++] = i;
for (p = G->vertices[i].firstarc; p; p = p->nextarc)
{
indegree[p->adjvex]--;
if (!(indegree[p->adjvex]))
Push(&S, p->adjvex);
}
}//while
if (count+1 < G->vexnum)
{
printf("error"); return ERROR;
}
else
{
return OK;
}
}
int CriticalPath(AlGraph *G)
{
int ve[20], vl[20];//事件的最早和最晚发生时间
int e[20], l[20];//活动的最早和最晚发生时间
int a[20];//保存拓扑排序序列顶点下标
int i,k,j,n=0;
ArcNode *p;
SqStack S;
InitStack(&S);
TopologicalSort(G, S,a);
for (i = 0; i < G->vexnum; i++)//ve[]置初值
ve[i] = 0;
for (i = 0; i < G->vexnum; i++)//求每个事件的最早发生时间
{
k = a[i];
p = G->vertices[k].firstarc;
while (p != NULL)
{//修改顶点k的所有后继结点的最早发生时间
j = p->adjvex;
if (ve[j] < ve[k] + p->weight)
ve[j] = ve[k] + p->weight;
p = p->nextarc;
}
}
for (i = 0; i < G->vexnum; i++)//vl[]置初值
vl[i] = ve[G->vexnum-1];
for (i = G->vexnum - 1; i >= 0; i--)//按逆拓扑排序求每个事件的最晚发生时间
{
k = a[i];
p = G->vertices[k].firstarc;
while (p != NULL)
{
j = p->adjvex;
if (vl[k]>vl[j]- p->weight)
vl[k]=vl[j] - p->weight;
p = p->nextarc;
}
}
printf("\nAOE网关键路径为:");
for (i = 0; i < G->vexnum; i++)
{
p = G->vertices[i].firstarc;
while (p!=NULL)
{
j = p->adjvex;
e[n] = ve[i];
l[n] = vl[j] - p->weight; //活动的最晚发生时间
if ((e[n] - l[n]) == 0)
printf("<%c,%c>", G->vertices[i].data, G->vertices[j].data);
n++;
p = p->nextarc;
}
}
return 1;
}
int main()
{
AlGraph G;
Creat(&G);
CriticalPath(&G);
}