有向图邻接表求入度,出度,删除、增加顶点,弧,深度遍历及其生成树等

#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();
}

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/padanTao/article/details/4302929
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞