有向圖鄰接表求入度,出度,刪除、增加頂點,弧,深度遍歷及其生成樹等
#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();
}