图的结构体
与邻接表不同,用邻接矩阵实现图,需要用一个一维数组存储顶点,一个二维数组存储邻接矩阵
由于此处是动态分配,使用指针
typedef int ArcType;
//点
struct Vertex {
char* name; // 点的名字
};
//弧
struct Arc {
ArcType ArcValue;
};
//图的类型
enum GraphKind {
DG, //0 有向图
DN, //1 有向网
UDG, //2 无向图
UDN //3 无向网
};
//图
struct Graph {
int VertexNum, ArcNum; //点数,弧数
GraphKind kind; //图的种类
Vertex* v;
Arc** arc;
};
创建图
//获取顶点v的序号(下标)
int VertexLoc(Graph G, Vertex v) {
for (int i = 0; i < G.VertexNum; i++) {
if (strcmp(v.name, G.v[i].name) == 0)
return i;
}
return -1; //否则返回-1
}
//创建图
void CreateGraph(Graph& G) {
//1.图类型
//2.输入点数、弧数
//3.给点起名字
//4.创建弧的邻接矩阵
//1.图类型
cout << "请输入图的类型(0有向图 1有向网 2无向图 3无向网)" << endl;
int kind;
cin >> kind;
G.kind = (GraphKind)kind;
//2.输入点数、弧数
cout << "请输入 点数 弧数" << endl;
cin >> G.VertexNum >> G.ArcNum;
//给点的数组分配内存
G.v = (Vertex*)malloc(G.VertexNum * sizeof(Vertex));
if (!G.v)
exit(ERROR);
//3.给点起名字
for (int i = 0; i < G.VertexNum; i++) {
cout << "请输入第" << i + 1 << "个点的名字:" << endl;
G.v[i].name = (char*)malloc(sizeof(char));
if (!G.v[i].name)
exit(ERROR);
cin >> G.v[i].name;
}
//4.初始化+创建弧的邻接矩阵
int value = 0; //图
if (G.kind % 2) //网
value = INF;
G.arc = (Arc**)malloc(G.VertexNum * sizeof(Arc*)); //列
if (!G.arc)
exit(ERROR);
for (int i = 0; i < G.VertexNum; i++) {
G.arc[i] = (Arc*)malloc(G.VertexNum * sizeof(Arc));
if (!G.arc[i])
exit(ERROR);
for (int j = 0; j < G.VertexNum; j++)
G.arc[i][j].ArcValue = value;
}
Vertex tail, head;
tail.name = (char*)malloc(sizeof(char));
head.name = (char*)malloc(sizeof(char));
//创建
//图
if (G.kind % 2 == 0) {
for (int i = 0; i < G.ArcNum; i++) {
cout << "请输入第" << i + 1 << "条弧的弧尾 弧头";
cin >> tail.name >> head.name;
int tailLoc, headLoc;
tailLoc = VertexLoc(G, tail);
headLoc = VertexLoc(G, head);
G.arc[tailLoc][headLoc].ArcValue = 1;
//无向图
if (G.kind == 2)
G.arc[headLoc][tailLoc].ArcValue = 1;
}
}
//网
if (G.kind % 2) {
for (int i = 0; i < G.ArcNum; i++) {
cout << "请输入第" << i + 1 << "条弧的 弧尾 弧头 权值";
ArcType value;
cin >> tail.name >> head.name >> value;
int tailLoc, headLoc;
tailLoc = VertexLoc(G, tail);
headLoc = VertexLoc(G, head);
G.arc[tailLoc][headLoc].ArcValue = value;
//无向网
if (G.kind == 3)
G.arc[headLoc][tailLoc].ArcValue = value;
}
}
}
*其中VertexNum 行VertexNum 列二维数组的动态分配内存*
G.arc = (Arc**)malloc(G.VertexNum * sizeof(Arc*));
G.arc[i] = (Arc*)malloc(G.VertexNum * sizeof(Arc));
输出图(遍历二维数组即可)
//输出图
void PrintGraph(Graph& G) {
//输出顶点
cout << "该图的" << G.VertexNum << "个顶点为" << endl;
for (int i = 0; i < G.VertexNum; i++)
cout << G.v[i].name << " ";
cout << endl;
//输出邻接矩阵
for (int i = 0; i < G.VertexNum; i++) {
for (int j = 0; j < G.VertexNum; j++) {
cout << G.arc[i][j].ArcValue << " ";
}
cout << endl;
}
}
点和弧的插入删除
1.插入点要给点数组和邻接矩阵重新分配内存和初始化
2. 删除点要删除和它关联的所有弧,并移动下标
//插入点
void InsertVertex(Graph& G, Vertex v) {
//点+1
Vertex* new_v = (Vertex*)realloc(G.v, (G.VertexNum + 1) * sizeof(Vertex));
if (!new_v)
exit(OVERFLOW);
new_v[G.VertexNum] = v;
G.v = new_v;
//邻接矩阵+1行1列
Arc** new_arc = (Arc**)realloc(G.arc, (G.VertexNum + 1) * sizeof(Arc*));
if (!new_arc)
exit(OVERFLOW);
for (int i = 0; i < G.VertexNum; i++) {
new_arc[i] = (Arc*)realloc(G.arc[i], (G.VertexNum + 1) * sizeof(Arc));
if (!new_arc[i])
exit(OVERFLOW);
}
new_arc[G.VertexNum] = (Arc*)malloc((G.VertexNum + 1) * sizeof(Arc));
G.arc = new_arc;
ArcType value = 0;
if (G.kind % 2)
value = INF;
for (int i = 0; i <= G.VertexNum; i++) {
G.arc[G.VertexNum][i].ArcValue = value;
G.arc[i][G.VertexNum].ArcValue = value;
}
G.VertexNum++;
}
//添加弧
status InsertArc(Graph& G, Vertex tail, Vertex head) {
int tailLoc, headLoc;
tailLoc = VertexLoc(G, tail);
if (tailLoc == -1)
return ERROR;
headLoc = VertexLoc(G, head);
if (headLoc == -1)
return ERROR;
int value = 1;
if (G.arc[tailLoc][headLoc].ArcValue != 0 && G.arc[tailLoc][headLoc].ArcValue != INF) //该点已存在弧
return ERROR;
ArcType ArcValue;
if (G.kind % 2 == 1) {
//网
cout << "请输入该弧的权值" << endl;
cin >> ArcValue;
}
G.arc[tailLoc][headLoc].ArcValue = ArcValue;
if (G.kind > 2)
//无向
G.arc[headLoc][tailLoc].ArcValue = ArcValue;
G.ArcNum++;
return OK;
}
//删除弧
status DeleteArc(Graph& G, Vertex tail, Vertex head) {
int tailLoc = VertexLoc(G, tail);
int headLoc = VertexLoc(G, head);
if (tailLoc == -1 || headLoc == -1)
return ERROR;
int ArcValue = 0;
if (G.kind % 2 == 1) //网
ArcValue = INF;
if (G.arc[tailLoc][headLoc].ArcValue == 0 || G.arc[tailLoc][headLoc].ArcValue == INF) //当前弧不存在
return ERROR;
G.arc[tailLoc][headLoc].ArcValue = ArcValue;
if (G.kind < 2) //有向
G.arc[headLoc][tailLoc].ArcValue = ArcValue;
G.ArcNum--;
return OK;
}
//删除顶点
status DeleteVertex(Graph& G, Vertex v) {
int vLoc = VertexLoc(G, v);
if (vLoc == -1)
return ERROR;
//删除相关弧
for (int i = 0; i < G.VertexNum; i++)
DeleteArc(G, v, G.v[i]);
for (int i = 1; i < G.VertexNum; i++)
DeleteArc(G, G.v[i], v);
//移动弧下标
for (int i = vLoc; i < G.VertexNum - 1; i++) {
G.arc[i] = G.arc[i + 1];
for (int j = 0; j < G.VertexNum; j++)
G.arc[j][i] = G.arc[j][i + 1];
}
G.VertexNum--;
return OK;
}