/*
题目2: 以邻接矩阵的方式确定有向网,完成:
⑴建立并显示出它的邻接链表;
⑵以非递归的方式进行深度优先遍历,显示遍历的结果,(并随时显示栈的入、出情况);
⑶对该图进行拓扑排序,显示拓扑排序的结果,并随时显示入度域的变化情况;
⑷给出某一确定顶点到所有其它顶点的最短路径
*/
#include<stdio.h>
#include<stdlib.h>
#define MAX_VERTEX_NUM 20 //最大顶点个数
#define STACK_INIT_SIZE 100 //存储空间初始分配量
#define STACKINCREMENT 10 //存储空间分配增量
#define OVERFLOW 0
#define ERROR 0
#define OK 1
#define INFINITY 100
typedef struct ArcCell //图的邻接矩阵结构定义
{
char adj; //顶点
int *info; //弧相关信息指针
}VertexNode;
typedef struct
{
VertexNode vexs[MAX_VERTEX_NUM]; //顶点向量
int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵
int vexnum,arcnum; //定点数和弧数
}MGraph;
typedef struct
{
int *base; //栈底指针
int *top; //栈顶指针
int stacksize; //存储空间
}SqStack;
int InitStack(SqStack &S) //构造一个空栈
{
S.base = (int *)malloc(STACK_INIT_SIZE *sizeof(int));
if(!S.base) //存储分配失败
return OVERFLOW;
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
return OK;
}
int StackEmpty(SqStack &S)
{
if(S.top==S.base) //空栈
return OK;
else
return ERROR;
}
int Push(SqStack &S,int e) //插入新的栈顶元素
{
if(S.top-S.base>=S.stacksize) //栈满,追加存储空间
{
S.base=(int *)realloc(S.base,(S.stacksize+STACKINCREMENT) *sizeof(int));
if(!S.base) //存储分配失败
return(OVERFLOW);
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}
*S.top++=e;
return OK;
}
int GetTop(SqStack &S,int &e)
{
if(S.top==S.base)
return ERROR;
e=*(S.top-1);
return e;
}
int Pop(SqStack &S,int &e) //删除栈顶元素
{
if(S.top==S.base)
return ERROR;
e=*--S.top;
return e;
}
void CreatGraph(MGraph *g)//邻接矩阵创建有向网
{
int i,j,m,r1,r2; //m权值
printf("请输入节点数:/n");
scanf("%d",&g->vexnum); //获取节点数
printf("请输入有向网顶点信息(空格间开):/n");
for(i=1;i<=g->vexnum;i++) //获取顶点信息
{
scanf("%s",&g->vexs[i].adj);
}
for(i=1;i<=g->vexnum;i++) //初始化邻接矩阵
for(j=1;j<=g->vexnum;j++)
{
g->arcs[i][j]=0;
}
printf("请输入权值信息(以弧尾值 弧头值 权值顺序,空格间开,0 0 0结束):/n");
scanf("%d%d%d",&r1,&r2,&m); //权值信息
while(r1!=0&&r2!=0&&m!=0) //生成邻接矩阵转
{
g->arcs[r1][r2]=m;
scanf("%d%d%d",&r1,&r2,&m);
}
}
void PrintGraph(MGraph *g)//打印有向网的邻接矩阵
{
int i,j;
for(i=1;i<=g->vexnum;i++)
{
for(j=1;j<=g->vexnum;j++)
{
printf("%2d ",g->arcs[i][j]);
}
printf("/n");
}
}
void PrintList(MGraph *g)//打印有向网的邻接表
{
int i,j;
for(i=1;i<=g->vexnum;i++)
{
printf("%s",&g->vexs[i].adj);
for(j=1;j<=g->vexnum;j++)
{
if(g->arcs[i][j]!=0) //获取非零值
{
printf("-->%s",&g->vexs[j].adj);
}
}
printf("-->NULL/n"); //一行结束,打印空
}
}
void DFSTraverse(MGraph *g) //非递归深度优先遍历
{
int visited[MAX_VERTEX_NUM],i=1,j,e=1; //visited[]标记向量,e出栈值
SqStack s;
InitStack(s);
Push(s,i); //首节点入栈
printf("插入栈顶元素:%d/n",i);
printf("-->%s/n",&g->vexs[i].adj);
visited[i]=1; //有输出,即为1
while(!StackEmpty(s))
{
i=e; //从e行开始
for(j=g->vexnum;j>=1;j--) //从右向左寻找
{
if(g->arcs[i][j]) //非零即入栈
{
Push(s,j);
printf("插入栈顶元素:%d/n",j);
}
}
Pop(s,e); //该行最左非零值入栈
printf("删除栈顶元素:%d/n",e);
if(visited[e]!=1) //未被标记
{
printf("-->%s/n",&g->vexs[e].adj);
visited[e]=1;
}
}
}
void FindInDegree(MGraph *g,int indegree[MAX_VERTEX_NUM]) //获取每个节点的入度,并存储在indegree数组中
{
int i,j,n; //n入度
for(i=1;i<=g->vexnum;i++)
{
n=0;
for(j=1;j<=g->vexnum;j++)
if(g->arcs[j][i]) //每行非零值个数
n++;
indegree[i]=n; //存储入度
}
}
int TopologicalSort(MGraph *g) // 拓扑排序
{
int indegree[MAX_VERTEX_NUM],i,j,k,count; //count输出顶点计数
SqStack S;
FindInDegree(g,indegree); //对各顶点求入度
InitStack(S);
for(i=1;i<=g->vexnum;i++) //建立零入度顶点栈
if(!indegree[i]) //入度为零入栈
Push(S,i);
count=0;
while(!StackEmpty(S))
{
Pop(S,i);
printf("/n-->%s",&g->vexs[i].adj);
++count;
for(j=1;j<=g->vexnum;j++)
{
if(g->arcs[i][j])
{
k=j;
if(!(--indegree[k]))
Push(S,k);
printf("/t此时%s入度:%d",&g->vexs[k].adj,indegree[k]);//若入度减为零,入栈
}
}
}
if (count<g->vexnum) //有回路
return ERROR;
else
return OK;
}
void ShortestPath_FLOYD(MGraph *g)//任意两点最短距离
{
int dist[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//dist[]两点间路径长度
int i,j,k;
for(i=1;i<=g->vexnum;i++) //初始化
for(j=1;j<=g->vexnum;j++)
dist[i][j]=g->arcs[i][j];
for(i=1;i<=g->vexnum;i++)
{
for(j=1;j<=g->vexnum;j++)
{
printf("%s-->%s:/t",&g->vexs[i].adj,&g->vexs[j].adj);
for(k=1;k<=g->vexnum;k++)
if(i!=j&&i!=k&&j!=k) //三点互不相同
{
if(dist[i][j]) //有直接路径
{
if(dist[i][k]&&dist[k][j])
if(dist[i][j]>dist[i][k]+dist[k][j]) //有中间更短路径
dist[i][j]=dist[i][k]+dist[k][j];
}
else
{
if(dist[i][k]&&dist[k][j])
dist[i][j]=dist[i][k]+dist[k][j];//取中间路径
}
}
printf("%d/n",dist[i][j]);
}
printf("/n");
}
}
void main()//主函数
{
MGraph *g=(MGraph *)malloc(sizeof(MGraph));
CreatGraph(g);
printf("***********************************************/n邻接矩阵输出:/n");
PrintGraph(g);
printf("***********************************************/n邻接链表输出:/n");
PrintList(g);
printf("***********************************************/n深度优先遍历:/n");
DFSTraverse(g);
printf("***********************************************/n拓扑排序:");
TopologicalSort(g);
printf("/n***********************************************/n最短路径:/n");
ShortestPath_FLOYD(g);
}