您的位置:首页 > 理论基础 > 数据结构算法

算法与数据结构--图的实现、基本操作及应用

2014-05-28 16:12 567 查看
#include<iostream>
#include<queue>
#include<stack>
using namespace std;

#define INFINITY DBL_MAX     //无穷大
#define MAX_VERTEX_NUM 20 //最大顶点个数
enum GraphKind //图的类型
{
DG,DN,UDG,UDN//有向图、有向网、无向图、无向网
};

//弧结构
typedef struct ArcCell
{
double adj;//权值,无权图用1表示
}AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
//邻接矩阵图结构
struct MGraph
{
int vexs[MAX_VERTEX_NUM];//顶点集合
AdjMatrix arecs;//邻接矩阵
int vexnum,arcnum;//顶点数、弧数
GraphKind kind;//图的类型
};

//表节点
struct ArcNode
{
int adjvex;//弧的顶点位置
ArcNode * nextarc;
double adj;//弧的权值
};
//头节点
typedef struct VNode
{
int data;//顶点序号信息
ArcNode * firstarc;
}AdjList[MAX_VERTEX_NUM];
//邻接表
struct ALGraph
{
int vexs[MAX_VERTEX_NUM];//顶点集合
AdjList vertices; //邻接链表
int vexnum,arcnum;//顶点数、弧数
int kind;//图的类型
};

//显示主菜单
void ShowMainMenu()
{
cout<<"\n";
cout<<"  ***************图的基本操作及应用******************\n";
cout<<"  *  1 无向图的基本操作及应用                      *\n";
cout<<"  *  2 有向图的基本操作及应用                      *\n";
cout<<"  *  3 无向网的基本操作及应用                      *\n";
cout<<"  *  4 有向网的基本操作及应用                      *\n";
cout<<"  *  5 退出                                        *\n";
cout<<"  ***************************************************\n";
}
/*
*无向图的函数集
*/
//创建无向图的邻接矩阵
bool CreatUDG_M(MGraph & MG)
{
MG.kind = UDG;
cout<<"请输入该无向图的顶点个数、弧的条数:"<<endl;
cin>>MG.vexnum>>MG.arcnum;
//初始化顶点集合
cout<<"依次输入顶点序号"<<endl;
for(int i = 0;i<MG.vexnum;i++)  cin>>MG.vexs[i];
//初始化邻接矩阵
for(int i = 0;i<MG.vexnum;i++)
{
for(int j = 0;j<MG.vexnum;j++)
{
MG.arecs[i][j].adj = INFINITY;
}
}
//构造邻接矩阵
for(int i = 0;i<MG.arcnum;i++)
{
int v1,v2;
cout<<"依次输入弧的两个顶点序号:"<<endl;
cin>>v1>>v2;
int *p1 = find(MG.vexs,MG.vexs+MG.vexnum,v1);
int *p2 = find(MG.vexs,MG.vexs+MG.vexnum,v2);
if(p1==MG.vexs+MG.vexnum||p2==MG.vexs+MG.vexnum) return false;
MG.arecs[(p1-MG.vexs)][(p2-MG.vexs)].adj = 1;
//无向图的邻接矩阵是对称矩阵
MG.arecs[(p2-MG.vexs)][(p1-MG.vexs)].adj = 1;
}
//输出该邻接矩阵
cout<<"该邻接矩阵为(-1代表无穷大):"<<endl;
for(int i = 0;i<MG.vexnum;i++)
{
for(int j = 0;j<MG.vexnum;j++)
{
if(MG.arecs[i][j].adj==INFINITY) cout<<"∞  ";
else
{
cout<<MG.arecs[i][j].adj<<"  ";
}
}
cout<<endl;
}
return true;
}
//创建无向图的邻接表
bool CreatUDG_ALG(ALGraph & ALG)
{
ALG.kind =  UDG;
cout<<"请输入该无向图的顶点个数、弧的条数:"<<endl;
cin>>ALG.vexnum>>ALG.arcnum;
//初始化顶点集合
cout<<"依次输入顶点序号"<<endl;
for(int i = 0;i<ALG.vexnum;i++)  cin>>ALG.vexs[i];
//构造邻接表
for(int i  = 0;i<ALG.vexnum;i++)
{
//初始化头结点的data信息
ALG.vertices[i].data = ALG.vexs[i];
ALG.vertices[i].firstarc = 0;
//循环输入该头结点的邻接弧
cout<<"输入与序号为"<<ALG.vexs[i]<<"节点相邻的节点序号"<<endl;
int v1;
ArcNode * rp = ALG.vertices[i].firstarc;
while (cin>>v1)
{

int *p1 =  find(ALG.vexs,ALG.vexs+ALG.vexnum,v1);
if(p1==ALG.vexs+ALG.vexnum)return false;
ArcNode *pA = (ArcNode *)malloc(sizeof(ArcNode));
if(!pA) return false;
pA->adj = 1;
pA->adjvex = p1-ALG.vexs;
pA->nextarc = 0;
if(0==ALG.vertices[i].firstarc) {ALG.vertices[i].firstarc = pA; rp = pA;}
else{rp->nextarc = pA; rp = pA;}
}
cin.clear();//清空输入流
}
//输出邻接表
for(int i  = 0;i<ALG.vexnum;i++)
{
cout<<"'"<<ALG.vexs[i]<<"'";
for(ArcNode * rp = ALG.vertices[i].firstarc;rp!=0;rp = rp->nextarc)
{
cout<<"--->"<<(*rp).adjvex;
}
cout<<endl;
}
return true;
}
//无向图的深度优先遍历
void Visit_fun(int & t)
{
t++;
}
void UDG_DFS(ALGraph &ALG,int v,bool visited[],void(*visit)(int& t))
{
visited[v] = true;visit(ALG.vexs[v]);
for(ArcNode * rp = ALG.vertices[v].firstarc;rp!=0;rp = rp->nextarc)
{
if(!visited[(*rp).adjvex]) UDG_DFS(ALG,(*rp).adjvex,visited,visit);
}
}
void UDG_DFSTraverse(ALGraph &ALG,void(*visit)(int &t))
{
bool *visited = new bool[ALG.vexnum];
for(int i = 0;i<ALG.vexnum;i++) visited[i] =  false;
for(int i = 0;i<ALG.vexnum;i++)
{
if(!visited[i]) UDG_DFS(ALG,i,visited,visit);
}

//测试数据序号是否都被修改
cout<<"测试结果(遍历每个节点,并将节点的序号加一):"<<endl;
for(int i = 0;i<ALG.vexnum;i++)
{
cout<<ALG.vexs[i]<<"  "<<endl;
}
}
//无向图的广度优先遍历
void UDG_BFSTraverse(ALGraph &ALG,void(*visit)(int &t))
{
//辅助访问数组
bool *visited = new bool[ALG.vexnum];
for(int i = 0;i<ALG.vexnum;i++) visited[i] =  false;
//辅助队列
queue<int> Queue;
for(int i= 0;i<ALG.vexnum;i++)
{
if(!visited[i])
{ visited[i] = true;
//先访问再如队列
visit(ALG.vexs[i]);
Queue.push(i);
while (!Queue.empty())
{
int v = Queue.front();//出队
Queue.pop();
for(ArcNode * rp = ALG.vertices[v].firstarc;rp!=0;rp = rp->nextarc)
{
if(!visited[(*rp).adjvex])
{
visited[(*rp).adjvex] = true;
visit(ALG.vexs[(*rp).adjvex]);
Queue.push((*rp).adjvex);
}
}
}

}
}
//测试数据序号是否都被修改
cout<<"测试结果(遍历每个节点,并将节点的序号加一):"<<endl;
for(int i = 0;i<ALG.vexnum;i++)
{
cout<<ALG.vexs[i]<<"  "<<endl;
}
}
//无向图操作菜单
void UndirectedGraph()
{
MGraph MG;
ALGraph ALG;
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:
CreatUDG_M(MG);
break;
case 2:
CreatUDG_ALG(ALG);
break;
case 3:
UDG_DFSTraverse(ALG,Visit_fun);
break;
case 4:
UDG_BFSTraverse(ALG,Visit_fun);
break;
default:
if (n!=5)
cout<<"错误,重新输入\n";
}
}while(n!=5);
}

/*
*有向图的函数集
*/
//创建有向图的邻接矩阵
bool CreatDG_M(MGraph& MDG)
{
MDG.kind = DG;
cout<<"请输入该有向图的顶点个数、弧的条数:"<<endl;
cin>>MDG.vexnum>>MDG.arcnum;
//初始化顶点集合
cout<<"依次输入顶点序号"<<endl;
for(int i = 0;i<MDG.vexnum;i++)  cin>>MDG.vexs[i];
//初始化邻接矩阵
for(int i = 0;i<MDG.vexnum;i++)
{
for(int j = 0;j<MDG.vexnum;j++)
{
MDG.arecs[i][j].adj = INFINITY;
}
}
//构造邻接矩阵
for(int i = 0;i<MDG.arcnum;i++)
{
int v1,v2;
cout<<"依次输入弧的弧尾序号、弧头序号:"<<endl;
cin>>v1>>v2;
int *p1 = find(MDG.vexs,MDG.vexs+MDG.vexnum,v1);
int *p2 = find(MDG.vexs,MDG.vexs+MDG.vexnum,v2);
if(p1==MDG.vexs+MDG.vexnum||p2==MDG.vexs+MDG.vexnum) return false;
MDG.arecs[(p1-MDG.vexs)][(p2-MDG.vexs)].adj = 1;
}
//输出该邻接矩阵
cout<<"该邻接矩阵为:"<<endl;
for(int i = 0;i<MDG.vexnum;i++)
{
for(int j = 0;j<MDG.vexnum;j++)
{
if(MDG.arecs[i][j].adj==INFINITY) cout<<"∞  ";
else
{
cout<<MDG.arecs[i][j].adj<<"  ";
}
}
cout<<endl;
}
return true;
}
//创建有向图的邻接表
bool CreatDG_ALG(ALGraph & ALDG)
{
ALDG.kind =  DG;
cout<<"请输入该有向图的顶点个数、弧的条数:"<<endl;
cin>>ALDG.vexnum>>ALDG.arcnum;
//初始化顶点集合
cout<<"依次输入顶点序号"<<endl;
for(int i = 0;i<ALDG.vexnum;i++)  cin>>ALDG.vexs[i];
//构造邻接表
for(int i  = 0;i<ALDG.vexnum;i++)
{
//初始化头结点的data信息
ALDG.vertices[i].data = ALDG.vexs[i];
ALDG.vertices[i].firstarc = 0;
//循环输入该头结点的邻接弧
cout<<"输入以序号为"<<ALDG.vexs[i]<<"节点为弧尾的弧头节点序号"<<endl;
int v1;
ArcNode * rp = ALDG.vertices[i].firstarc;
while (cin>>v1)
{
int *p1 =  find(ALDG.vexs,ALDG.vexs+ALDG.vexnum,v1);
if(p1==ALDG.vexs+ALDG.vexnum)return false;
ArcNode *pA = (ArcNode *)malloc(sizeof(ArcNode));
if(!pA) return false;
pA->adj = 1;
pA->adjvex = p1-ALDG.vexs;
pA->nextarc = 0;
if(0==ALDG.vertices[i].firstarc) {ALDG.vertices[i].firstarc = pA; rp = pA;}
else{rp->nextarc = pA; rp = pA;}
}
cin.clear();//清空输入流
}
//输出邻接表
for(int i  = 0;i<ALDG.vexnum;i++)
{
cout<<"'"<<ALDG.vexs[i]<<"'";
for(ArcNode * rp = ALDG.vertices[i].firstarc;rp!=0;rp = rp->nextarc)
{
cout<<"--->"<<(*rp).adjvex;
}
cout<<endl;
}
return true;
}
//拓扑排序
bool TopologicalSort(ALGraph & ALDG)
{
//入度数组
int *indegree = new int[ALDG.vexnum];
//初始化入度数组
for(int i = 0;i<ALDG.vexnum;i++)
{
int re= 0;
for(int j = 0;j<ALDG.vexnum;j++)
{
if(j!=i)//查找入度
{
for(ArcNode * rp = ALDG.vertices[j].firstarc;rp!=0;rp = rp->nextarc)
{
if((*rp).adjvex==i) re++;
}
}
}
indegree[i] = re;
}
//保存入度为0的栈
stack<int> Stack;
for(int i = 0;i<ALDG.vexnum;i++)
{
if(0==indegree[i]) Stack.push(i);
}
int count = 0;//记录输出节点的个数
while (!Stack.empty())
{
int v = Stack.top();//出栈
Stack.pop(); count++;
//输出
cout<<ALDG.vexs[v]<<"  ";
for(ArcNode * rp = ALDG.vertices[v].firstarc;rp!=0;rp = rp->nextarc)
{
--indegree[(*rp).adjvex];
if(0==indegree[(*rp).adjvex]) Stack.push((*rp).adjvex);
}
}
if(count<ALDG.vexnum)
{
return false;
}
return true;
}
//有向图操作菜单
void DirectedGraph ()
{
MGraph MDG;//有向图邻接矩阵
ALGraph ALDG;//有向图邻接表
int n;
do
{
cout<<"\n";
cout<<"  ***************有向图的基本操作及应用***************\n";
cout<<"  *  1 创建有向图的邻接矩阵                         *\n";
cout<<"  *  2 创建有向图的邻接表                           *\n";
cout<<"  *  3 拓扑排序                                     *\n";
cout<<"  *  4 退出                                         *\n";
cout<<"  ****************************************************\n";
cin>>n;
switch(n){
case 1:
CreatDG_M(MDG);
break;
case 2:
CreatDG_ALG(ALDG);
break;
case 3:
TopologicalSort(ALDG);
break;
default:
if (n!=4)
cout<<"错误,重新输入\n";
}
}while(n!=4);
}

/*
*无向网的函数集
*/
//创建无向网的邻接矩阵
bool CreatUDN_M(MGraph &MG)
{
MG.kind = UDN;
cout<<"请输入该无向网的顶点个数、弧的条数:"<<endl;
cin>>MG.vexnum>>MG.arcnum;
//初始化顶点集合
cout<<"依次输入顶点序号"<<endl;
for(int i = 0;i<MG.vexnum;i++)  cin>>MG.vexs[i];
//初始化邻接矩阵
for(int i = 0;i<MG.vexnum;i++)
{
for(int j = 0;j<MG.vexnum;j++)
{
MG.arecs[i][j].adj = INFINITY;
}
}
//构造邻接矩阵
for(int i = 0;i<MG.arcnum;i++)
{
int v1,v2;
double w;
cout<<"依次输入弧的两个顶点序号及权值:"<<endl;
cin>>v1>>v2>>w;
int *p1 = find(MG.vexs,MG.vexs+MG.vexnum,v1);
int *p2 = find(MG.vexs,MG.vexs+MG.vexnum,v2);
if(p1==MG.vexs+MG.vexnum||p2==MG.vexs+MG.vexnum) return false;
MG.arecs[(p1-MG.vexs)][(p2-MG.vexs)].adj = w;
//无向图的邻接矩阵是对称矩阵
MG.arecs[(p2-MG.vexs)][(p1-MG.vexs)].adj = w;
}
//输出该邻接矩阵
cout<<"该邻接矩阵为(-1代表无穷大):"<<endl;
for(int i = 0;i<MG.vexnum;i++)
{
for(int j = 0;j<MG.vexnum;j++)
{
if(MG.arecs[i][j].adj==INFINITY) cout<<"∞  ";
else
{
cout<<MG.arecs[i][j].adj<<"  ";
}
}
cout<<endl;
}
return true;
}
//创建无向网的邻接表
bool CreatUDN_ALG(ALGraph &ALN)
{
ALN.kind =  UDN;
cout<<"请输入该无向网的顶点个数、弧的条数:"<<endl;
cin>>ALN.vexnum>>ALN.arcnum;
//初始化顶点集合
cout<<"依次输入顶点序号"<<endl;
for(int i = 0;i<ALN.vexnum;i++)  cin>>ALN.vexs[i];
//构造邻接表
for(int i  = 0;i<ALN.vexnum;i++)
{
//初始化头结点的data信息
ALN.vertices[i].data = ALN.vexs[i];
ALN.vertices[i].firstarc = 0;
//循环输入该头结点的邻接弧
cout<<"输入与序号为"<<ALN.vexs[i]<<"节点相邻的节点序号、弧的权值"<<endl;
int v1;
double w;
ArcNode * rp = ALN.vertices[i].firstarc;
while (cin>>v1)
{
cin>>w;
int *p1 =  find(ALN.vexs,ALN.vexs+ALN.vexnum,v1);
if(p1==ALN.vexs+ALN.vexnum)return false;
ArcNode *pA = (ArcNode *)malloc(sizeof(ArcNode));
if(!pA) return false;
pA->adj = w;
pA->adjvex = p1-ALN.vexs;
pA->nextarc = 0;
if(0==ALN.vertices[i].firstarc) {ALN.vertices[i].firstarc = pA; rp = pA;}
else{rp->nextarc = pA; rp = pA;}
}
cin.clear();//清空输入流
}
//输出邻接表
for(int i  = 0;i<ALN.vexnum;i++)
{
cout<<"'"<<ALN.vexs[i]<<"'";
for(ArcNode * rp = ALN.vertices[i].firstarc;rp!=0;rp = rp->nextarc)
{
cout<<"--->"<<(*rp).adjvex;
}
cout<<endl;
}
return true;
}
//prim算法求最小生成树
typedef struct
{
int adjvex;//顶点序号
double lowcost;//最短距离
}Closedge[MAX_VERTEX_NUM];
bool MiniSpanTree(MGraph & MN)
{
Closedge closedge;//记录未选节点到已选节点中最短的距离
int k = 0;
//初始化辅组数组
for(int i = 0;i<MN.vexnum;i++)
{
if(i!=k) {closedge[i].lowcost = MN.arecs[i][k].adj;closedge[i].adjvex = MN.vexs[k];}
}
closedge[k].lowcost = 0;//标识为已选
for(int i = 1;i<MN.vexnum;i++)//选择其余的n-1个顶点
{
//求出未选节点中的最短距离
double low = INFINITY+1;

for(int j = 0;j<MN.vexnum;j++)
{
if((closedge[j].lowcost!=0)&&(closedge[j].lowcost<low))
{
k = j;
low = closedge[j].lowcost;
}
}
//打印该路线
cout<<MN.vexs[k]<<"  "<<closedge[k].adjvex<<"  "<<closedge[k].lowcost<<endl;
//标识为已选
closedge[k].lowcost = 0;
//更新最短距离
for(int j = 0;j<MN.vexnum;j++)
{
if(closedge[j].lowcost>MN.arecs[j][k].adj)
{
closedge[j].adjvex =MN.vexs[k];
closedge[j].lowcost = MN.arecs[j][k].adj;
}
}
}
return true;
}
// kruskal算法求最小生成树
void Kruskal(MGraph & MN)
{
int i,j,k;
int n = MN.vexnum;
AdjMatrix S;//用来表示连通关系
AdjMatrix Q;//表示节点之间的权值
//初始化
for(i=0;i<n;i++)
for(j=0;j<n;j++){
if(i==j) S[i][j].adj=1;
else S[i][j].adj=0;
Q[i][j].adj = MN.arecs[i][j].adj;
}
k=1;
while(k<n)
{
//找到权值最小的边
double low = INFINITY+1;
int Begin,End;
for(i=0;i<n;i++)
for(j=0;j<n;j++){
if(Q[i][j].adj<low)
{
Begin = i;
End = j;
low = Q[i][j].adj;
}
}
Q[Begin][End].adj = INFINITY;//归无穷
if(0==S[Begin][End].adj)
{
cout<<MN.vexs[Begin]<<"---"<<MN.vexs[End]<<"  "<<MN.arecs[Begin][End].adj<<endl;
k++;
//更新全局的连通关系
for(i = 0;i<n;i++)
{
if(S[Begin][i].adj!=0)
{
S[End][i].adj = S[i][End].adj = 1;
//更新相连分支
for(int j = 0;j<n;j++)
{
if(S[End][j].adj!=0)
{
S[j][i].adj = S[i][j].adj = 1;
}
}
}
}
for(i = 0;i<n;i++)
{
if(S[End][i].adj!=0)
{
S[Begin][i].adj = S[i][Begin].adj = 1;
//更新相连分支
for(int j = 0;j<n;j++)
{
if(S[Begin][j].adj!=0)
{
S[j][i].adj = S[i][j].adj = 1;
}
}
}
}

}//if
}//while
}
//无向网操作菜单
void IndirectedNet()
{
MGraph MN;
ALGraph ALN;
int n;
do{
cout<<"\n";
cout<<"  ***************无向网的基本操作及应用***************\n";
cout<<"  *  1 创建无向网的邻接矩阵                         *\n";
cout<<"  *  2 创建无向网的邻接表                           *\n";
cout<<"  *  3 prim算法求最小生成树                         *\n";
cout<<"  *  4 kruskal算法求最小生成树                      *\n";
cout<<"  *  5 退出                                         *\n";
cout<<"  ****************************************************\n";
cin>>n;
switch(n){
case 1:
CreatUDN_M(MN);
break;
case 2:
CreatUDN_ALG(ALN);
break;
case 3:
MiniSpanTree(MN);
break;
case 4:
Kruskal(MN);
break;
default:
if (n!=5)
cout<<"错误,重新输入\n";
}
}while(n!=5);

}

/*
*有向网的函数集
*/
//创建有向网的邻接矩阵
bool CreatDN_M(MGraph &MDN )
{
MDN.kind = DG;
cout<<"请输入该有向网的顶点个数、弧的条数:"<<endl;
cin>>MDN.vexnum>>MDN.arcnum;
//初始化顶点集合
cout<<"依次输入顶点序号"<<endl;
for(int i = 0;i<MDN.vexnum;i++)  cin>>MDN.vexs[i];
//初始化邻接矩阵
for(int i = 0;i<MDN.vexnum;i++)
{
for(int j = 0;j<MDN.vexnum;j++)
{
MDN.arecs[i][j].adj = INFINITY;
}
}
//构造邻接矩阵
for(int i = 0;i<MDN.arcnum;i++)
{
int v1,v2;
double w;
cout<<"依次输入弧的弧尾序号、弧头序号、权值:"<<endl;
cin>>v1>>v2>>w;
int *p1 = find(MDN.vexs,MDN.vexs+MDN.vexnum,v1);
int *p2 = find(MDN.vexs,MDN.vexs+MDN.vexnum,v2);
if(p1==MDN.vexs+MDN.vexnum||p2==MDN.vexs+MDN.vexnum) return false;
MDN.arecs[(p1-MDN.vexs)][(p2-MDN.vexs)].adj = w;
}
//输出该邻接矩阵
cout<<"该邻接矩阵为:"<<endl;
for(int i = 0;i<MDN.vexnum;i++)
{
for(int j = 0;j<MDN.vexnum;j++)
{
if(MDN.arecs[i][j].adj==INFINITY) cout<<"∞  ";
else
{
cout<<MDN.arecs[i][j].adj<<"  ";
}
}
cout<<endl;
}
return true;
}
//创建有向网的邻接表
bool CreatDN_ALG(ALGraph & ALDN)
{
ALDN.kind =  DG;
cout<<"请输入该有向网的顶点个数、弧的条数:"<<endl;
cin>>ALDN.vexnum>>ALDN.arcnum;
//初始化顶点集合
cout<<"依次输入顶点序号"<<endl;
for(int i = 0;i<ALDN.vexnum;i++)  cin>>ALDN.vexs[i];
//构造邻接表
for(int i  = 0;i<ALDN.vexnum;i++)
{
//初始化头结点的data信息
ALDN.vertices[i].data = ALDN.vexs[i];
ALDN.vertices[i].firstarc = 0;
//循环输入该头结点的邻接弧
cout<<"输入以序号为"<<ALDN.vexs[i]<<"节点为弧尾的弧头节点序号、弧的权值"<<endl;
int v1;
double w;
ArcNode * rp = ALDN.vertices[i].firstarc;
while (cin>>v1)
{
cin>>w;
int *p1 =  find(ALDN.vexs,ALDN.vexs+ALDN.vexnum,v1);
if(p1==ALDN.vexs+ALDN.vexnum)return false;
ArcNode *pA = (ArcNode *)malloc(sizeof(ArcNode));
if(!pA) return false;
pA->adj = w;
pA->adjvex = p1-ALDN.vexs;
pA->nextarc = 0;
if(0==ALDN.vertices[i].firstarc) {ALDN.vertices[i].firstarc = pA; rp = pA;}
else{rp->nextarc = pA; rp = pA;}
}
cin.clear();//清空输入流
}
//输出邻接表
for(int i  = 0;i<ALDN.vexnum;i++)
{
cout<<"'"<<ALDN.vexs[i]<<"'";
for(ArcNode * rp = ALDN.vertices[i].firstarc;rp!=0;rp = rp->nextarc)
{
cout<<"--->"<<(*rp).adjvex;
}
cout<<endl;
}
return true;
}
//关键路径
bool TopologicalOrder(ALGraph & ALDN,stack<int> & T,double ve[] )//T用于保存拓扑排序
{
//入度数组
int *indegree = new int[ALDN.vexnum];
//初始化入度数组
for(int i = 0;i<ALDN.vexnum;i++)
{
int re= 0;
for(int j = 0;j<ALDN.vexnum;j++)
{
if(j!=i)//查找入度
{
for(ArcNode * rp = ALDN.vertices[j].firstarc;rp!=0;rp = rp->nextarc)
{
if((*rp).adjvex==i) re++;
}
}
}
indegree[i] = re;
}
//保存入度为0的栈
//初始化事件最早发生数组
stack<int> Stack;
for(int i = 0;i<ALDN.vexnum;i++)
{
if(0==indegree[i]) Stack.push(i);
ve[i] = 0;
}

int count = 0;//记录输出节点的个数
while (!Stack.empty())
{
int v = Stack.top();//出栈
Stack.pop(); count++;
T.push(v);
for(ArcNode * rp = ALDN.vertices[v].firstarc;rp!=0;rp = rp->nextarc)
{
--indegree[(*rp).adjvex];
if(0==indegree[(*rp).adjvex]) Stack.push((*rp).adjvex);
if(ve[v]+(*rp).adj>ve[(*rp).adjvex]) ve[(*rp).adjvex] = ve[v]+(*rp).adj;
}
}
if(count<ALDN.vexnum)
{
return false;
}
return true;
}
bool CriticalPath(ALGraph & ALDN )
{
stack<int>  T;//保存拓扑排序
double * ve  = new double[ALDN.vexnum];//事件最早发生数组
if(!TopologicalOrder(ALDN,T,ve)) return false;
double * vl = new double[ALDN.vexnum];//事件最迟发生数组
//初始化最迟发生数组
for(int i = 0;i<ALDN.vexnum;i++)
{
vl[i] = ve[T.top()];
}
//按照拓扑逆序求各项的最迟发生时间
while(!T.empty())
{
int j = T.top();
T.pop();
ArcNode *p = ALDN.vertices[j].firstarc;
for(;p!=0;p=p->nextarc)
{
if((vl[(*p).adjvex]-(*p).adj)<vl[j]) vl[j] = (vl[(*p).adjvex]-(*p).adj);
}
}
//查找关键路径
for(int i = 0;i<ALDN.vexnum;i++)
{
for(ArcNode *p = ALDN.vertices[i].firstarc;p!=0;p=p->nextarc)
{
if(ve[i] == (vl[p->adjvex] - p->adj))
{
cout<<"*  :"<<ALDN.vexs[i]<<"---"<<ALDN.vexs[p->adjvex]<<"  :"<<ve[i]<<"<--"<<p->adj<<"-->"<<vl[p->adjvex]<<endl;
}
}
}
return true;
}
//单源顶点最短路径问题
bool ShortestPath(MGraph &MDN,int v0)
{
AdjMatrix P;//p[v][w]用于记录v0到v点最短路径上的节点 为true则在该最短路径上
double *D = new double[MDN.vexnum];//记录v0到每一点的最短距离
bool *fina = new bool[MDN.vexnum];//记录v0是否已经找到到每一点的最短路径
//初始化参数
for(int i = 0;i<MDN.vexnum;i++)
{
fina[i] = false;
D[i] = MDN.arecs[v0][i].adj;
//先把所有路径置空
for(int j = 0;j<MDN.vexnum;j++) P[i][j].adj = 0;
if(D[i]<INFINITY)
{
P[i][v0].adj = 1;
P[i][i].adj = 1;
}
}
D[v0] = 0;
fina[v0] = true;
//为剩下的n-1个节点查找最短距离
for(int i = 1;i<MDN.vexnum;i++)
{
double min = INFINITY+1;//记录剩下的节点到v0的最短距离
int mV;//记录剩下的节点到v0的最短距离的节点
//找出最短距离
for(int j= 0;j<MDN.vexnum;j++)
{
if(!fina[j])
{
if(D[j]<min)
{
mV= j;
min = D[j];
}
}
}
//mV加入找到最短路径集合
fina[mV] = true;
//更新剩下的每一个点到v0的最短距离集合 及 最短路径集合
for(int j= 0;j<MDN.vexnum;j++)
{
if(!fina[j]&&(min+MDN.arecs[mV][j].adj<D[j]))
{
D[j] = min+MDN.arecs[mV][j].adj;
//更新最短路径集合
for(int a = 0;a<MDN.vexnum;a++)
{
P[j][a].adj = P[mV][a].adj;
}
P[j][j].adj = 1;
}

}
}
//输出测试数据
for(int j= 0;j<MDN.vexnum;j++)
{
//先判断是否存在最短路径
if(D[j]==INFINITY)
{
cout<<MDN.vexs[j]<<"  无"<<endl;
}
else
{
//先输出最短路径
cout<<MDN.vexs[j]<<"     ";
for(int i = 0;i<MDN.vexnum;i++)
{
if(1==P[j][i].adj)
{
cout<<MDN.vexs[i]<<"   ";
}
}
cout<<"最短距离: "<<D[j]<<endl;
}

}

return true;
}
//有向网操作菜单
void DirectedNet()
{
MGraph MDN;
ALGraph ALDN;
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:
CreatDN_M(MDN);
break;
case 2:
CreatDN_ALG(ALDN);
break;
case 3:
CriticalPath(ALDN);
break;
case 4:
ShortestPath(MDN,0);
break;
default:
if (n!=5)
cout<<"错误,重新输入\n";
}
}while(n!=5);
}

void main()
{
int n;
do{
ShowMainMenu();
cin>>n;
switch(n){
case 1:
UndirectedGraph();
break;
case 2:
DirectedGraph();
break;
case 3:
IndirectedNet();
break;
case 4:
DirectedNet();
break;
default:
if (n!=5)
cout<<"错误,重新输入\n";
}
}while(n!=5);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  数据结构