//根据网上和严蔚敏书上写的。
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#define MaxVertexNum 100 //最大顶点个数
#define QM 100 //队列的最大元素个数
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
int visited[MaxVertexNum]; //用于深度优先遍历
typedef enum {DG, Dn, UDG, UDN} GraphKind; //有向图,有向网,无向图,无向网
typedef int VertexType; //顶点类型
typedef struct
{
int adj; //相邻与否,或者权值大小
}ArcCell;
typedef struct
{
VertexType vexs[MaxVertexNum]; //顶点向量
ArcCell arcs[MaxVertexNum][MaxVertexNum]; //邻接矩阵
int vexnum; //顶点数
int arcnum; //弧数
int GraphKind; //图的种类
}MGraph;
typedef struct //广度优先用的队列
{
VertexType *base;
VertexType front, rear;
}SQueue;
int LocateVex( MGraph *M,VertexType v ); //求顶点位置
int CreatGraph( MGraph *M ); //生成图
int CreatGraphDG( MGraph *M ); //创建有向图
int CreatGraphDN( MGraph *M ); //创建有向网
int CreatGraphUDG( MGraph *M ); //创建无向图
int CreatGraphUDN( MGraph *M ); //创建无向网
int FirstAdjVex( MGraph *M, int v ); //返回v的第一个邻接节点
int NextAdjVex( MGraph *M, int v , int w); //返回v相对于w的下一个邻接节点
void PrintMatrix( MGraph *M ); //打印邻接矩阵
void InsetVex( MGraph *M, VertexType v ); //插入节点
int DelVex( MGraph *M, VertexType v ); //删除节点
void InsertArc( MGraph *M ); //添加一条弧
void DeArc( MGraph *M ); //删掉一条弧
void DFS( MGraph *M, int v ); //DFS
void DFSTraverse( MGraph *M ); //DFS深度优先遍历
void BFSTraverse( MGraph *M ); //BFS广度优先遍历
//队列函数声明
void InitQueue( SQueue *Q ); //初始化队列
void EnQueue( SQueue *Q, int e ); //入队
void OutQueue( SQueue *Q, int *e); //出队
int QueueEmpty( SQueue *Q ); //队列是否空
int main()
{
int time;
printf("请输入试验次数:");
scanf("%d", &time);
while(time--)
{
MGraph M;
M.vexnum = M.arcnum = 0;
CreatGraph( &M );
PrintMatrix( &M );
DeArc( &M );
PrintMatrix( &M );
DFSTraverse( &M );
printf("\n");
getch();
BFSTraverse( &M );
}
return 0;
}
//求顶点位置
int LocateVex( MGraph *M, VertexType v )
{
int k;
for(k = 0; k < M->vexnum; k++)
if(M->vexs[k] == v)
return k;
return -1;
}
//创建图的选择函数
int CreatGraph( MGraph *G )
{
printf("输入要创建图的类型\n");
printf("0: 退出 1:有向图 2: 有向网 3: 无向图 4: 无向网 \n");
while( scanf("%d", &G->GraphKind) )
{
switch (G->GraphKind)
{
case 0:
exit(-1);
case 1:
return CreatGraphDG( G );
case 2:
return CreatGraphDN( G );
case 3:
return CreatGraphUDG( G );
case 4:
return CreatGraphUDN( G );
default:
{
system("cls");
printf("输入无效,请重新输入要创建图的类型\n");
printf("0: 退出 1:有向图 2: 有向网 3: 无向图 4: 无向网 \n");
continue;
}
}
}
}
//创建有向图
int CreatGraphDG( MGraph *M )
{
int i, j, k;
int weight = 1;
VertexType v1, v2;
printf("请输入有向图的顶点数和弧数:\n");
scanf("%d %d", &M->vexnum, &M->arcnum);
//初始化邻接矩阵
for(i = 0; i < M->vexnum; i++)
for(j = 0; j < M->vexnum; j++)
M->arcs[i][j].adj = 0; //初始化所有顶点不相邻
printf("输入有向图的%d个顶点:\n", M->vexnum);
for(i = 0; i < M->vexnum; i++)
scanf("%d", &M->vexs[i]);
printf("建立弧,请输入%d条弧的顶点:\n", M->arcnum);
for(k = 0; k < M->arcnum; k++)
{
scanf("%d %d", &v1, &v2);
i = LocateVex(M, v1);
j = LocateVex(M, v2);
if(i < 0 || j < 0)
return ERROR;
M->arcs[i][j].adj = weight;
}
return OK;
}
//创建有向网
int CreatGraphDN( MGraph *M )
{
int i, j, k;
int weight;
VertexType v1, v2;
printf("输入有向网的顶点数和弧数:\n");
scanf("%d %d", &M->vexnum, &M->arcnum);
for(i = 0; i < M->vexnum; i++)
for(j = 0; j < M->vexnum; j++)
M->arcs[i][j].adj = 0; //初始化所有顶点不相邻
printf("输入网的%d个顶点:\n", M->vexnum);
for(i = 0; i < M->vexnum; i++)
scanf("%d", &M->vexs[i]);
printf("输入网的%d条弧的顶点和权值:\n", M->arcnum);
for(k = 0; k < M->arcnum; k++)
{
scanf("%d %d %d", &v1, &v2, &weight);
i = LocateVex(M, v1);
j = LocateVex(M, v2);
if(i < 0 || j < 0)
return ERROR;
M->arcs[i][j].adj = weight;
}
return OK;
}
//创建无向图
int CreatGraphUDG( MGraph *M )
{
int i, j, k;
int weight = 1;
VertexType v1, v2;
printf("输入无向图的顶点数和弧数:\n");
scanf("%d %d", &M->vexnum, &M->arcnum);
for(i = 0; i < M->vexnum; i++)
for(j = 0; j < M->vexnum; j++)
M->arcs[i][j].adj = 0; //初始化所有顶点不相邻
printf("输入无向图的%d个顶点:\n", M->vexnum);
for(i = 0; i < M->vexnum; i++)
scanf("%d", &M->vexs[i]);
printf("建立弧,请输入无向图的%d条弧的顶点:\n", M->arcnum);
for(k = 0; k < M->arcnum; k++)
{
scanf("%d %d", &v1, &v2);
i = LocateVex(M, v1);
j = LocateVex(M, v2);
if(v1 < 0 || v2 < 0)
return ERROR;
M->arcs[j][i].adj =M->arcs[i][j].adj = weight;
}
return OK;
}
//创建无向网
int CreatGraphUDN( MGraph *M )
{
int i, j, k;
int weight;
VertexType v1, v2;
printf("输入无向网的顶点数和弧数:\n");
scanf("%d %d", &M->vexnum, &M->arcnum);
for(i = 0; i < M->vexnum; i++)
for(j = 0; j < M->arcnum; j++)
M->arcs[i][j].adj = 0;
printf("输入无向网的%d个顶点:\n", M->vexnum);
for(i = 0; i < M->vexnum; i++)
scanf("%d", &M->vexs[i]);
printf("建立弧,请输入无向网%d条弧的顶点和权值:\n", M->arcnum);
for(k = 0; k < M->arcnum; k++)
{
scanf("%d %d %d", &v1, &v2, &weight);
i = LocateVex(M, v1);
j = LocateVex(M, v2);
if(v1 < 0 || v2 < 0)
return ERROR;
M->arcs[i][j].adj = M->arcs[j][i].adj = weight;
}
return OK;
}
//打印邻接矩阵
void PrintMatrix( MGraph *M)
{
int i, j;
for(i = 0; i < M->vexnum; i++)
{
for(j = 0; j < M->vexnum; j++)
printf("%d\t", M->arcs[i][j].adj);
printf("\n");
}
}
//返回v的第一个邻接节点
int FirstAdjVex( MGraph *M, int v )
{
int i;
for(i = 0; i < M->vexnum; i++)
if( M->arcs[v][i].adj != 0 )
return i;
return -1;
}
//返回v相对于w的下一个邻接节点
int NextAdjVex( MGraph *M, int v, int w )
{
int i;
for(i = w+1; i < M->vexnum; i++)
if( M->arcs[v][i].adj != 0 )
return i;
return -1;
}
//插入节点v
void InsertVex( MGraph *M, VertexType v )
{
int i, j;
printf("插入一个顶点:\n");
M->vexs[M->vexnum++] = v;
i = LocateVex( M, v );
for(j = 0; j < M->vexnum; j++)
M->arcs[i][j].adj = M->arcs[j][i].adj = 0; //默认添加顶点和其他顶点都不相邻
}
//删除一个节点
int DelVertex( MGraph *M, VertexType v )
{
int i, j;
i = LocateVex( M, v );
if( i == -1 )
{
printf("该节点不存在\n");
return ERROR;
}
for(j = 0; j < M->vexnum; j++)
M->arcs[i][j].adj = M->arcs[j][i].adj = 0; //删除与该顶点邻接的弧
for(j = i; j < M->vexnum - 1; j++)
M->vexs[j] = M->vexs[j+1];
M->vexnum--;
return OK;
}
//DFS
void DFS( MGraph *M , int v )
{
int vj;
visited[v] = TRUE;
printf("%d ", M->vexs[v]);
/*
for( vj = 0; vj < M->vexnum; vj++)
if( !visited[vj] && M->arcs[v][vj].adj )
DFS( M, vj );
*/
for( vj = FirstAdjVex(M, v); vj >= 0; vj = NextAdjVex(M, v, vj) )
if( !visited[vj] )
DFS( M, vj);
}
//DFS深度优先遍历
void DFSTraverse( MGraph *M )
{
int vi;
printf("深度遍历:\n");
for(vi = 0; vi < M->vexnum; vi++)
visited[vi] = FALSE;
for(vi = 0; vi < M->vexnum; vi++)
if( !visited[vi] )
DFS( M, vi );
}
//广度优先遍历
void BFSTraverse( MGraph *M )
{
int v, u, w;
SQueue Q;
printf("广度优先遍历:\n");
for(v = 0; v < M->vexnum; v++)
visited[v] = FALSE;
InitQueue( &Q );
for(v = 0; v < M->vexnum; v++)
if( !visited[v] )
{
visited[v] = TRUE;
printf("%d ", M->vexs[v]);
EnQueue( &Q, v );
while( !QueueEmpty( &Q ) )
{
OutQueue( &Q, &u);
for( w = FirstAdjVex( M, u ); w >= 0; w = NextAdjVex( M, u, w) )
{
if( !visited[w] )
{
visited[w] = TRUE;
printf("%d ", M->vexs[w]);
EnQueue( &Q, w );
}
}
}
}
printf("\n");
}
//初始化队列
void InitQueue( SQueue *Q )
{
Q->base = (VertexType * ) malloc ( sizeof(VertexType) * QM );
if( Q->base == NULL )
{
printf("分配内存失败\n");
exit(-1);
}
Q->front = Q->rear = 0;
}
//队列是否为空
int QueueEmpty( SQueue *Q )
{
return Q->front == Q->rear;
}
//入队
void EnQueue( SQueue *Q, int e )
{
int t = (Q->rear + 1) % QM;
if( t == Q->front )
{
printf("队列已满溢出");
exit(-1);
}
Q->base[t-1] = e;
Q->rear = t;
}
//出队
void OutQueue( SQueue *Q, int *e )
{
if( QueueEmpty(Q) )
{
printf("出队失败,队列为空\n");
exit(-1);
}
*e = Q->base[ (Q->front)++ ];
}
//添加一条弧
void InsertArc( MGraph *M )
{
VertexType v1, v2;
int weight;
int i, j;
printf("添加一条弧\n");
if( M->GraphKind == 1 || M->GraphKind == 3 ) //图
{
printf("输入要添加的弧的两个顶点: ");
while( scanf("%d %d", &v1, &v2) )
{
i = LocateVex( M, v1);
j = LocateVex( M, v2);
if( i < 0 || j < 0 )
{
printf("顶点不在图中请重新输入:");
continue;
}
if( M->GraphKind == 1 ) //有向图
M->arcs[i][j].adj = 1;
else //无向图
M->arcs[i][j].adj = M->arcs[j][i].adj = 1;
break;
}
}
else
{
printf("输入要添加的弧的两个顶点和权值: ");
while( scanf("%d %d %d", &v1, &v2, &weight) )
{
i = LocateVex( M, v1);
j = LocateVex( M, v2);
if( i < 0 || j < 0 )
{
printf("顶点不在图中请重新输入:");
continue;
}
if( M->GraphKind == 2 ) //有向网
M->arcs[i][j].adj = weight;
else
M->arcs[i][j].adj = M->arcs[j][i].adj = weight;
break;
}
}
}
//删掉一条弧
void DeArc( MGraph *M )
{
int v1, v2;
int i, j;
printf("请输入删掉弧的两个顶点: ");
while( scanf("%d %d", &v1, &v2) )
{
i = LocateVex( M, v1 );
j = LocateVex( M, v2 );
if( i < 0 || j < 0 )
{
printf("该节点不在图中,请重新输入: ");
continue;
}
if( M->GraphKind <= 2 )
M->arcs[i][j].adj = 0;
else
M->arcs[i][j].adj = M->arcs[j][i].adj = 0;
break;
}
}