数据结构之邻接矩阵(C++版)

#include <iostream>
#include <stdlib.h>
#include <string.h>
#define INFINITY 1000 //最大值∞
#define MAX_VERTEX_NUM 20 //最大顶点个数
#define MAXLISTSIZE 100 //循环队列的最大容量
#define TRUE 1
#define FALSE 0
using namespace std;
typedef enum{DG, DN, AG, AN}GraphKind; //类型标志{有向图,有向网,无向图,无向网}
typedef int VRType;
typedef char VertexType;
typedef int ElemType;

bool visited[MAX_VERTEX_NUM]; //全局变量,访问标志数组

typedef struct ArcCell
{ //弧的定义
VRType adj; //VRType是顶点关系类型。对无权图,用1或0表示相邻否;对带权图,则为权值类型。
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct{ //图的定义
VertexType vexs[MAX_VERTEX_NUM]; //顶点信息
AdjMatrix arcs; //表示顶点之间关系的二维数组
int vexnum, arcnum; //图的当前顶点数和弧(边)数
int kind; //图的种类标志
}MGraph;

typedef struct
{
ElemType *elem; //存储空间基址   
int rear; //队尾指针   
int front; //队头指针
int queuesize; //允许的最大存储空间,以元素为单位  
}Queue;

void InitQueue(Queue &Q, int maxsize)
{
//构造一个最大存储空间为 maxsize 的空队列 Q  
if (maxsize == 0)
maxsize = MAXLISTSIZE;
Q.elem = new ElemType[maxsize]; //为循环队列分配存储空间  
if (!Q.elem) exit(1); //存储分配失败
Q.queuesize = maxsize;
Q.front = Q.rear = 0;
} //InitQueue

bool EnQueue(Queue &Q, ElemType e)
{
// 若当前队列不满,这在当前队列的尾元素之后,插入元素 e 为新的队列尾元素,并返回TRUE,否则返回FALSE
if((Q.rear + 1) % Q.queuesize == Q.front)
return FALSE;
Q.elem[Q.rear] = e;
Q.rear = (Q.rear+1) % Q.queuesize;
return TRUE;
}

bool DeQueue(Queue &Q, ElemType &e)
{
//若队列不空,则删除当前队列Q中的头元素,用 e 返回其值,并返回TRUE,否则返回 FALSE 
if (Q.front == Q.rear)
return FALSE;
e = Q.elem[Q.front];
Q.front = (Q.front+1) % Q.queuesize;
return TRUE;
}

bool QueueEmpty(Queue Q)
{
if(Q.front == Q.rear)
return TRUE;
else
return FALSE;
}

void DestroyQueue(Queue &Q)
{
delete[] Q.elem;
Q.queuesize = 0;
}

int LocateVex(MGraph G, VertexType v)
{ //初始条件:图G存在,v和G中顶点有相同特征
//操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回-1
int i;
for(i = 0; i < G.vexnum; ++i)
if(v == G.vexs[i])
return i;
return -1;
}

void CreateDG(MGraph &G)
{ //采用数组(邻接矩阵)表示法,构造有向图G。
int i, j, k;
VertexType va, vb; //顶点
cout << "请输入邻接矩阵的顶点数和边数:";
cin >> G.vexnum >> G.arcnum;
cout << "请输入邻接矩阵的顶点:";
for(i = 0; i < G.vexnum; ++i) //构造顶点向量
cin >> G.vexs[i];
for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵
for(j = 0; j < G.vexnum; ++j)
{
G.arcs[i][j].adj = 0; //有向网,初始化为0
}
for(k = 0; k < G.arcnum; ++k) //构造邻接矩阵
{
cout << "请输入第" << k + 1 << "条弧的起点(行)和终点(列): ";
cin >> va >> vb; //输入一条边依附的顶点
i = LocateVex(G, va);
j = LocateVex(G, vb); //确定va和vb在G中的位置
G.arcs[i][j].adj = 1; //顶点间有边赋值为1
}//for
}//CreateDG

void CreateDN(MGraph &G)
{ //采用数组(邻接矩阵)表示法,构造有向网G。
int i, j, k;
VRType w; //权值
VertexType va, vb; //顶点
cout << "请输入邻接矩阵的顶点数和边数:";
cin >> G.vexnum >> G.arcnum;
cout << "请输入邻接矩阵的顶点:";
for(i = 0; i < G.vexnum; ++i) //构造顶点向量
cin >> G.vexs[i];
for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵
for(j = 0; j < G.vexnum; ++j)
{
G.arcs[i][j].adj = INFINITY; //有向网,初始化为最大值
}
for(k = 0; k < G.arcnum; ++k) //构造邻接矩阵
{
cout << "请输入第" << k + 1 << "条弧的起点(行)和终点(列)和权值: ";
cin >> va >> vb >> w; //输入一条边依附的顶点及权值
i = LocateVex(G, va);
j = LocateVex(G, vb); //确定va和vb在G中的位置
G.arcs[i][j].adj = w; //w为权值
}//for
}//CreateDN

void CreateAG(MGraph &G)
{ //采用数组(邻接矩阵)表示法,构造无向图G。
int i, j, k;
VertexType va, vb; //顶点
cout << "请输入邻接矩阵的顶点数和边数:";
cin >> G.vexnum >> G.arcnum;
cout << "请输入邻接矩阵的顶点:";
for(i = 0; i < G.vexnum; ++i) //构造顶点向量
cin >> G.vexs[i];
for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵
for(j = 0; j < G.vexnum; ++j)
{
G.arcs[i][j].adj = 0; //无向图,初始化为0
}
for(k = 0; k < G.arcnum; ++k) //构造邻接矩阵
{
cout << "请输入第" << k + 1 << "条弧的两顶点: ";
cin >> va >> vb; //输入一条边依附的顶点
i = LocateVex(G, va);
j = LocateVex(G, vb); //确定va和vb在G中的位置
G.arcs[i][j].adj = 1; //顶点间有边赋值为1
G.arcs[j][i] = G.arcs[i][j];
}//for
}//CreateAG

void CreateAN(MGraph &G)
{ //采用数组(邻接矩阵)表示法,构造无向网G。
int i, j, k;
VRType w; //权值
VertexType va, vb; //顶点
cout << "请输入邻接矩阵的顶点数和边数:";
cin >> G.vexnum >> G.arcnum;
cout << "请输入邻接矩阵的顶点:";
for(i = 0; i < G.vexnum; ++i) //构造顶点向量
cin >> G.vexs[i];
for(i = 0; i < G.vexnum; ++i) //初始化邻接矩阵
for(j = 0; j < G.vexnum; ++j)
{
G.arcs[i][j].adj = INFINITY; //无向网,初始化为最大值
}
for(k = 0; k < G.arcnum; ++k) //构造邻接矩阵
{
cout << "请输入第" << k + 1 << "条弧的两顶点和权值: ";
cin >> va >> vb >> w; //输入一条边依附的顶点及权值
i = LocateVex(G, va);
j = LocateVex(G, vb); //确定va和vb在G中的位置
G.arcs[i][j].adj = w; //w为权值
G.arcs[j][i] = G.arcs[i][j];
}//for
}//CreateAN


void CreateGraph(MGraph &G)
{ //采用数组(邻接矩阵)表示法,构造图G。
cout << "请输入图的类型(输入前面的数字){0.有向图, 1.有向网, 2.无向图, 3.无向网}:" << endl;
cin >> G.kind;
switch(G.kind)
{
case DG:
CreateDG(G); //构造有向图
break;
case DN:
CreateDN(G); //构造有向网
break;
case AG:
CreateAG(G); //构造无向图
break;
case AN:
CreateAN(G); //构造无向网
break;
default:
cout <<"输入的图的类型错误:" << endl;
break;
}
return;
}

int FirstAdjVex(MGraph G, int v)
{
int j, k = -1;
for(j = 0; j < G.vexnum; j++)
if(G.arcs[v][j].adj==1)
{
k = j;
break;
}
return k;
}

int NextAdjVex(MGraph G, int v, int w)
{
int j, k = -1;
for(j = w + 1; j < G.vexnum; j++)
if(G.arcs[v][j].adj==1)
{
k = j;
break;
}
return k;
}

void DFS(MGraph G, int v)
{
int j;
cout << G.vexs[v] << " ";
visited[v] = TRUE;
for(j = 0; j < G.vexnum; j++)
{
if(G.kind == DG || G.kind == AG)
if(!visited[j] && G.arcs[v][j].adj == 1)
DFS(G, j);
if(G.kind == DN || G.kind == AN)
if(!visited[j] && G.arcs[v][j].adj != INFINITY)
DFS(G, j);
}
}

void DFSTraverse(MGraph G)
{
int v;
for(v = 0; v < G.vexnum; v++)
visited[v] = FALSE; //初始化为FALSE,遍历后改为TRUE
for(v = 0; v < G.vexnum; v++)
if(!visited[v])
DFS(G, v);
}

void BFSTraverse(MGraph G)
{ //对以数组存储表示的图G进行广度优先搜索遍历
Queue Q; // 附设队列Q
int u, v, w;
for (v = 0; v < G.vexnum; ++v)
visited[v] = FALSE;
InitQueue(Q, G.vexnum); //设置空队列Q
for(v = 0; v < G.vexnum; ++v )
if(!visited[v])
{ //从每一个未被访问的顶点出发进行广度优先搜索
visited[v] = TRUE;
cout << G.vexs[v] << " "; //访问输出图中第v个顶点
EnQueue(Q, v); //v入队列
while(!QueueEmpty(Q))
{
DeQueue(Q, u); //队头元素出队并置为u
for(w = 0; w < G.vexnum; w++)
if(G.arcs[u][w].adj && ! visited[w])
{
visited[w] = TRUE;
cout << G.vexs[w] << " "; //访问输出图中第w个顶点
EnQueue(Q, w); //当前访问的顶点w入队列Q
}//if
}//while
}//if
DestroyQueue(Q);
}//BFSTraverse

int main(void)
{
MGraph G;
int i, j;
CreateGraph(G);
cout << "邻接矩阵为:" << endl;
for(i = 0; i < G.vexnum; i++)
{
for(j = 0; j < G.vexnum; j++)
{
cout << G.arcs[i][j].adj << " ";
}
cout << endl;
}
cout << "深度优先遍历为:";
DFSTraverse(G);
cout << endl;
cout << "广度优先遍历为:";
BFSTraverse(G);
cout << endl;
return 0;
}

原文地址:https://www.cnblogs.com/wwttsqt/p/7783205.html