IDE:Visual Studio 2019
声明:为了方便书写代码,用到了C++的引用调用特性和iostream作为输入输出,读者可以使用指针调用和scanf_s/print语句实现相同效果
tips:有疑问可以在下面交流,我会尽量回复的
头文件heads.h
#pragma once
#include "stdio.h"
#include "iostream"
#define OK 1
#define TRUE 1
#define FALSE 0
#define ERROR 0
#define OVERFLOW -1
using namespace std;
typedef short int Status;
头文件Graph.h
#include "heads.h"
typedef int VRType;//顶点关系类型
typedef int InfoType;//弧相关信息
typedef int VertexType;//顶点信息
enum GraphKind{ DG, DN, UDG, UDN };
//数组表示法
#define INFINITY INT_MAX;
#define MAX_VERTEX_NUM 20
typedef struct ArcCell {
VRType adj;
InfoType* info;
}AreCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef struct {
VertexType vexs[MAX_VERTEX_NUM];
AdjMatrix arcs;
int vexnum, arcnum;//图当前顶点数和弧数
enum GraphKind Kind;
}MGraph;
//MGraph
//创造邻接矩阵
Status CreateMGraph(MGraph& G);
//邻接表
typedef struct ArcNode {
int adjvex;
struct ArcNode* nextarc;
InfoType* info;
}ArcNode,*Arc;
typedef struct VNode {
VertexType data;
ArcNode* firstarc;
}VNode,AdjList[MAX_VERTEX_NUM];
typedef struct {
AdjList vertices;
int vexnum, arcnum;
enum GraphKind Kind;
}AlGraph;
//结点在图中的定位
int LocateVex(AlGraph G, VertexType e);
//创建邻接表
Status CreateAlGraph(AlGraph& G);
//删除邻接表
Status DestoryAlGraph(AlGraph& G);
//顶点赋值
Status PutVex(AlGraph& G, int i, VertexType e);
//返回第一个邻接点
int FirstAdjVex(AlGraph G, int v);
//返回下一个邻接点
int NextAdjVex(AlGraph G, int v, int w);
//增加结点
Status InsertVex(AlGraph& G, VertexType e);
//删除结点和依附的弧
Status DeleteVex(AlGraph& G, VertexType e);
//插入弧
Status InsertArc(AlGraph& G, int v, int w, InfoType e);
//删除弧
Status DeleteArc(AlGraph& G, int v, int w);
//深度优先遍历
Status visit(AlGraph G, int v);
void DFS(AlGraph G, int v);
void DFSTraverse(AlGraph G, Status(*visit)(AlGraph G, int v));
源文件ALGraph.cpp
#include "Graph.h"
bool visited[MAX_VERTEX_NUM];
Status(*VisitFunc)(AlGraph G, int v);
//弧的初始化
Status InitArc(AlGraph &G,int a,int b,InfoType e) {
Arc q=G.vertices[a].firstarc;
Arc p = (Arc)malloc(sizeof(ArcNode));
p->info = (InfoType*)malloc(sizeof(InfoType));
if (!p)return ERROR;
p->nextarc = NULL;
*(p->info) = e;
p->adjvex = b;
if (q == NULL) {
G.vertices[a].firstarc = p;
}
else {
while (q->nextarc)q = q->nextarc;
q->nextarc = p;
}
return OK;
}//InitArc
//结点在图中的定位
int LocateVex(AlGraph G, VertexType e) {
int i = 0;
for (; i < G.vexnum; i++) {
if (e == G.vertices[i].data)break;
}
return i;
}//LocateVex
//创建有向网
Status CreateDNAlGraph(AlGraph& G) {
cout << "有向网图开始初始化..." << endl;
VertexType v1, v2;
VRType w;
int i, j;
cout << "依次输入顶点数,弧数" << endl;
cin >> G.vexnum >> G.arcnum;
for (i = 0; i < G.vexnum; ++i) {
cout << "输入第" << i + 1 << "个顶点的元素" << endl;
cin >> G.vertices[i].data;
G.vertices[i].firstarc = NULL;
}
for (int k = 0; k < G.arcnum; k++) {
cout << "依次输入第" << k + 1 << "条弧依附的两个顶点的元素以及弧的权值" << endl;
cin >> v1 >> v2 >> w;
i = LocateVex(G, v1); j = LocateVex(G, v2);
InitArc(G, i, j, w);
}
return OK;
}//CreateDNAlGraph
//创建邻接表
Status CreateAlGraph(AlGraph& G) {
cout << "请输入邻接表的样式" << endl;
scanf_s("%u", &G.Kind);
switch (G.Kind)
{
case DN:return CreateDNAlGraph(G);
case UDN:break;
default:return ERROR;
}
}//CreateAlGraph
//删除邻接表
Status DestoryAlGraph(AlGraph& G) {
for (int i = 0; i < G.vexnum; ++i) {
Arc p = G.vertices[i].firstarc, q = p->nextarc;
if (p == NULL)continue;
while (p) {
free(p->info);
free(p);
p = q;
if(q->nextarc)q = q->nextarc;
}
}
free(&G);
return OK;
}//DeatoryAlGraph
//顶点赋值
Status PutVex(AlGraph& G, int i, VertexType e) {
G.vertices[i].data = e;
return OK;
}//PutVex
//返回第一个邻接点
int FirstAdjVex(AlGraph G, int v) {
if (G.vertices[v].firstarc)return G.vertices[v].firstarc->adjvex;
return -1;
}//FirstAdjVex
//返回下一个邻接点
int NextAdjVex(AlGraph G, int v, int w) {
Arc p = G.vertices[v].firstarc;
while (p) {
if (p->adjvex == w)break;
p = p->nextarc;
}
if (p == NULL || p->nextarc == NULL)return -1;
return p->nextarc->adjvex;
}//NextAdjVex
//增加结点
Status InsertVex(AlGraph& G, VertexType e) {
G.vertices[G.vexnum].data = e;
G.vertices[G.vexnum].firstarc = NULL;
G.vexnum++;
return OK;
}//InsertVex
//删除结点和依附的弧
Status DeleteVex(AlGraph& G, VertexType e) {
int i = LocateVex(G, e), j = 0;
Arc p = G.vertices[i].firstarc, q = p;
G.vertices[i].firstarc = NULL;
while (p) {
q = p->nextarc;
free(p->info);
free(p);
p = q;
j++;
}
for (int z = i; z < G.vexnum; z++) {
G.vertices[z].data = G.vertices[z + 1].data;
G.vertices[z].firstarc = G.vertices[z + 1].firstarc;
}
G.vexnum--;
for (int z = 0; z < G.vexnum; z++) {
p=G.vertices[z].firstarc;
if (p) {
if (p->adjvex == i) {
G.vertices[z].firstarc = p->nextarc;
free(p->info);
free(p);
j++;
p = G.vertices[z].firstarc;
}
while (p) {
if (p->adjvex == i) {
q->nextarc = p->nextarc;
free(p->info);
free(p);
j++;
p = q->nextarc;
continue;
}
if (p->adjvex > i) {
p->adjvex--;
}
q = p;
p = p->nextarc;
}
}
}
G.arcnum -= j;
return OK;
}//DeleteVex
//插入弧
Status InsertArc(AlGraph& G, int v, int w,InfoType e){
InitArc(G, v, w, e);
++G.arcnum;
return OK;
}//InsertArc
//删除弧
Status DeleteArc(AlGraph& G, int v, int w) {
int a, b;
a = LocateVex(G, v);
b = LocateVex(G, w);
Arc p = G.vertices[a].firstarc, q = p;
if (G.vertices[a].firstarc->adjvex == b) {
G.vertices[a].firstarc = p->nextarc;
free(p->info);
free(p);
G.arcnum--;
return OK;
}
else {
while (p) {
if (p->adjvex == b) {
q->nextarc = p->nextarc;
free(p->info);
free(p);
G.arcnum--;
return OK;
}
q = p;
p = p->nextarc;
}
}
return ERROR;
}//DeleteArc
//深度优先遍历
Status visit(AlGraph G, int v) {
cout<<G.vertices[v].data<<" ";
return OK;
}
void DFS(AlGraph G, int v) {
visited[v] = TRUE; VisitFunc(G, v);
for (int w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w)) {
if (!visited[w])DFS(G, w);
}
}
void DFSTraverse(AlGraph G, Status(*visit)(AlGraph G, int v)) {
VisitFunc = visit;
for (int v = 0; v < G.vexnum; ++v)visited[v] = FALSE;
for (int v = 0; v < G.vexnum; v++) {
if (!visited[v])DFS(G, v);
}
cout << endl;
}//DFSTraverse
MGraph.cpp
#include "Graph.h"
//结点在图中的定位
int LocateVex(MGraph G, VertexType e) {
int i = 0;
for (; i < G.vexnum; i++) {
if (e == G.vexs[i])break;
}
return i;
}
//弧相关信息输入
void Input(InfoType &e) {
cin >> e;
}
//无向网图的初始化
Status CreateMUDG(MGraph& G) {
cout << "无向网图开始初始化..." << endl;
bool IncInfo;
VertexType v1, v2;
VRType w;
int i, j;
cout << "依次输入顶点数,弧数以及是否有弧的相关信息" << endl;
cin >> G.vexnum >> G.arcnum >> IncInfo;
for (i = 0; i < G.vexnum; ++i) {
cout << "输入第"<<i+1<<"个顶点的元素" << endl;
cin >> G.vexs[i];
}
for (i = 0; i < G.vexnum; i++) {
for (int j = 0; j < G.vexnum; j++) {
G.arcs[i][j].adj = INFINITY;
G.arcs[i][j].info = NULL;
}
}
for (int k = 0; k < G.arcnum; k++) {
cout << "依次输入第"<<k+1<<"条弧依附的两个顶点的元素以及弧的权值" << endl;
cin >> v1 >> v2 >> w;
i = LocateVex(G, v1); j = LocateVex(G, v2);
G.arcs[i][j].adj = w;
if (IncInfo)Input(*G.arcs[i][j].info);
G.arcs[j][i] = G.arcs[i][j];
}
return OK;
}//CreateMUDG
//创造邻接矩阵
Status CreateMGraph(MGraph& G) {
cout << "输入矩阵类型,0:有向图;1:有向网;2:无向图;3:无向网;" << endl;
scanf_s("%u", &G.Kind);
switch(G.Kind)
{
//case DG:return CreateMDG(G);
//case DN:return CreateMDN(G);
//case UDG:return CreateMUDG(G);
case UDN:return CreateMUDG(G);
default:return ERROR;
}
}//CreateMGraph
Main.cpp
#include "Graph.h"
int main(void) {
AlGraph G;
CreateAlGraph(G);
DFSTraverse(G, visit);
DeleteVex(G, 8);
DFSTraverse(G, visit);
DeleteArc(G, 4, 6);
DFSTraverse(G, visit);
InsertVex(G, 1);
InsertArc(G, 1, 6, 1);
DFSTraverse(G, visit);
}
结果
指针!指针!还是指针!
注意从顶点元素到元素在邻接表数组内的下标的映射