#include "stdio.h"
#include "math.h"
#include"malloc.h"
#include "stack"
#include <queue>
#define OK 1
#define ERROR -1
#define MAX 32764 // 最大值∞
//#define MaxLen 1000
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
#define MAX_VERTEX_NUM 50 // 最大顶点个数
typedef enum {DG, DN, AG, AN} GraphKind; //{有向图,有向网,无向图,无向网}
typedef int status;
typedef int VRType;
typedef int InfoType;
typedef char VertexType;
typedef char TElemType;
typedef char QElemType;
/*--------------------图的邻接矩阵存储表示---------------------*/
typedef struct ArcCell {
VRType adj; // VRType是顶点关系类型。对无权图,用1或0表示相邻否;
// 对带权图,则为权值类型。
InfoType *info; // 该弧相关信息的指针
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct{
VertexType vexs[MAX_VERTEX_NUM]; // 顶点向量
AdjMatrix arcs; // 邻接矩阵
int vexnum, arcnum; // 图的当前顶点数和弧数
GraphKind kind; // 图的种类标志
}MGraph;
/*------------------------图的邻接表存储表示-----------------*/
typedef struct ArcNode {
int weight;
int adjvex; // 该弧所指向的顶点的位置
struct ArcNode *nextarc; // 指向下一条弧的指针
InfoType *info; // 该弧相关信息的指针
}ArcNode;
typedef struct VNode {
VertexType data; // 顶点信息
ArcNode *firstarc; // 指向第一条依附该顶点的弧
}VNode, AdjList[MAX_VERTEX_NUM];
typedef struct {
AdjList vertices;
int vexnum, arcnum; // 图的当前顶点数和弧数
GraphKind kind; // 图的种类标志
}ALGraph;
/*------------------------树的孩子兄弟存储表示-----------------*/
typedef struct CSNode{
TElemType data;
struct CSNode *firstchild,*nextsibling;
} CSNode, *CSTree;
/*------------------------队列的存储结构-------------------------*/
typedef struct QNode{
QElemType data;
struct QNode *next;
} QNode, *QueuePtr;
typedef struct {
QueuePtr front;
QueuePtr rear;
} LinkQueue;
/*----------------------单链队列的相关算法-------------------------*/
//构造空队列
status InitQueue(LinkQueue &Q){
Q.rear=Q.front=(QueuePtr)malloc(sizeof(QNode));
if(!Q.front) return (OVERFLOW);
Q.front->next=NULL;
return OK;
}
//队是否为空
bool QueueEmpty(LinkQueue Q){
if(!Q.front->next)
return (true);
return (false);
}
//入队
status EQueue(LinkQueue &Q, QElemType e){
QNode *p;
p=(QNode *)malloc( sizeof(QNode));
if (!p) return (OVERFLOW);
p->data= e;
p->next=NULL;
Q.rear->next=p;
Q.rear=p;
return(OK);
}
//出队
status DeQueue(LinkQueue &Q, QElemType &e){
QNode *p;
if(!Q.front) return (OVERFLOW);
p=Q.front->next;
e=p->data;
Q.front->next=p->next;
if(Q.rear==p) Q.rear=Q.front;
free(p);
return (OK);
}
/*--------------------------栈的基本操作-------------------------------------------*/
//栈的存储结构
typedef char SElemType;
typedef struct {
SElemType *base; //栈底指针
SElemType *top; //栈顶指针
int stacksize; //栈的大小
}SqStack;
//构造空栈
status InitStack (SqStack &S){
S.base=(SElemType *)malloc(STACK_INIT_SIZE * sizeof(SElemType));
if (!S.base) return(OVERFLOW);
S.stacksize = STACK_INIT_SIZE;
S.top = S.base;
return(OK);
}
//出栈
status Pop(SqStack &S, SElemType &e){
if(S.base == S.top) return(ERROR);//栈空
e=*--S.top;
return(OK);
}
//入栈
status Push(SqStack &s,SElemType e)
{
if(s.top-s.base>=s.stacksize)
return OVERFLOW;
*s.top++=e;
return OK;
}
//销毁栈
status DestroyStack(SqStack &S)
{
S.top=NULL;
S.base=NULL;
delete[] S.base;
S.stacksize=0;
return OK;
}
//判断栈是否为空
int EmptyStack(SqStack s)
{
if(s.top==s.base) return 1;
else return 0;
}
//得到栈顶元素
status GetTop(SqStack &s,SElemType &e)
{
if(s.top==s.base) return ERROR;
e=*(s.top-1);
return OK;
}
//栈的长度
int StackLength(SqStack s)
{
return s.top-s.base;
}
//得到栈的所有元素值
status Get(SqStack s){
int i,n;
n=StackLength(s);
if(!n) return ERROR;
for(i=0;i<n;i++)
printf("%c/t",*(s.base+i));
return OK;
}
/*-----------------------创建有向图的邻接矩阵-----------------*/
//元素在图中的位置
int locateMG(MGraph g,VertexType v){
for(int i=0;i<g.vexnum;i++){
if(g.vexs[i]==v)
return i;
}
return -1;
}
//边是否存在
status arcExist(MGraph g,int i,int j){
if(g.arcs[i][j].adj==MAX)
return 0;
return 1;
}
//图是否存在
int ExistM(MGraph g){
if(g.vexnum<0){
printf("图不存在,请先创建图/n");
return 0;
}
return 1;
}
//创建有向图的邻接矩阵
status createMDG(MGraph &g){
int i,j,k,n,l;
VertexType v,v1,v2;
printf("请输入有向图的顶点数:");
scanf("%d",&g.vexnum);
i=g.vexnum*(g.vexnum-1);
printf("请输入有向图的弧数:");
scanf("%d",&g.arcnum);
while(g.arcnum>i){
printf("/n输入有误,边数不能超过%d,请重新输入!",i);
printf("/n请输入有向图的弧数:");
scanf("%d",&g.arcnum);
}
for(i=0;i<g.vexnum;i++)//初始化邻接矩阵
for(j=0;j<g.vexnum;j++)
g.arcs[i][j].adj=MAX;
printf("请依次输入有向图的各个顶点(用回车分隔):");
for(i=0;i<g.vexnum;i++){//输入顶点信息
getchar();
scanf("%c",&v);
l=locateMG(g,v);
if(l>0){
printf("输入的顶点重复,请重新输入/n");
i--;
continue;
}
g.vexs[i]=v;
}
for(k=1;k<=g.arcnum;k++){//构造邻接矩阵
getchar();
printf("请输入第%d条弧的起点与终点(用逗号分隔):",k);
scanf("%c,%c",&v1,&v2);
i=locateMG(g,v1);
j=locateMG(g,v2);
if(i<0||j<0||i==j||arcExist(g,i,j)){
printf("输入错误,请重新输入/n");
k--;
continue;
}
printf("请输入第%d条弧的权值:",k);
scanf("%d",&n);
g.arcs[i][j].adj=n;
}
printf("有向图的邻接矩阵创建成功/n");
return OK;
}
/*---------------------创建有向图的邻接表--------------------*/
//元素在图中的位置
int locateALG(ALGraph g,VertexType v){
for(int i=0;i<g.vexnum;i++){
if(g.vertices[i].data==v)
return i;
}
return -1;
}
//当前有向图中是否存在边<i,j>
int GraphExist(ALGraph G,int i,int j){
ArcNode *s;
s=G.vertices[i].firstarc;
while(s&&s->adjvex!=j)
s=s->nextarc;
if(s) return 1;
else return 0;
}
//图是否存在
int ExistG(ALGraph g){
if(g.vexnum<0){
printf("图不存在,请先创建图/n");
return 0;
}
return 1;
}
status CreateADG(ALGraph &g){
int i,j,k,l,n;
ArcNode *p;
VertexType v1,v2;
char c;
printf("请输入有向图的顶点数:");
scanf("%d",&g.vexnum);
while(g.vexnum>MAX_VERTEX_NUM){
printf("/n输入有误,顶点数不能超过%d,请重新输入!",MAX_VERTEX_NUM);
printf("/n请输入有向图的顶点数:");
scanf("%d",&g.vexnum);
}
i=g.vexnum*(g.vexnum-1);
printf("请输入有向图的边数:");
scanf("%d",&g.arcnum);
while(g.arcnum>i){
printf("/n输入有误,边数不能超过%d,请重新输入!",i);
printf("/n请输入有向图的边数:");
scanf("%d",&g.arcnum);
}
printf("请依次输入有向图的各个顶点(用回车分隔):");
for(i=0;i<g.vexnum;i++){//输入顶点信息
getchar();
scanf("%c",&c);
l=locateALG(g,c);
if(l>=0){
printf("输入的顶点重复,请重新输入/n");
i--;
continue;
}
g.vertices[i].data=c;
g.vertices[i].firstarc=NULL;
}
for(k=0;k<g.arcnum;k++){//输入边的信息
getchar();
printf("请输入第%d条弧的起点与终点(用逗号分隔):",k+1);
scanf("%c,%c",&v1,&v2);
i=locateALG(g,v1);
j=locateALG(g,v2);
if(i<0||j<0||i==j||GraphExist(g,i,j)){
printf("输入错误,请重新输入/n");
k--;
continue;
}
p=(ArcNode*)malloc(sizeof(ArcNode));//建立结点
if(!p) return ERROR;
printf("请输入第%d条弧的权值:",k+1);
scanf("%d",&n);
p->adjvex=j;
p->nextarc=g.vertices[i].firstarc;//顶点i的链表
g.vertices[i].firstarc=p;//添加到最左边
p->weight=n;
}
printf("有向图的邻接表创建成功/n");
return OK;
}
/*------------------------------输出图的信息-------------------*/
void printGra(ALGraph G){
ArcNode *p;
int i;
printf("图中有%d个顶点,%d条弧:/n",G.vexnum,G.arcnum);
for(i=0;i<G.vexnum;i++){
p=G.vertices[i].firstarc;
printf("%c/t",G.vertices[i].data);
while(p){
printf("<%c,%c,%d>/t",G.vertices[i].data,G.vertices[p->adjvex].data,p->weight);
p=p->nextarc;
}
printf("/n");
}
}
void printMg(MGraph g){
int i,j;
for(i=0;i<g.vexnum;i++){
printf("%c/t",g.vexs[i]);
for(j=0;j<g.vexnum;j++)
{
if (g.arcs[i][j].adj!=MAX)
printf("<%c,%c,%d>/t",g.vexs[i],g.vexs[j],g.arcs[i][j].adj);
}
printf("/n");
}
}
/*--------------------邻接表深度优先遍历并判断图的连通性 -----------------*/
ArcNode *nextnode=NULL;//全局变量
bool visited[21];//全局变量
//得到i号顶点的第一个邻接点
int FirstAdjVex(ALGraph g,int i){
ArcNode *p;
p=g.vertices[i].firstarc;
if(!p) return -1;
nextnode=p->nextarc;
return(p->adjvex);
}
//得到i号顶点的下一个邻接点
int NextAdjVex(ALGraph g,int i){
if(!nextnode) return -1;
int m=nextnode->adjvex;
nextnode=nextnode->nextarc;
return m;
}
//访问图中的i号顶点
void visitvex(ALGraph g,int i){
printf("%c/t",g.vertices[i].data);
}
//从图某个顶点进行深度优先遍历
int DFS(ALGraph g,int i){
int w;
visited[i]=true;
visitvex(g,i);
for(w=FirstAdjVex(g,i);w>=0;w=NextAdjVex(g,i))
if(!visited[w]) DFS(g,w);
return OK;
}
//对图进行深度优先遍历
status DFSTraverse(ALGraph g){
int v,u,x;
int count[100];
for(v=0;v<g.vexnum;v++){
count[v]=0;
printf("从%c开始深度优先遍历的结果:",g.vertices[v].data);
for(u=0;u<g.vexnum;u++) visited[u]=false;
for(x=v;x<g.vexnum+v;x++){
int a;
a=x;
a=a%g.vexnum;
if(!visited[a]){
DFS(g,a);
count[v]++;
}
}
printf("/n");
}
int min;
min=count[0];
for(int i=0;i<g.vexnum;i++){
if(min>count[i])
min=count[i];
}
if(min!=1)
printf("/n该有向图是不连通图!连通分量为:%d/n",min);
else
printf("/n该有向图是连通图!/n");
return OK;
}
/*---------------------返回当前有向图中的每个顶点的入度与出度----------------*/
//图中某个顶点的入度
status InDegree(ALGraph G,int i){
int j;
int n=0;
for(j=0;j<G.vexnum;j++){
if(GraphExist(G,j,i)) n++;
}
return n;
}
//图中某个顶点的出度
status OutDegree(ALGraph G,int i){
ArcNode *p;
int j=0;
p=G.vertices[i].firstarc;
while(p!=NULL){
j++;
p=p->nextarc;
}
return j;
}
//每个顶点的与出度入度
void degree(ALGraph G){
int i,n,m;
char a;
for(i=0;i<G.vexnum;i++){
a=G.vertices[i].data;
n=InDegree(G,i);
m=OutDegree(G,i);
printf("顶点%c的入度是%d,出度是%d/n",a,n,m);
}
}
/*-------------------------------当前有向图插入弧-----------------------*/
int GraphAdd(ALGraph &G){
int n,k,i,j,w;
ArcNode *p;
VertexType v1,v2;
k=G.vexnum*(G.vexnum-1)-G.arcnum;
printf("请输入要增加的弧数:");
scanf("%d",&n);
while(n>k){
printf("/n输入有误,增加的边数不能超过%d,请重新输入!",k);
printf("/n请输入有向图的边数:");
scanf("%d",&n);
}
for(k=0;k<n;k++){
getchar();
printf("请输入要增加的弧的起点与终点(用逗号分隔):");
scanf("%c,%c",&v1,&v2);
i=locateALG(G,v1);
j=locateALG(G,v2);
if(i<0||j<0||i==j||GraphExist(G,i,j)){
printf("输入有误,请重新输入/n");
k--;
continue;
}
printf("请输入第%d条弧的权值:",k+1);
scanf("%d",&w);
p=new ArcNode;
p->adjvex=j;
p->weight=w;
p->nextarc=G.vertices[i].firstarc;
G.vertices[i].firstarc=p;
G.arcnum++;
printf("插入弧成功/n");
}
return 1;
}
/*--------------------------当前有向图中插入顶点-----------------------*/
int NodeAdd(ALGraph &G){
int i,l,n;
char c;
printf("请输入要增加的顶点个数:");
scanf("%d",&n);
//增加的定点个数判断
if(G.vexnum+n>MAX_VERTEX_NUM){
printf("输入错误,最多有50个顶点/n");
return ERROR;
}
for(i=0;i<n;i++){//输入顶点信息
getchar();
printf("请输入要增加的顶点:");
scanf("%c",&c);
l=locateALG(G,c);
if(l>=0){
printf("输入的顶点重复,请重新输入/n");
i--;
continue;
}
G.vertices[G.vexnum].data=c;
G.vertices[G.vexnum].firstarc=NULL;
G.vexnum++;
printf("增加顶点成功/n");
}
return OK;
}
/*---------------------------当前有向图删除弧-------------------*/
int delArc(ALGraph &G,int i,int j){
ArcNode *p,*q;
p=G.vertices[i].firstarc;
if(p->adjvex==j){
G.vertices[i].firstarc=p->nextarc;
free(p);
}
else{
while(p->nextarc&&p->nextarc->adjvex!=j)
p=p->nextarc;
if(p){
q=p->nextarc;
p->nextarc=q->nextarc;
free(q);
}
}
G.arcnum--;
return OK;
}
int GraphDel(ALGraph &G){
int n,k,i,j;
VertexType v1,v2;
printf("请输入要删除的弧数:");
scanf("%d",&n);
while(n>G.arcnum){
printf("删除的弧数不能超过%d,请重新输入/n",G.arcnum);
printf("请输入要删除的弧数:");
scanf("%d",&n);
}
for(k=0;k<n;k++){
getchar();
printf("请输入要删除的弧的起点与终点(用逗号分隔):");
scanf("%c,%c",&v1,&v2);
i=locateALG(G,v1);
j=locateALG(G,v2);
if(i<0||j<0||i==j||(!GraphExist(G,i,j))){
printf("输入有误,请重新输入/n");
k--;
continue;
}
delArc(G,i,j);
}
return 1;
}
/*---------------------------当前有向图删除顶点-------------------*/
int NodeDel(ALGraph &G){
int i,l,n,k;
char c;
ArcNode *p;
printf("请输入要删除的顶点个数:");
scanf("%d",&n);
if(n>G.vexnum){
printf("输入错误/n");
return ERROR;
}
for(k=0;k<n;k++){//输入要删除顶点信息
getchar();
printf("请输入要删除的顶点:");
scanf("%c",&c);
l=locateALG(G,c);
if(l<0){
printf("输入的顶点不存在,请重新输入/n");
k--;
continue;
}
for(i=0;i<G.vexnum;i++){
//删除与此顶点相关的弧
if(GraphExist(G,i,l)){
delArc(G,i,l);
}
if(GraphExist(G,l,i)){
delArc(G,l,i);
}
//修改必要表结点的顶点的位置值
p=G.vertices[i].firstarc;
while(p){
if(p->adjvex>l){ p->adjvex--;
}
p=p->nextarc;
}
}
//释放空间,顶点c后的顶点前移
for(i=l;i<G.vexnum-1;i++){
G.vertices[i]=G.vertices[i+1];
}
G.vexnum--;
printf("删除顶点成功/n");
}
return OK;
}
/*--------------------------存储结构的转换-----------------------*/
//将邻接表转换成邻接矩阵
status TranlateAl(ALGraph G1, MGraph &G2){
//设置参数
int i,j;
ArcNode *p;
G2.kind = G1.kind;
G2.vexnum = G1.vexnum;
G2.arcnum = G1.arcnum;
//复制顶点
for(i=0;i<G1.vexnum;i++)
G2.vexs[i] = G1.vertices[i].data;
//复制弧
for(i=0;i<G2.vexnum;i++)
for(j=0;j<G2.vexnum;j++)
G2.arcs[i][j].adj=MAX;
for(i=0;i<G1.vexnum;i++){//复制G1每个顶点的邻接点
p=G1.vertices[i].firstarc;
while(p){
G2.arcs[i][p->adjvex].adj=p->weight;
p=p->nextarc;
}
}
printf("转换成功/n");
return OK;
}
//将邻接矩阵转换成邻接表
status TranlateDG(MGraph G1,ALGraph &G2){
int i,j;
ArcNode *p;
//设置参数
G2.kind= G1.kind;
G2.vexnum = G1.vexnum;
G2.arcnum = G1.arcnum;
//复制顶点
for(i=0;i<G1.vexnum;i++){
G2.vertices[i].data=G1.vexs[i];
G2.vertices[i].firstarc=NULL;
}
//复制弧
for(i=0;i<G1.vexnum;i++){
for(j=0;j<G1.vexnum;j++){
if(G1.arcs[i][j].adj!=MAX){
p=(ArcNode*)malloc(sizeof(ArcNode));//建立结点
if(!p) return ERROR;
p->weight=G1.arcs[i][j].adj;
p->adjvex=j;
p->nextarc=G2.vertices[i].firstarc;//顶点i的链表
G2.vertices[i].firstarc=p;//添加到最左边
}
}
}
printf("转换成功/n");
return OK;
}
/*-----------------深度优先生成树-------------------*/
char GetVex(ALGraph G,int i){
return G.vertices[i].data;
}
void DFSTree(ALGraph G,int i, CSTree &T){
//从第i个顶点出发深度优先遍历有向图G,建立以T为根的生成树
int w;
CSNode *p,*q;
visited[i]=true;
bool first=true;
for(w=FirstAdjVex(G,i);w>=0;w=NextAdjVex(G,i))
if(!visited[w]){
p=(CSTree)malloc(sizeof(CSNode));
p->data=GetVex(G,w);
p->firstchild=NULL;
p->nextsibling=NULL;
if(first){ //w是i的第一个未被访问的邻接顶点
T->firstchild=p;//是根的左孩子结点
first=false;
}
else{ //w是i的其他未被访问的邻接顶点
q->nextsibling=p; //是上一邻接顶点的右兄弟结点
}
q=p;
DFSTree(G,w,q);
}
}
status DFSforest(ALGraph G,CSTree &T){
//建立有向图的深度优先生成森林/生成树
int i;
CSNode *p,*q;
T=NULL;
for(i=0;i<G.vexnum;i++) visited[i]=false;
for(i=0;i<G.vexnum;i++)
if(!visited[i]){ //第i顶点为新的生成树的根节点
p=(CSTree)malloc(sizeof(CSNode));
p->data=GetVex(G,i);
p->firstchild=NULL;
p->nextsibling=NULL;
if(!T) T=p; //是第一棵生成树的根(T的根)
else q->nextsibling=p; //是其他生成树的根
q=p; //q指示当前生成树的根
DFSTree(G,i,p); //建立以p为根的生成树
}
printf("图的深度优先生成森林成功/n");
return OK;
}
//树的先根遍历
void Preorder(CSTree T){
if (!T) return;
printf("%c/t",T->data); // 访问根结点
Preorder(T->firstchild); // 遍历左子树
Preorder(T->nextsibling); // 遍历右子树
}
/*---------------------是否存在路径,并输出一条简单路径-------------------*/
//判断有向图G中顶点i到顶点j是否有路径
status DfsReachable(ALGraph g, int i, int j){
int n,k;
LinkQueue Q;
ArcNode *p;
char v,v1;
InitQueue(Q);
v1=g.vertices[i].data;
EQueue(Q,v1);
while(!QueueEmpty(Q)){ //队列不空时循环
DeQueue(Q,v);
n=locateALG(g,v);
visited[n]=true;
for(p=g.vertices[n].firstarc;p;p=p->nextarc){
k=p->adjvex;
v=g.vertices[k].data;
if(j==k){
return 1;
}
if(!visited[k]){
EQueue(Q,v);
}
}
}
return 0;
}
//找简单路径
bool found;
void reacher(ALGraph G,int i,int j,SqStack &s){
VertexType v;
int w;
ArcNode *p;
visited[i]=true;
v=G.vertices[i].data;
Push(s,v);
for(p=G.vertices[i].firstarc;p;p=p->nextarc){
int k=p->adjvex;
if(!found){
v=G.vertices[k].data;
if(j==k){
found=true;
Push(s,v);
break;
}
else
if(!visited[k]){
reacher(G,k,j,s);
}
}
}
if(!found){
Pop(s,v);
}
}
int exist_path(ALGraph G){
SqStack s;
InitStack(s);
int n,i,j;
VertexType v1,v2;
found=false;
for(n=0;n<G.vexnum;n++)
visited[n]=false;
printf("请输入起点与终点(用逗号分隔):");
getchar();
scanf("%c,%c",&v1,&v2);
i=locateALG(G,v1);
j=locateALG(G,v2);
if (i<0||j<0||i==j)
{
printf("输入错误/n");
return -1;
}
if(DfsReachable(G,i,j)){
for(n=0;n<G.vexnum;n++)
visited[n]=false;
reacher(G,i,j,s);
printf("顶点%c到顶点%c存在路径,其一条简单路径为:",v1,v2);
Get(s);
DestroyStack(s);
}
else
printf("顶点%c到顶点%c不存在路径/n",v1,v2);
return OK;
}
/*--------------------------拓扑排序判断是否存在环--------------*/
status ToplogicalSort(ALGraph G){
char v;
LinkQueue Q;
ArcNode *p;
int k;
int i,j;
int n=G.vexnum;
int indegree[21];
for(i=0;i<n;i++)
indegree[i]=InDegree(G,i);
InitQueue(Q);
for(i=0;i<n;i++){
if(!indegree[i]){
v=G.vertices[i].data;
EQueue(Q,v);
}
}
int count=0; //对输出顶点计数
while (!QueueEmpty(Q)){
DeQueue(Q,v);
++count;
j=locateALG(G,v);
for(p=G.vertices[j].firstarc;p;p=p->nextarc){
k=p->adjvex;
--indegree[k]; // 弧头顶点的入度减1
if(!indegree[k]){
v=G.vertices[k].data;
EQueue(Q,v);
}
}
}//while
if (count<n){
printf("此有向图中存在环/n");
return ERROR;
}
printf("此有向图中不存在环/n");
return OK;
}
/*---------------------源点到其他顶点的最短路径----------------------*/
int prev[50];//prev[v]表示从源s到顶点v的最短路径上顶点的前驱顶点。
bool P[50][50]; //p[i][w]为true时w为v到i当前求的最短路径上的顶点
int D[50]; //D[w]存放顶点w的权值
//得到边<i,j>的权值
int getWei(ALGraph G,int i,int j){
ArcNode *s;
s=G.vertices[i].firstarc;
while(s&&s->adjvex!=j){
s=s->nextarc;
}
if(s) return s->weight;
else return MAX;
}
void ShortestPath_DIJ(ALGraph G,int v){
int i=0,j,v0,w,min;
bool final[50]; //当final[w]为true,已经求的从v到w得最短路径
for(v0=0;v0<G.vexnum;v0++){
prev[v0]=-1;
final[v0]=false;
D[v0]=getWei(G,v,v0);
for(w=0;w<G.vexnum;++w) P[v0][w]=false; // 设空路径
if(D[v0]<MAX){ //顶点i与源点v邻接
prev[v0]=v;
P[v0][v]=true;
P[v0][v0] =true;
}
}
D[v]=0; final[v]=true;
//主循环,每次求得v0到某个顶点v的最短路径,并将v加到S集中
for(i=1;i<G.vexnum;++i){
//当前所知离v顶点的最近距离
min=MAX;
for(w=0;w<G.vexnum;++w){
if(!final[w])
if(D[w]<min){
v0=w; min=D[w];
}
}
if(v0==G.vexnum){
break;
}
final[v0]=true; //更新当前最短路径及距离
for(w=0;w<G.vexnum;++w)
if(!final[w]&&(min+getWei(G,v0,w)<D[w])){
prev[w]=v0;
D[w]=min+getWei(G,v0,w);
for(j=0;j<G.vexnum;j++) P[w][j]=P[v0][j];
P[w][w]=true;
}//if
}//for
}
//输出最短路径
void printPath(ALGraph G,int v){
int i,k;
SqStack s;
InitStack(s);
SElemType a;
for(i=0;i<G.vexnum;i++){
if(i!=v){
if(D[i]!=MAX){
printf("%c到%c的最短路径长度为:%d/n",G.vertices[v].data,G.vertices[i].data,D[i]);
printf("%c到%c的最短路径为:",G.vertices[v].data,G.vertices[i].data);
a=G.vertices[i].data;
Push(s,a);
for(k=prev[i];k>-1;k=prev[k]){
a=G.vertices[k].data;
Push(s,a);
}//for(k)
while(!EmptyStack(s)){
Pop(s,a);
printf("%c/t",a);
}//while
printf("/n");
}//if(D[i]!=MAX)
else
printf("%c到%c不存在最短路径/n",G.vertices[v].data,G.vertices[i].data);
}//if(i!=v)
}//for(i)
}
/*---------------------任两点间的最短路径----------------------*/
void AllShortestPath(ALGraph G){
int i;
for(i=0;i<G.vexnum;i++){
ShortestPath_DIJ(G,i);
printPath(G,i);
}
}
/*-------------------------菜单----------------------*/
void menu(){
MGraph m;
ALGraph a;
CSTree T=NULL;
int n;
while(n){
printf("/n");
printf("/t****************************选择菜**********************************/n");
printf("/t/t/t1:创建有向图的邻接表/n");
printf("/t/t/t2:创建有向图的邻接矩阵/n");
printf("/t/t/t3:求每个顶点的入度,出度/n");
printf("/t/t/t4:深度优先遍历有向图,并判断其连通性/n");
printf("/t/t/t5:在有向图中插入弧/n");
printf("/t/t/t6:在有向图中删除弧/n");
printf("/t/t/t7:在有向图中插入顶点/n");
printf("/t/t/t8:在有向图中删除顶点/n");
printf("/t/t/t9:邻接矩阵转换成邻接表/n");
printf("/t/t/t10:邻接表转换成邻接矩阵/n");
printf("/t/t/t11:有向图深度优先生成树,并进行遍历/n");
printf("/t/t/t12:判断有向图中是否存在环/n");
printf("/t/t/t13:两顶点是否存在路径,存在时输出一条简单路径/n");
printf("/t/t/t14:某顶点到其他顶点的最短路径/n");
printf("/t/t/t15:任两点间的最短路径/n");
printf("/t/t/t0:退出/n");
printf("/t********************************************************************/n");
printf("请选择菜单号:");
scanf("%d",&n);
switch(n){
case 1:
CreateADG(a);
printGra(a);
break;
case 2:
createMDG(m);
break;
case 3:
if(!ExistG(a))
break;
printGra(a);
degree(a);
break;
case 4:
if(!ExistG(a))
break;
printGra(a);
DFSTraverse(a); break;
case 5:
if(!ExistG(a))
break;
GraphAdd(a);
printGra(a); break;
case 6:
if(!ExistG(a))
break;
GraphDel(a);
printGra(a); break;
case 7:
if(!ExistG(a))
break;
NodeAdd(a);
printGra(a); break;
case 8:
if(!ExistG(a))
break;
NodeDel(a);
printGra(a); break;
case 9:
if(!ExistM(m))
break;
TranlateDG(m,a);
printGra(a);
break;
case 10:
if(!ExistG(a))
break;
TranlateAl(a,m);
printMg(m);
break;
case 11:
if(!ExistG(a))
break;
printGra(a);
DFSforest(a,T);
printf("对生成树进行遍历的结果:");
Preorder(T); break;
case 12:
if(!ExistG(a))
break;
printGra(a);
ToplogicalSort(a); break;
case 13:
if(!ExistG(a))
break;
printGra(a);
exist_path(a); break;
case 14:
if(!ExistG(a))
break;
SqStack s;
InitStack(s);
char c;
int m;
printGra(a);
printf("请输入源点:");
getchar();
scanf("%c",&c);
m=locateALG(a,c);
if(m<0){
printf("输入错误/n");
break;
}
ShortestPath_DIJ(a,m);
printPath(a,m);
break;
case 15:
if(!ExistG(a))
break;
printGra(a);
AllShortestPath(a); break;
default:
break;
}
}
}
void main(){
menu();
}