实验题目: 图的基本操作实现
实验环境: Visual C++ 6.0
实验目的:掌握图的邻接矩阵和邻接表两个存储结构及表示。
掌握图的DFS和BFS两种遍历算法。
理解并掌握下述完整算法的基本思想以及算法实现方法:最小生成树算法、最短路径算法、拓扑排序算法及关键路径算法。
实验内容:1. 创建一个无向图,并分别对其进行DFS和BFS。
2. 实现最短路径、最小生成树、拓扑排序三种算法。
#include
#include
#include
#include
#include
#include
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MaxInt 32767
#define MVNum 100
using namespace std;
typedef int Status;
bool visited[MVNum];
typedef struct
{
int vexs[MVNum];//顶点表
int arcs[MVNum][MVNum];//邻接矩阵
int vexnum,arcnum; //图的当前点数和边数
}AMGraph;
Status CreateUDN(AMGraph &G)//用邻接矩阵建立无向网
{
int i,j,k,w;
int v1,v2;
printf("请输入总点数和总边数\n");
cin>>G.vexnum>>G.arcnum;//输入总点数,总边数
for(i=0;i>v1>>v2>>w;
G.arcs[v1][v2]=w;
G.arcs[v2][v1]=w;
}
return OK;
}
Status CreateDirUDN(AMGraph &G)//用邻接矩阵建立有向网
{
int i,j,k,w;
int v1,v2;
printf("请输入顶点数和边数\n");
cin>>G.vexnum>>G.arcnum;//输入总点数,总边数
for(i=0;i>v1>>v2>>w;
G.arcs[v1][v2]=w;
}
return OK;
}
typedef struct ArcNode//边结点
{
int adjvex;//该边所指向的顶点的位置
struct ArcNode * nextarc;//指向下一条边的指针
//OtherInfo info;//和边相关的信息
}ArcNode;
typedef struct VNode//顶点信息
{
int data;
ArcNode *firstarc;//指向第一条依附该顶点的边的指针
}VNode,AdjList[MVNum];
typedef struct
{
AdjList vertices;
int visited[MVNum];
int vexnum,arcnum;//图的当前节点数和边数
}ALGraph;
Status CreateUDG(ALGraph &G)//邻接表无向网
{
ArcNode *p1,*p2;
int v1,v2,i,j,k;
printf("请输入总点数和总边数\n");
cin>>G.vexnum>>G.arcnum;
for(i=0;i>i>>j;
p1=(ArcNode *)malloc(sizeof(ArcNode));
p1->adjvex=j;
p1->nextarc=G.vertices[i].firstarc;
G.vertices[i].firstarc=p1;//将新结点*P1插入顶点Vi的头部
p2=(ArcNode *)malloc(sizeof(ArcNode));
p2->adjvex=i;
p2->nextarc=G.vertices[j].firstarc;
G.vertices[j].firstarc=p2;
}
return OK;
}
Status CreateDirUDG(ALGraph &G)//邻接表有向网
{
ArcNode *p1,*p2;
int v1,v2,i,j,k;
printf("请输入总点数和总边数\n");
cin>>G.vexnum>>G.arcnum;
for(i=0;i>i>>j;
p1=(ArcNode *)malloc(sizeof(ArcNode));
p1->adjvex=j;
p1->nextarc=G.vertices[i].firstarc;
G.vertices[i].firstarc=p1;//将新结点*P1插入顶点Vi的头部
}
return OK;
}
void DFS_AL(ALGraph G,int v)
{//图G为邻接表类型,从第V个顶点出发深度优先搜索遍历图G
ArcNode *p;
int w;
cout<adjvex;//w是V的邻接点
if(!visited[w])//如果W未访问,则递归调用DFS__AL
DFS_AL(G,w);
p=p->nextarc;//p指向下一个边结点
}
}
typedef struct//队列的顺序储存
{
int *base;
int front;
int rear;
}SqQueue;
Status InitQueue(SqQueue &Q)
{//构造一个空的循环队列
Q.base=(int*)malloc(sizeof(int)*MVNum) ;
if(!Q.base)
exit(OVERFLOW);
Q.front=Q.rear=0;
return OK;
}
Status EnQueue(SqQueue &Q,int v)
{//插入元素v为Q的新队尾元素
if((Q.rear+1)%MVNum==Q.front)
return ERROR;
Q.base[Q.rear]=v;//新元素插入队尾
Q.rear=(Q.rear+1)%MVNum;//队尾指针加一
return OK;
}
Status DeQueue(SqQueue &Q,int &v)
{//删除Q的队头元素,用V返回其值
if(Q.front==Q.rear)
return ERROR;
v=Q.base[Q.front];//保存队头元素
Q.front=(Q.front+1)%MVNum;//队头指针加一
return OK;
}
Status QueueEmpty(SqQueue &Q)//判断队列是否为空
{
if(Q.front==Q.rear)
return 1;
return 0;
}
void Visit(ALGraph &G,int i)
{
printf(" %d",G.vertices[i].data) ;
G.visited[i]=1; //将访问标志置为1
}
void BFS_AL(ALGraph G,int v)
{//按广度优先非递归遍历连通图G
SqQueue Q;
ArcNode *w;
int u;
cout<nextarc)
{//依次检查u的所有邻接点w
if(!G.visited[w->adjvex] )
{
Visit(G,w->adjvex);
EnQueue(Q,w->adjvex);
}
}
}
printf("\n");
}
struct node
{
int adjvex;//最小边在U的那个顶点
int lowcost;//最小边上的权值
}closedge[MVNum];
void MiniSpanTree_Prim(AMGraph G,int k)
{//无向网G以邻接矩阵形式储存,从顶点u出发构造G的最小生成树T,输出T的各条边
//k=LocateVex(G,u);//k为顶点u的下标
int i,j,u0,v0,minn;
for(j=0;j0)
{
if(closedge[j].lowcostadjvex]++;
G.vertices[i].firstarc=G.vertices[i].firstarc->nextarc;
}
}
}
Status TopologicalSort(ALGraph &G)//拓扑排序
{
SqStack S;
int i,m,k,v;
int indegree[1100];
ArcNode *p;
InitStack(S);
Findindegree(G,indegree);
printf("各顶点的入度为:\n");
for(i=0;inextarc)
{
k=p->adjvex;
if(!(--indegree[k]))
Push(S,k);
}
}
printf("\n");
printf("排序成功\n");
}
int main()
{
AMGraph G,T;
ALGraph M,N,R;
int v,k;
printf("************************\n");
printf("1.DFS遍历邻接表无向网\n");
printf("2.BFS遍历邻接表无向网\n");
printf("3.邻接矩阵无向网生成最小生成树\n");
printf("4.邻接矩阵有向网生成最短路径\n");
printf("5.邻接表有向网生成拓扑序列\n");
printf("0.退出\n");
printf("************************\n");
int choose=-1;
while(choose)
{
printf("请选择: \n");
scanf("%d",&choose);
switch(choose)
{
case 1:
{
printf("请先创建一个无向网邻接链表\n:");
CreateUDG(M);
printf("创建成功\n");
printf("请输入遍历的起点\n");
scanf("%d",&v);
DFS_AL(M,v);
break;
}
case 2:
{
printf("请先创建一个无向图邻接链表\n");
CreateUDG(N);
printf("创建成功\n");
printf("请输入遍历的起点\n");
scanf("%d",&v);
BFS_AL(N,v);
break;
}
case 3:
{
printf("请先创建一个无向网邻接矩阵\n");
CreateUDN(G);
printf("创建成功\n");
printf("请输入起点\n");
scanf("%d",&k);
MiniSpanTree_Prim(G,k);
break;
}
case 4:
{
printf("请创建一个有向网邻接矩阵\n");
CreateDirUDN(T);
printf("创建成功\n");
printf("请输入起点\n");
scanf("%d",&k);
ShortestPath_DIJ(T,k);
break;
}
case 5:
{
printf("请先创建一个有向网邻接链表\n");
CreateDirUDG(R);
printf("创建成功\n");
TopologicalSort(R);
break;
}
}
}
return 0;
}