杂谈:最近清明小长假,好好的放松了一下。节前 和 节后 都有点 松懈。不好,不好。贵在坚持。加油。
图的邻接矩阵表示法是用 两个数组 来表示 图的数据结构。一个是顶点数组,另一个是邻接矩阵数组。邻接矩阵 里存放着 顶点的关系。
用邻接矩阵表示图,在 看 顶点之间 是否有边,或者 求顶点的度等操作时比较简单。但空间浪费巨大,在插入,删除 顶点 和边 操作时 需要 移动大量数据,造成不便。所以在插入删除比较多,节点数比较多的时候 不宜 使用这种结构。
下面上代码:
源代码网盘地址:点击打开链接
// MGraph2.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <climits>
#include <cstring>
#define INFINITY INT_MAX
#define MAX_VERTEX_NUM 20
enum E_State
{
E_State_Error = 0,
E_State_Ok = 1,
};
enum E_Graph_Kind
{
DG = 0,//有向图
DN,//有向网
UDG,//无向图
UDN,//无向网
};
//边(弧)单元
typedef struct ArcCell
{
int adj;//表示顶点的关系类型,对于无权图,0,1表示是否相邻,对于有权图,表示权值类型
char * info;//边,弧其余信息.
}AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
//定义图
struct MGraph
{
char vexs[MAX_VERTEX_NUM];//顶点集
AdjMatrix arcs;//图的邻接矩阵
int vexNum,arcNum;
E_Graph_Kind kind;
};
int graphLocation(MGraph graph,char vex);
void createDG(MGraph * graph);
void createDN(MGraph * graph);
void createUDG(MGraph * graph);
void createUDN(MGraph * graph);
void graphCreate(MGraph * graph){
E_Graph_Kind kind;
printf("请输入要创建的图的类型(有向图:0,有向网:1,无向图:2,无向网:3)\n");
scanf("%d",&kind);
switch (kind){
case DG:
createDG(graph);
break;
case DN:
createDN(graph);
break;
case UDG:
createUDG(graph);
break;
case UDN:
createUDN(graph);
break;
default:
break;
}
}
//返回顶点vex的第一个邻接点
char firstAdjVex(MGraph graph,char vex){
int location = graphLocation(graph,vex);
int i = 0;
for (; i < graph.vexNum; i++){
if ((graph.kind == DG || graph.kind == UDG) && graph.arcs[location][i].adj == 1){
return graph.vexs[i];
}
else if((graph.kind == DN || graph.kind == UDN) && graph.arcs[location][i].adj != INFINITY){
return graph.vexs[i];
}
}
return ' ';
}
//返回顶点vex1 相对于 vex2的下一个邻接点.
char nextAdjVex(MGraph graph,char vex1,char vex2){
int location1 = graphLocation(graph,vex1);
int location2 = graphLocation(graph,vex2);
int i = location2+1;
for (; i < graph.vexNum; i++){
if ((graph.kind == DG || graph.kind == UDG) && graph.arcs[location1][i].adj == 1){
return graph.vexs[i];
}
else if((graph.kind == DN || graph.kind == UDN) && graph.arcs[location1][i].adj != INFINITY){
return graph.vexs[i];
}
}
return ' ';
}
//查找顶点的位置
int graphLocation(MGraph graph,char vex){
for (int i = 0; i < graph.vexNum; i++){
if (graph.vexs[i] == vex){
return i;
}
}
return -1;
}
//创建图 子函数
//有向图
void createDG(MGraph * graph){
graph->kind = DG;
printf("请输入顶点数,边(弧)数\n");
scanf("%d%d%*c",&graph->vexNum,&graph->arcNum);
//初始化邻接矩阵
for (int i = 0; i < MAX_VERTEX_NUM; i++){
for (int j = 0; j < MAX_VERTEX_NUM; j++){
graph->arcs[i][j].adj = 0;
graph->arcs[i][j].info = NULL;
}
}
//构造顶点集
printf("请输入顶点集\n");
for (int i = 0; i < graph->vexNum; i++){
scanf("%c",&graph->vexs[i]);
}
//构造顶点关系
fflush(stdin);
printf("请输入顶点的关系\n");
for (int i = 0; i < graph->arcNum; i++){
char vex1,vex2;
scanf("%c%c%*c",&vex1,&vex2);
int location1 = graphLocation(*graph,vex1);
int location2 = graphLocation(*graph,vex2);
graph->arcs[location1][location2].adj = 1;
}
}
//有向网
void createDN(MGraph * graph){
graph->kind = DN;
printf("请输入顶点数,边(弧)数\n");
scanf("%d%d%*c",&graph->vexNum,&graph->arcNum);
//初始化邻接矩阵
for (int i = 0; i < MAX_VERTEX_NUM; i++){
for (int j = 0; j < MAX_VERTEX_NUM; j++){
graph->arcs[i][j].adj = INFINITY;
graph->arcs[i][j].info = NULL;
}
}
//构造顶点集
printf("请输入顶点集\n");
for (int i = 0; i < graph->vexNum; i++){
scanf("%c",&graph->vexs[i]);
}
//构造顶点关系
fflush(stdin);
printf("请输入顶点的关系\n");
for (int i = 0; i < graph->arcNum; i++){
char vex1,vex2;
int weight;
scanf("%c%c%d%*c",&vex1,&vex2,&weight);
int location1 = graphLocation(*graph,vex1);
int location2 = graphLocation(*graph,vex2);
graph->arcs[location1][location2].adj = weight;
}
}
//无向图
void createUDG(MGraph * graph){
graph->kind = UDG;
printf("请输入顶点数,边(弧)数\n");
scanf("%d%d%*c",&graph->vexNum,&graph->arcNum);
//初始化邻接矩阵
for (int i = 0; i < MAX_VERTEX_NUM; i++){
for (int j = 0; j < MAX_VERTEX_NUM; j++){
graph->arcs[i][j].adj = 0;
graph->arcs[i][j].info = NULL;
}
}
//构造顶点集
printf("请输入顶点集\n");
for (int i = 0; i < graph->vexNum; i++){
scanf("%c",&graph->vexs[i]);
}
fflush(stdin);
//构造顶点关系
printf("请输入顶点的关系\n");
for (int i = 0; i < graph->arcNum; i++){
char vex1,vex2;
scanf("%c%c%*c",&vex1,&vex2);
int location1 = graphLocation(*graph,vex1);
int location2 = graphLocation(*graph,vex2);
graph->arcs[location1][location2].adj = graph->arcs[location2][location1].adj = 1;
}
}
//无向网
void createUDN(MGraph * graph){
graph->kind = UDN;
printf("请输入顶点数,边(弧)数\n");
scanf("%d%d%*c",&graph->vexNum,&graph->arcNum);
//初始化邻接矩阵
for (int i = 0; i < MAX_VERTEX_NUM; i++){
for (int j = 0; j < MAX_VERTEX_NUM; j++){
graph->arcs[i][j].adj = INFINITY;
graph->arcs[i][j].info = NULL;
}
}
//构造顶点集
printf("请输入顶点集\n");
for (int i = 0; i < graph->vexNum; i++){
scanf("%c",&graph->vexs[i]);
}
//构造顶点关系
fflush(stdin);
printf("请输入顶点的关系\n");
for (int i = 0; i < graph->arcNum; i++){
char vex1,vex2;
int weight;
scanf("%c%c%d%*c",&vex1,&vex2,&weight);
int location1 = graphLocation(*graph,vex1);
int location2 = graphLocation(*graph,vex2);
graph->arcs[location1][location2].adj =graph->arcs[location2][location1].adj = weight;
}
}
//查看顶点数据之间是否相邻
bool graphIsAdj(MGraph graph,char vex1,char vex2){
E_Graph_Kind kind = graph.kind;
int weight = (kind == DG || kind == UDG) ? 0 : INFINITY;
int location1 = graphLocation(graph,vex1);
int location2 = graphLocation(graph,vex2);
return graph.arcs[location1][location2].adj != weight ? true : false;
}
int graphDegree(MGraph graph,char vex){
int location = graphLocation(graph,vex);
E_Graph_Kind kind = graph.kind;
int weight = (kind == DG || kind == UDG) ? 0 : INFINITY;
int degree = 0;
for (int i = 0; i < graph.vexNum; i++){//计算行
if (graph.arcs[location][i].adj != weight){
degree++;
}
}
for (int i = 0; i < graph.vexNum; i++){//计算列
if (graph.arcs[i][location].adj != weight){
degree++;
}
}
if (kind == UDG || kind == UDN){
degree /= 2;
}
return degree;
}
//当有以下操作时,不适合 用邻接矩阵的方式来处理。
void insertVex(MGraph * graph,char vex){
graph->vexs[graph->vexNum++] = vex;
}
//需要移动很多元素.
void deleteVex(MGraph * graph,char vex){
int location = graphLocation(*graph,vex);
//删除顶点集
for (int i = location+1; i < graph->vexNum; i++){
graph->vexs[i-1] = graph->vexs[i];
}
//计算删除的边(弧)数
graph->arcNum -= graphDegree(*graph,vex);
//删除边(弧)
//vex下面的上移
for (int i = location+1; i < graph->vexNum; i++){
for (int j = 0; j < graph->vexNum; j++){
graph->arcs[i-1][j] = graph->arcs[i][j];
}
}
//vex右边的左移
for (int i = location + 1; i < graph->vexNum; i++){
for (int j = 0; j < graph->vexNum; j++){
graph->arcs[j][i-1] = graph->arcs[j][i];
}
}
//清理垃圾数据(第vexNum行 和 第vexNum列)
int maxVexNum = graph->vexNum;
E_Graph_Kind kind = graph->kind;
int weight = (kind == DG || kind == UDG) ? 0 : INFINITY;
for (int i = 0; i < maxVexNum; i++){
graph->arcs[maxVexNum-1][i].adj = weight;
graph->arcs[i][maxVexNum-1].adj = weight;
}
graph->vexNum--;
}
//插入边(弧)
void insertArc(MGraph * graph,char vex1,char vex2,int weight){
int location1 = graphLocation(*graph,vex1);
int location2 = graphLocation(*graph,vex2);
E_Graph_Kind kind = graph->kind;
if (kind == DG || kind == UDG){
graph->arcs[location1][location2].adj = 1;
}
else{
graph->arcs[location1][location2].adj = weight;
}
if (kind == UDG || kind == UDN)
{
graph->arcs[location2][location1].adj = graph->arcs[location1][location2].adj;
}
}
//删除边(弧)
void deleteArc(MGraph * graph,char vex1,char vex2){
int location1 = graphLocation(*graph,vex1);
int location2 = graphLocation(*graph,vex2);
E_Graph_Kind kind = graph->kind;
if (kind == DG || kind == UDG){
graph->arcs[location1][location2].adj = 0;
}
else{
graph->arcs[location1][location2].adj = INFINITY;
}
if (kind == UDG || kind == UDN)
{
graph->arcs[location2][location1].adj = graph->arcs[location1][location2].adj;
}
}
void printAdjMatrix(MGraph graph){
for (int i = 0; i < graph.vexNum; i++){
for (int j = 0; j < graph.vexNum; j++){
printf("%d\t",graph.arcs[i][j]);
}
printf("\n");
}
}
int _tmain(int argc, _TCHAR* argv[])
{
MGraph graph;
graphCreate(&graph);
printAdjMatrix(graph);
printf("图 有 %d个顶点,%d个边(弧)\n",graph.vexNum,graph.arcNum);
char * isAdj = graphIsAdj(graph,'a','d')? "相邻":"不相邻";
int degree = graphDegree(graph,'c');
printf("a 和 d %s,c的度数是:%d\n",isAdj,degree);
char vexFirst = firstAdjVex(graph,'c');
char vexNext = nextAdjVex(graph,'c','a');
printf("c的第一个邻接点是%c\nc的相对于a的下一个邻接点是%c\n",vexFirst,vexNext);
insertVex(&graph,'e');
printf("插入节点e之后:\n");
printAdjMatrix(graph);
printf("插入边(e,d)之后:\n");
insertArc(&graph,'e','d',1);
printAdjMatrix(graph);
printf("删除顶点c之后:\n");
deleteVex(&graph,'c');
printAdjMatrix(graph);
deleteArc(&graph,'a','b');
printf("删除弧(a,b)之后:\n");
printAdjMatrix(graph);
return 0;
}
运行截图:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIiclRnblN0LclHdpZXYyd2LcBzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CXq5ESNhXSE1kb1cVY0ZlbaZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39zMxIDM1EjMzEDOwQDM1EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)