#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>
#include<iostream.h>
#define INFINITY 35542//用整型最大代替正无穷
#define NULL 0
#define FALSE 0
#define TRUE 1
#define ERROR 0
#define WRONG 0
#define OVERFLOW 0
#define M 10
#define MAX 20
#define MAXV 100
#define MAX_NAME 9
#define MAX_INFO 20
#define OK 1
#define STACK_INIT_SIZE 50
struct VertexType
{
char data[3];/*顶点值*/;
int info;/*弧的长度*/
struct VertexType *next;/*顶点的下一个指针*/
};
typedef int ElemType;
typedef int Status;
typedef int VRType;
typedef char InfoType;//弧的相关信息类型
#define MAX_VERTEX_NUM 26//最大顶点个数
enum GraphKind{DG,DN,UDG,UDN};//{有向图,有向网,无向图,无向网}
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;
};
//
typedef struct Arcnode
{
int adjvex;
int weight;
struct Arcnode* nextarc;
}Arcnode;//边表结点
typedef struct vnode
{
int vertex;
Arcnode* firstedge;
}vertexnode;//顶点表结点
typedef vertexnode adj_list[MAX];//adj_list是邻接表类型
typedef struct adjlist_graph
{
int Arcnodes, edges;//图中顶点数和边数
adj_list adjlist;//邻接表
}algraph;
typedef struct
{
int u; /*边的起始顶点*/
int v; /*边的终止顶点*/
int w; /*边的权值*/
}edge;
void visit(VertexType ver);
void Input(VertexType &ver);
void InputArc(InfoType *&arc);
void OutputArc(InfoType *arc);
int LocateVex(MGraph G,VertexType u);//返回顶点在图中的位置
void CreateDG(MGraph &G);//采用数组表示法,构造有向图
void CreateDN(MGraph &G);//构造有向网
void CreateUDG(MGraph &G);//构造无向图
void CreateUDN(MGraph &G);//构造无向网
void CreateGraph(MGraph &G);//构造图
void CreateUDG_ALG(algraph* g);//建立无向图的邻接表
void CreateUDN_ALG(algraph* g);//建立无向网的邻接表
void CreateDG_ALG(algraph* g);//建立有向图的邻接表
void CreateDN_ALG(algraph* g);//建立有向网的邻接表
void dispgraph(algraph* g);//输出邻接表
void Display(MGraph G);//输出邻接矩阵存储结构图
void InsertVex(MGraph &G,VertexType v);//在图中插入新的结点
Status InsertArc(MGraph &G,VertexType v,VertexType w);//在图中插入弧
void DestroyGraph(MGraph &G);
Status PutVex(MGraph &G,VertexType v,VertexType value);
void DFS(algraph * g);
void BFS(algraph * g);
void prim(MGraph g,int v);
void sortedge(MGraph g,edge E[]); /*从邻接矩阵产生权值递增的边集*/
void kruskal(edge E,int n,int e);
void Input(VertexType &ver)
{
scanf("%s",&ver.data);
}
void visit(VertexType ver)
{
printf("%s",ver.data);
}
int LocateVex(MGraph G,VertexType u)
{ //返回该结点在图中的位置
int i;
for(i=0;i<G.vexnum;i++)
if(strcmp(u.data,G.vexs[i].data)==0)
return i;
return 0;
}
void InputArc(InfoType *&arc)
{
char s[MAX_INFO];//临时存放空间
int m;
printf("请输入该弧的相关信息:",MAX_INFO);
gets(s);
m=strlen(s);
if(m)
{
arc=(char *)malloc((m+1)*sizeof(char));//动态生成相关信息存储空间
strcpy(arc,s);
}
}
void OutputArc(InfoType *arc)
{
printf("%s/n",arc);
}
VertexType GetVex(MGraph G,int v)
{
if(v>=G.vexnum||v<0)
exit(OVERFLOW);
return G.vexs[v];//返回顶点的信息
}
void CreateDG(MGraph &G)
{
int i,j,k,IncInfo;//IncInfo为0则弧不包括相关信息
VertexType v1,v2;
printf("请输入有向图G的顶点数,弧数,弧是否有相关信息(是:1否:0):");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
printf("请输入%d个顶点的值/n",G.vexnum,MAX_NAME);
for(i=0;i<G.vexnum;i++)//构造顶点向量
Input(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条弧的弧尾,弧头:/n",G.arcnum);
for(k=0;k<G.arcnum;k++)
{
scanf("%s%s*%c",v1.data,v2.data);
i=LocateVex(G,v1);//弧尾的序号
j=LocateVex(G,v2);//弧头的序号
G.arcs[i][j].adj=1;//有向图
if(IncInfo)
{
InputArc(G.arcs[i][j].info);
}
G.kind=DG;
}
}
void CreateDN(MGraph &G)
{ //采用数组表示法,构造有向网G
int i,j,k,IncInfo;
VRType w;//顶点关系类型
VertexType v1,v2;
printf("请输入有向网G的顶点数,弧数,弧是否有相关信息(是:1否:0)");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
printf("请输入%d个顶点的值:/n",G.vexnum);
for(i=0;i<G.vexnum;i++)
Input(G.vexs[i]);
for(i=0;i<G.vexnum;i++)
for(j=0;j<G.vexnum;j++)
{
G.arcs[i][j].adj=INFINITY;//网,不相邻
G.arcs[i][j].info=NULL;
}
printf("请输入%d条弧的弧尾,弧头,权值:/n",G.arcnum);
for(k=0;k<G.arcnum;k++)
{
scanf("%s%s%d%*c",v1.data,v2.data,&w);
i=LocateVex(G,v1);//弧尾序号
j=LocateVex(G,v2);//弧头序号
G.arcs[i][j].adj=w;//有向网
if(IncInfo)//有相关信息
InputArc(G.arcs[i][j].info);
//动态生成存储空间,输入弧的相关信息
}
G.kind=DN;
}
void CreateUDG(MGraph &G)
{ //采用数组构造无向图
int i,j,k,IncInfo;
VertexType v1,v2;
printf("请输入无向图G的顶点数,边数,边是否有相关信息(是:1否:0):");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
printf("请输入%d个顶点的值:/n",G.vexnum);
for(i=0;i<G.vexnum;i++)
Input(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++)
{
scanf("%s%s%*c",v1.data,v2.data);
i=LocateVex(G,v1);//顶点1的序号
j=LocateVex(G,v2);//顶点2的序号
G.arcs[i][j].adj=1;//图
if(IncInfo)//有相关信息
InputArc(G.arcs[i][j].info);//动态生成存储空间,输入弧的相关信息
G.arcs[j][i]=G.arcs[i][j];
}
G.kind=UDG;
}
void CreateUDN(MGraph &G)
{
int i,j,k,IncInfo;
VRType w;
VertexType v1,v2;
printf("请输入无向网的顶点数,边数,边是否含相关结点信息(1,是;0,否)");
scanf("%d%d%d",&G.vexnum,&G.arcnum,&IncInfo);
printf("请输入%d个结点的值:/n",G.vexnum);
for(i=0;i<G.vexnum;i++)
Input(G.vexs[i]);
for(i=0;i<G.vexnum;i++)
for(j=0;j<G.vexnum;j++)
{
G.arcs[i][j].adj=INFINITY;//网,不相邻
G.arcs[i][j].info=NULL;//无相关信息
}
printf("请输入%d条边的顶点1顶点2及连接它们边的权值:/n",G.arcnum);
for(k=0;k<G.arcnum;k++)
{
scanf("%s%s%d%*c",v1.data,v2.data,&w);
i=LocateVex(G,v1);
j=LocateVex(G,v2);
G.arcs[i][j].adj=w;//网
if(IncInfo)
InputArc(G.arcs[i][j].info);
G.arcs[j][i]=G.arcs[i][j];
}
G.kind=UDN;
}
void ShowMainMenu()
{
cout<<"/n";
cout<<" ***************图的基本操作及应用******************/n";
cout<<" * 1 无向图的基本操作及应用 */n";
cout<<" * 2 无向网的基本操作及应用 */n";
cout<<" * 3 有向图的基本操作及应用 */n";
cout<<" * 4 有向网的基本操作及应用 */n";
cout<<" * 5 退出 */n";
cout<<" ***************************************************/n";
}
void Display(MGraph G)
{
int i,j;
char s[7]="无向图",s1[3]="边";
switch(G.kind)
{
case DG:strcpy(s,"有向图");
strcpy(s1,"弧");
break;
case DN:strcpy(s,"有向网");
strcpy(s1,"弧");
break;
case UDG:strcpy(s,"无向图");
case UDN:strcpy(s,"无向网");
}
printf("%d个顶点%d条%s的%s,顶点依次是:",G.vexnum,G.arcnum,s1,s);
for(i=0;i<G.vexnum;i++)
{
visit(GetVex(G,i));
printf(" ");
}
printf("/nG.arcs.adj:/n");
for(i=0;i<G.vexnum;i++)
{
for(j=0;j<G.vexnum;j++)
printf("%7d",G.arcs[i][j].adj);
printf("/n");
}
printf("G.arcs.info:/n");
if(G.kind<2)
printf("弧尾 弧头 该%s的信息:/n",s1);
for(i=0;i<G.vexnum;i++)
if(G.kind<2)//有向
{
for(j=0;j<G.vexnum;j++)
if(G.arcs[i][j].info)
{
printf("%5s%5s",G.vexs[i].data,G.vexs[j].data);
OutputArc(G.arcs[i][j].info);
}
}
else//无向
for(j=i+1;j<G.vexnum;j++)
if(G.arcs[i][j].info)
{ printf("%5s%5s",G.vexs[i].data,G.vexs[j].data);
OutputArc(G.arcs[i][j].info);
}
}
/
void CreateUDG_ALG(algraph* g)
{
Arcnode* newArcnode;
int i, j, k;
printf("请输入顶点数和边数: ");
scanf("%d%d", &g->Arcnodes, &g->edges);
printf("顶点数 = %d, 边数 = %d/n", g->Arcnodes, g->edges);
for(i = 0; i < g->Arcnodes; i++)
{
g->adjlist[i].vertex = i;
g->adjlist[i].firstedge = NULL;
}
for(k = 0; k < g->edges; k++)
{
printf("请输入新边: ");
scanf("%d%d", &i, &j);
printf("/n");
newArcnode = (Arcnode* )malloc(sizeof(Arcnode));
newArcnode->adjvex = j;
newArcnode->weight = 0;
newArcnode->nextarc = g->adjlist[i].firstedge;
g->adjlist[i].firstedge = newArcnode;
newArcnode = (Arcnode* )malloc(sizeof(Arcnode));
newArcnode->adjvex = i;
newArcnode->weight = 0;
newArcnode->nextarc = g->adjlist[j].firstedge;
g->adjlist[j].firstedge = newArcnode;
}
}
void CreateUDN_ALG(algraph* g)
{
Arcnode* newArcnode;
int i, j, k,m;
printf("请输入顶点数和边数: ");
scanf("%d%d", &g->Arcnodes, &g->edges);
printf("顶点数 = %d, 边数 = %d/n", g->Arcnodes, g->edges);
for(i = 0; i < g->Arcnodes; i++)
{
g->adjlist[i].vertex = i;
g->adjlist[i].firstedge = NULL;
}
for(k = 0; k < g->edges; k++)
{
printf("请输入新边和此边的权值: ");
scanf("%d%d%d", &i, &j,&m);
printf("/n");
newArcnode = (Arcnode* )malloc(sizeof(Arcnode));
newArcnode->adjvex = j;
newArcnode->weight = m;
newArcnode->nextarc = g->adjlist[i].firstedge;
g->adjlist[i].firstedge = newArcnode;
newArcnode = (Arcnode* )malloc(sizeof(Arcnode));
newArcnode->adjvex = i;
newArcnode->weight = m;
newArcnode->nextarc = g->adjlist[j].firstedge;
g->adjlist[j].firstedge = newArcnode;
}
}
void CreateDG_ALG(algraph* g)
{
Arcnode* newArcnode;
int i, j, k;
printf("请输入顶点数和边数: ");
scanf("%d%d", &g->Arcnodes, &g->edges);
printf("顶点数 = %d, 边数 = %d/n", g->Arcnodes, g->edges);
for(i = 0; i < g->Arcnodes; i++)
{
g->adjlist[i].vertex = i;
g->adjlist[i].firstedge = NULL;
}
for(k = 0; k < g->edges; k++)
{
printf("请输入新边: ");
scanf("%d%d", &i, &j);
printf("/n");
newArcnode = (Arcnode* )malloc(sizeof(Arcnode));
newArcnode->adjvex = j;
newArcnode->weight = 0;
newArcnode->nextarc = g->adjlist[i].firstedge;
g->adjlist[i].firstedge = newArcnode;
}
}
void CreateDN_ALG(algraph* g)
{
Arcnode* newArcnode;
int i, j, k,m;
printf("请输入顶点数和边数: ");
scanf("%d%d", &g->Arcnodes, &g->edges);
printf("顶点数 = %d, 边数 = %d/n", g->Arcnodes, g->edges);
for(i = 0; i < g->Arcnodes; i++)
{
g->adjlist[i].vertex = i;
g->adjlist[i].firstedge = NULL;
}
for(k = 0; k < g->edges; k++)
{
printf("请输入新边和此边的权值: ");
scanf("%d%d%d", &i, &j,&m);
printf("/n");
newArcnode = (Arcnode* )malloc(sizeof(Arcnode));
newArcnode->adjvex = j;
newArcnode->weight = m;
newArcnode->nextarc = g->adjlist[i].firstedge;
g->adjlist[i].firstedge = newArcnode;
}
}
void dispgraph(algraph* g)
{
Arcnode* Arcnode;
int i;
for(i = 0; i < g->Arcnodes; i++)
{
Arcnode = g->adjlist[i].firstedge;
printf("g->adjlist[%d] = %d: ", i, g->adjlist[i].vertex);
while(Arcnode != NULL)
{
printf("%d %d/t", Arcnode->adjvex, Arcnode->weight);
Arcnode = Arcnode->nextarc;
}
printf("/n");
}
}
/
int visited[MAX];
void DFS(algraph * g,int v)
{
Arcnode *p;
visited[v]=1;
printf("%3d",v);
p=g->adjlist[v].firstedge;
while(p!=NULL)
{
if(visited[p->adjvex]==0)
DFS(g,p->adjvex);
p=p->nextarc;
}
}
void BFS(algraph * g,int u)
{
Arcnode *p;
int queue[MAX],front=0,rear=0;/*定义循环列队并初始化*/
int visited[MAX];/*定义存放结点访问标记的数组*/
int w,i;
for(i=0;i<g->Arcnodes;i++) visited[i]=0;/*访问标记的数组的初始化*/
printf("%3d",u);/*输出被访问顶点的编号*/
visited[u]=1;/*置已被访问标记*/
rear=(rear+1)%MAX;
queue[rear]=u;/*V进队*/
while(front!=rear)/*若队列不为空时循环*/
{
front=(front+1)%MAX;
w=queue[front]; /*出队并赋给w*/
p=g->adjlist[w].firstedge;/*找与顶点w邻接的第一个顶点*/
while(p!=NULL)
{
if(visited[p->adjvex]==0)/*若当前结点未被访问*/
{
printf("%3d",p->adjvex);/*访问相邻结点*/
visited[p->adjvex]=1;/*置该顶点已被访问的标记*/
rear=(rear+1)%MAX;/*该顶点进队*/
queue[rear]=p->adjvex;
}
p=p->nextarc;/*找下一个邻接顶点*/
}
}
printf("/n");
}
void prim(MGraph g,int v)
{
int lowcost[MAX],min,n=g.vexnum;
int closest[MAX],i,j,k;
for(i=0;i<n;i++)
{
lowcost[i]=g.arcs[v][i].adj; /*给lowcost[]和closest[]置初值,lowcost[]存放权值,closest[]存放顶点信息*/
closest[i]=v;
}
for(i=1;i<n;i++) /*找出n-1个顶点*/
{
min=INFINITY;
for(j=0;j<n;j++) /*在V-U中找出离U最近的顶点K*/
if(lowcost[j]!=0&&lowcost[j]<min)
{
min=lowcost[j];k=j;
}
printf("边(%d,%d)权为:%d/n",closest[k],k,min);
lowcost[k]=0; /*标记K已经加入U中*/
for(j=0;j<n;j++) /*修改数组lowcost和closest*/
if(g.arcs[k][j].adj !=0&&g.arcs[k][j].adj<lowcost[j])
{
lowcost[j]=g.arcs[k][j].adj ;
closest[j]=k;
}
}
}
void sortedge(MGraph g,edge E[]) /*从邻接矩阵产生权值递增的边集*/
{
int i,j,k=0;
edge temp;
for(i=0;i<g.vexnum;i++)
for(j=0;j<g.vexnum;j++)
if(g.arcs[i][j].adj <INFINITY)
{
E[k].u=i;
E[k].v=j;
E[k].w=g.arcs[i][j].adj ;
k++;
}
for(i=1;i<k;i++) /*按权值递增有序进行直接插入排序*/
{
temp=E[i];
j=i-1; /*从右向左在有序区e[0....i-1]中找e[i]的插入位置*/
while(j>=0&&temp.w<E[j].w)
{
E[j+1]=E[j]; /*将权值大于e[i].w的记录后移*/
j--;
}
E[j+1]=temp; /*在j+1处插入e[i]*/
}
}
void kruskal(edge E[],int n,int e)
{
int i,j,m1,m2,sn1,sn2,k;
int vset[MAX];
for(i=0;i<n;i++)vset[i]=i; /*初始化辅助数组*/
k=1; /*K表示当前构造的第几条边,初值为1*/
j=0; /*e中边的下标,初始值为0*/
while(k<n) /*生成的边数小于n时循环*/
{
m1=E[j].u;
m2=E[j].v; /*取一条边的头尾结点*/
sn1=vset[m1];
sn2=vset[m2]; /*分别得到两个顶点所属的集合编号*/
if(sn1!=sn2)
{
printf("(%d,%d):%d/n",m1,m2,E[j].w);
k++; /*生成边数增1*/
for(i=0;i<n;i++) /*两个集合统一编号*/
if(vset[i]==sn2) /*集合编号为sn2的改为sn1*/
vset[i]=sn1;
}
j++; /*扫描下一条边*/
}
}
/
typedef struct STACK /*定义栈类型*/
{
ElemType *base;
ElemType *top;
int stacksize;
int length;
}SqStack,*Stack;
void InitStack(Stack *S) /*初始化栈*/
{
*S=(SqStack *)malloc(sizeof(SqStack));
(*S)->base=(ElemType *)malloc(STACK_INIT_SIZE*sizeof(ElemType));
if(!(*S)->base)exit(-1);
(*S)->top=(*S)->base;
(*S)->stacksize=STACK_INIT_SIZE;
(*S)->length=0;
}
Status DestroyStack(Stack *S) /* 销毁栈*/
{
free((*S)->base);
free((*S));
return 1;
}
Status StackEmpty(SqStack S) /*判断栈空否*/
{
if(S.top==S.base) return 1;
else
return 0;
}
void Push(Stack *S,ElemType e) /*把数据压入栈*/
{
if((*S)->top - (*S)->base>=(*S)->stacksize)
{
(*S)->base=(ElemType *) realloc((*S)->base,
((*S)->stacksize + 10) * sizeof(ElemType));
if(!(*S)->base)exit(-1);
(*S)->top=(*S)->base+(*S)->stacksize;
(*S)->stacksize +=10;
}
*((*S)->top++)=e;
++(*S)->length;
}
Status Pop(Stack *S,ElemType *e)/*删除栈顶元素*/
{
if((*S)->top==(*S)->base) return 0;
*e=*((*S)->top-1);
--(*S)->length;
(*S)->top--;
return 1;
}
void FindInDegree(algraph G, int indegree[])//求入度操作
{
int i;
for (i = 1; i <= G.Arcnodes; i++)
{
indegree[i] = 0;
}
for (i = 1; i <= G.Arcnodes; i++)
{
while (G.adjlist[i].firstedge)
{
indegree[G.adjlist[i].firstedge->adjvex]++;
G.adjlist[i].firstedge = G.adjlist[i].firstedge->nextarc;
}
}
}
void FindInDegree1(MGraph G,int *indegree)/*对各顶点求入度,邻接矩阵的列*/
{
int i,j;
for(i=0;i<G.vexnum;i++)
for(j=0;j<G.vexnum;j++)
if(G.arcs[j][i].adj==1) indegree[i]++;
}
void CreatGraph(algraph *G)//构件图
{
int m, n, i;
Arcnode *p;
printf("请输入顶点数和边数:");
scanf("%d%d",&G->Arcnodes,&G->edges);
for (i = 1; i <= G->Arcnodes; i++)
{
G->adjlist[i].vertex = i;
G->adjlist[i].firstedge = NULL;
}
for (i = 1; i <= G->edges; i++) //输入存在边的点集合
{
printf("/n请输入存在边的两个顶点的序号:");
scanf("%d%d",&n,&m);
while (n < 0 || n > G->Arcnodes || m < 0 || m > G->Arcnodes)
{
printf("输入的顶点序号不正确 请重新输入:");
scanf("%d%d",&n,&m);
}
p = (Arcnode*)malloc(sizeof(Arcnode));
if (p == NULL)
{
printf("memory allocation failed,goodbey");
exit(1);
}
p->adjvex = m;
p->nextarc = G->adjlist[n].firstedge;
G->adjlist[n].firstedge = p;
}
printf("建立的邻接表为:/n"); //输出建立好的邻接表
for(i = 1; i <= G->Arcnodes; i++)
{
printf("%d",G->adjlist[i].vertex);
for(p = G->adjlist[i].firstedge; p; p = p->nextarc)
printf("%3d",p->adjvex);
printf("/n");
}
}
void TopologicalSort(algraph G) //进行拓扑排序
{
int indegree[M];
int i, k, n;
int count = 0;
Arcnode *p;
Stack S;
FindInDegree(G, indegree);
InitStack(&S);
for (i = 1; i <= G.Arcnodes; i++)
{
printf("第%d个点的入度为%d /n", i, indegree[i]);
}
printf("/n");
for ( i = 1; i <= G.Arcnodes; i++)
{
if (!indegree[i])
Push(&S,i);
}
printf("进行拓扑排序输出顺序为:"); //输出结果
while(!StackEmpty(*S))
{
Pop(&S,&n);
printf("%4d",G.adjlist[n].vertex);
count++;
for (p = G.adjlist[n].firstedge; p != NULL; p = p->nextarc)
{
k = p->adjvex;
if (!(--indegree[k]))
{
Push(&S,k);
}
}
}
printf("/n");
if (count < G.Arcnodes)
{
printf("出现错误/n");
}
else
{
printf("排序成功/n");
}
}
int *ve,*vl;/*最早发生时间和最迟发生时间数组*/
int TopologicalOrder(MGraph G,Stack *T)/*有向图采用矩阵存储结构,无回路返回1*/
{
Stack S;
int i,k,count,*indegree;
VertexType *p;
indegree=(int *)malloc(G.vexnum*sizeof(int));/*度数组空间*/
ve=(int *)malloc(G.vexnum*sizeof(int));/*最早发生时间的数组空间*/
for(i=0;i<G.vexnum;i++)
indegree[i]=0;/*初始化*/
for(i=0;i<G.vexnum;i++)
ve[i]=0;/*初始化*/
FindInDegree1(G,indegree);/*求各点入度*/
InitStack(&S);/*初始化栈*/
InitStack(T);
for(i=0;i<G.vexnum;++i)
if(!indegree[i]) Push(&S,i);/*入度为0进栈*/
count=0;/*对输出顶点计数*/
while(!StackEmpty(*S))
{
Pop(&S,&i);/*拿出入度为0 的*/
Push(T,i);/*i号顶点入T栈*/
++count;/*计数*/
p=G.vexs[i].next;
while(p)
{
k=LocateVex(G,*p);
if(!(--indegree[k])) Push(&S,k);/*减一后为0就入栈*/
if(ve[i]+G.arcs[i][k].adj>ve[k]) ve[k]=ve[i]+G.arcs[i][k].adj ;/*在它的所有邻点中找出能使最大*/
p=p->next;
}
}
DestroyStack(&S);
free(indegree);
if(count<G.vexnum) return 0;/*有向图有回路*/
else return 1;
}
int CriticalPath(MGraph G)/*G为有向网,输出G的各项关键活动*/
{
Stack T;
int j,dut,e1,e2,k=0;
char tag;
VertexType *p;
if(!TopologicalOrder(G,&T)) return 0;/*有回路就不做*/
vl=(int *)malloc(G.vexnum*sizeof(int));/*最迟发生时间数组空间*/
for(j=0;j<G.vexnum;j++)/*初始化事件的最迟发生时间*/
vl[j]=ve[j];
while(!StackEmpty(*T))/*按拓扑逆序求各事件的 vl 值*/
{
Pop(&T,&j);/*从最后一个开始*/
p=G.vexs[j].next;
while(p)
{
k=LocateVex(G,*p);/*邻点的位置*/
dut=G.arcs[j][k].adj;/*两点间的长度*/
if(vl[k]-dut>vl[j]) vl[j]=vl[k]-dut;
p=p->next;
}
}
for(j=0;j<G.vexnum;j++)
printf("事件 %s 的最早和最迟发生时间分别为 *%d* 和 *%d*/n",G.vexs[j].data,ve[j],vl[j]);
printf("关键活动为:/n");
for(j=0;j<G.vexnum;j++)/*求关键活动和它的值,顶点是事件,弧是活动*/
{
p=G.vexs[j].next;/*每个事件要依赖它的邻点才可知是否最早=最迟*/
while(p)
{
k=LocateVex(G,*p);/*邻点的位置*/
dut=p->info;/*弧长*/
e1=ve[j];e2=vl[k]-dut;/*如果最早开始时间=最迟开始时间,最迟为邻点减去弧长*/
if(e1==e2) tag='*';
else tag=' ';
if(tag=='*')
printf("*%s* 到 *%s* 长度为*%d* 发生时间为 *%d*/n",G.vexs[j].data,G.vexs[k].data,dut,e2);
p=p->next;
}
}
free(vl);free(ve);DestroyStack(&T);
return 1;
}
void ppath(int path[],int i,int v0)
{
int k;
k=path[i];
if(k==v0)
return;
ppath(path,k,v0);
printf("%d",k);
}
void DisPath(int dist[],int path[],int s[],int n,int v0)/*由path计算最短路径*/
{
int i;
printf("path:");
for(i=0;i<n;i++)
printf("%3d",path[i]);
printf("/n");
for(i=0;i<n;i++)
if(s[i]==1&&i!=v0)
{
printf("从%d到%d的最短路径长度为:%d/t路径为:",v0,i,dist[i]);
printf("%d",v0);
ppath(path,i,v0);
printf("%d/n",i);
}
else
printf("从%d到%d不存在路径/n",v0,i);
}
void Dijkstra(MGraph g,int v0)
{
int dist[MAXV],path[MAXV];
int s[MAXV];
int mindis,i,j,u,n=g.vexnum ;
for(i=0;i<n;i++)
{
dist[i]=g.arcs[v0][i].adj;
s[i]=0;
if(g.arcs[v0][i].adj<INFINITY)
path[i]=v0;
else
path[i]=-1;
}
s[v0]=1;path[v0]=0;
for(i=0;i<n;i++)
{
mindis=INFINITY;
u=-1;
for(j=0;j<n;j++)
if(s[j]==0&&dist[j]<mindis)
{
u=j;
mindis=dist[j];
}
s[u]=1;
for(j=0;j<n;j++)
if(s[j]==0)
if(g.arcs[u][j].adj<INFINITY&&dist[u]+g.arcs[u][j].adj<dist[j])
{
dist[j]=dist[u]+g.arcs[u][j].adj;
path[j]=u;
}
}
printf("输出最短路径:/n");
DisPath(dist,path,s,n,v0);
}
void UDG1()
{
MGraph MG;
algraph * ALG=new algraph;
int n;
do
{
cout<<"/n";
cout<<" ***************无向图的基本操作及应用***************/n";
cout<<" * 1 创建无向图的邻接矩阵 */n";
cout<<" * 2 创建无向图的邻接表 */n";
cout<<" * 3 无向图的深度优先遍历 */n";
cout<<" * 4 无向图的广度优先遍历 */n";
cout<<" * 5 退出 */n";
cout<<" ****************************************************/n";
cin>>n;
switch(n){
case 1:
CreateUDG(MG);
Display(MG);
break;
case 2:
CreateUDG_ALG(ALG);
dispgraph(ALG);
break;
case 3:
CreateUDG_ALG(ALG);
dispgraph(ALG);
int v;
printf("输入深度遍历的起始顶点:");
scanf("%d",&v);
printf("从顶点%d开始的DFS(递归算法):/n",v);
DFS(ALG,v);
break;
case 4:
CreateUDG_ALG(ALG);
dispgraph(ALG);
int u;
printf("输入宽度遍历的起始顶点:");
scanf("%d",&u);
printf("从顶点%d开始的BFS:/n",u);
BFS(ALG,u);
break;
default:
if (n!=5)
cout<<"错误,重新输入/n";
}
}while(n!=5);
}
void UDN1()
{
MGraph MN;
algraph * ALN=new algraph;
int n;
edge E[MAX];
do{
cout<<"/n";
cout<<" ***************无向网的基本操作及应用***************/n";
cout<<" * 1 创建无向网的邻接矩阵 */n";
cout<<" * 2 创建无向网的邻接表 */n";
cout<<" * 3 prim算法求最小生成树 */n";
cout<<" * 4 kraskal算法求最小生成树 */n";
cout<<" * 5 退出 */n";
cout<<" ****************************************************/n";
cin>>n;
switch(n){
case 1:
CreateUDN(MN);
Display(MN);
break;
case 2:
CreateUDN_ALG(ALN);
dispgraph(ALN);
break;
case 3:
CreateUDN(MN);
int u;
printf("输入起始顶点:");
scanf("%d",&u);
printf("/n");
printf("普里母算法求解最小生成树的结果:");
prim(MN,u);
break;
case 4:
CreateUDN(MN);
printf("克鲁斯卡尔算法求解最小生成树的结果:");
sortedge(MN,E);
kruskal(E,MN.vexnum,MN.arcnum);
break;
default:
if (n!=5)
cout<<"错误,重新输入/n";
}
}while(n!=5);
}
void DG1()
{
MGraph MG;
algraph * ALG=new algraph;
algraph G;
int n;
do
{
cout<<"/n";
cout<<" ***************有向图的基本操作及应用***************/n";
cout<<" * 1 创建有向图的邻接矩阵 */n";
cout<<" * 2 创建有向图的邻接表 */n";
cout<<" * 3 拓扑排序 */n";
cout<<" * 4 退出 */n";
cout<<" ****************************************************/n";
cin>>n;
Stack *T=new Stack;
switch(n){
case 1:
CreateDG(MG);
Display(MG);
break;
case 2:
CreateDG_ALG(ALG);
dispgraph(ALG);
break;
case 3:
CreatGraph(&G);
TopologicalSort(G);
break;
default:
if (n!=4)
cout<<"错误,重新输入/n";
}
}while(n!=4);
}
void DN1()
{
MGraph MN;
algraph * ALN=new algraph;
int n;
do{
cout<<"/n";
cout<<" ***************有向网的基本操作及应用***************/n";
cout<<" * 1 创建有向网的邻接矩阵 */n";
cout<<" * 2 创建有向网的邻接表 */n";
cout<<" * 3 关键路径 */n";
cout<<" * 4 单源顶点最短路径问题 */n";
cout<<" * 5 退出 */n";
cout<<" ****************************************************/n";
cin>>n;
Stack *T=new Stack;
switch(n){
case 1:
CreateDN(MN);
Display(MN);
break;
case 2:
CreateDN_ALG(ALN);
dispgraph(ALN);
break;
case 3:
CreateDN(MN);
CriticalPath(MN);
break;
case 4:
CreateDN(MN);
int u;
printf("输入起始顶点:");
scanf("%d",&u);
printf("/n");
Dijkstra(MN,u);
break;
default:
if (n!=5)
cout<<"错误,重新输入/n";
}
}while(n!=5);
}
void main()
{
int n;
do{
ShowMainMenu();
cin>>n;
switch(n){
case 1:
UDG1();
break;
case 2:
UDN1();
break;
case 3:
DG1();
break;
case 4:
DN1();
break;
default:
if (n!=5)
cout<<"错误,重新输入/n";
}
}while(n!=5);
}
无向网里面的关键路径貌似运行有错误,请高手帮忙指点