算法设计与分析
图的基本操作及应用(邻接表&&邻接矩阵)
图的基本操作及应用
1.实验目的
(1)掌握图的基本存储方法;
(2)掌握有关图的操作算法并用高级语言实现;
(3)熟练掌握图的两种搜索路径的遍历方法。
2.实验内容
(1)图的基本操作
分别用邻接矩阵和邻接表两种方法表示一个无向图,并实现以下操作(完成实验报告):
a. 增加一个结点
b. 删除一个结点
c. 增加一条边
d. 删除一条边
(2)图的应用(选做,参考迪杰斯特拉算法和弗洛伊德算法)
假设以一个带权有向图表示某一区域的公交线路网,图中顶点代表一些区域中的重要场所,弧代表已有的公交线路,弧上的权表示该线路上的票价(或搭乘所需时间)。试设计一个简易交通指南系统,指导前来咨询者以最低的票价或最少的时间从区域中的某一场所到达另一场所。
3.实验步骤
(1)定义结点结构,定义图结构;
(2)存储图信息;
(3)定义求某顶点到其他所有顶点最短路径的函数;
(4)写出完整程序。
#include <iostream>
using namespace std;
#define MVNum 100
typedef struct ArcNode
{
int adjvex;
struct ArcNode *nextarc;
}ArcNode;
typedef struct VNode
{
char data;
ArcNode *firstarc;
}VNode, AdjList[MVNum];
typedef struct
{
AdjList vertices;
int vexnum, arcnum;
}ALGraph;
int LocateVex(ALGraph G, char v)
{
int i;
for (i = 0; i < G.vexnum; i++)
{
if (G.vertices[i].data == v)break;
}
return i;
}
void CreateUDG(ALGraph &G)
{
int i, j, k;
char v1, v2;
ArcNode *p1; ArcNode *p2;
cout << "请输入有向图的总顶点数及边数(以空格隔开):" << endl;
cin >> G.vexnum >> G.arcnum;
cout << "请依次输入各顶点的信息(如 a):" << endl;
for (i = 0; i < G.vexnum; ++i)
{
cout << "请依次输入第" << i + 1 << "个顶点:";
cin >> G.vertices[i].data;
G.vertices[i].firstarc = NULL;
}
cout << "请输入各条边依附的顶点(如 a b):" << endl;
for (k = 0; k < G.arcnum; ++k)
{
cout << "请输入第" << k + 1 << "条边依附的顶点:";
cin >> v1 >> v2;
i = LocateVex(G, v1); j = LocateVex(G, v2);
p1 = new ArcNode;
p1->adjvex = j;
p1->nextarc = G.vertices[i].firstarc; G.vertices[i].firstarc = p1;
p2 = new ArcNode;
p2->adjvex = i;
p2->nextarc = G.vertices[j].firstarc; G.vertices[j].firstarc = p2;
}
cout << "创建成功!" << endl;
}
void display(ALGraph G)
{
int i;
cout << "*****邻接表表示法创建的无向图*****" << endl;
for (i = 0; i < G.vexnum; ++i) {
VNode temp = G.vertices[i];
ArcNode *p = temp.firstarc;
if (p == NULL) {
cout << G.vertices[i].data;
}
else {
cout << temp.data;
while (p) {
cout << "->";
cout << p->adjvex + 1;
p = p->nextarc;
}
}
cout << endl;
}
}
void Insert_Vex(ALGraph &G, char v)
{
cout << "请输入新顶点的信息:";
cin >> v;
G.vertices[G.vexnum].data = v;
G.vertices[G.vexnum].firstarc = NULL;
G.vexnum++;
cout << "增加成功!" << endl;
}
void Delete_Vex(ALGraph &G, char v)
{
ArcNode *p1, *p2;
p1 = new ArcNode; p2 = new ArcNode;
cout << "请输入需要删除的顶点:";
cin >> v;
int i = LocateVex(G, v);
G.vertices[i].firstarc = NULL;
for (int j = i; j < G.vexnum - 1; j++)
{
G.vertices[j] = G.vertices[j + 1];
}
G.vexnum--;
for (int k = 0; k < G.vexnum; k++)
{
p1 = G.vertices[k].firstarc; p2 = p1->nextarc;
if ((*p1).adjvex == i)
{
G.vertices[k].firstarc = p1->nextarc;
while (p2)
{
if ((*p2).adjvex > i)(*p2).adjvex--;
p2 = p2->nextarc;
}
}
else if ((*p1).adjvex > i)
{
(*p1).adjvex--;
while (p2)
{
if ((*p2).adjvex == i)p1->nextarc = p2->nextarc;
else if ((*p2).adjvex > i)(*p2).adjvex--;
p1 = p1->nextarc;
p2 = p2->nextarc;
}
}
else
{
while (p2)
{
if ((*p2).adjvex == i)p1->nextarc = p2->nextarc;
else if ((*p2).adjvex > i)(*p2).adjvex--;
p1 = p1->nextarc;
p2 = p2->nextarc;
}
}
}
cout << "删除成功!" << endl;
}
void Insert_Arc(ALGraph &G, char v, char w)
{
int i, j;
ArcNode *p1, *p2;
cout << "请输入新边依附的两个顶点:";
cin >> v >> w;
if ((i = LocateVex(G, v)) < 0) cout << "位置有误,插入失败!" << endl;
if ((j = LocateVex(G, w)) < 0) cout << "位置有误,插入失败!" << endl;
p1 = new ArcNode;
p1->adjvex = j;
p1->nextarc = G.vertices[i].firstarc; G.vertices[i].firstarc = p1;
p2 = new ArcNode;
p2->adjvex = i;
p2->nextarc = G.vertices[j].firstarc; G.vertices[j].firstarc = p2;
G.arcnum++;
cout << "增加成功!" << endl;
}
void Delete_Arc(ALGraph &G, char v, char w)
{
int i, j;
ArcNode *p1, *p2;
ArcNode *q1, *q2;
p1 = new ArcNode; p2 = new ArcNode;
q1 = new ArcNode; q2 = new ArcNode;
cout << "请输入要删除的边依附的顶点:";
cin >> v >> w;
if ((i = LocateVex(G, v)) < 0) cout << "该边不存在,删除失败!" << endl;
if ((j = LocateVex(G, w)) < 0) cout << "该边不存在,删除失败!" << endl;
p1 = G.vertices[j].firstarc; p2 = p1->nextarc;
if ((*p1).adjvex == i)G.vertices[j].firstarc = p1->nextarc;
else
{
while (p2)
{
if ((*p2).adjvex == i)p1->nextarc = p2->nextarc;
p1 = p1->nextarc;
p2 = p2->nextarc;
}
}
p1 = G.vertices[i].firstarc; p2 = p1->nextarc;
if ((*p1).adjvex == j)G.vertices[i].firstarc = p1->nextarc;
else
{
while (p2)
{
if ((*p2).adjvex == j)p1->nextarc = p2->nextarc;
p1 = p1->nextarc;
p2 = p2->nextarc;
}
}
cout << "删除成功!" << endl;
}
int main()
{
ALGraph G; int x;
char v='0', w='0';
CreateUDG(G);
cout << "[1]、增加一个新顶点" << '\t' << "[2]、删除顶点v及其相关的边" << endl;
cout << "[3]、增加一条边" << '\t' << '\t' << "[4]、删除一条边" << endl;
cout << "[5]、输出邻接表" << '\t' << '\t' << "[0]、退出" << endl;
cout << "请选择功能键:" << endl;
do {
cin >> x;
switch (x)
{
case 1:Insert_Vex(G, v); break;
case 2:Delete_Vex(G, v); break;
case 3:Insert_Arc(G, v, w); break;
case 4:Delete_Arc(G, v, w); break;
case 5:display(G); break;
case 0:cout << "已退出!" << endl; return 0;
default:cout << "输入错误,请重新输入!" << endl;
}
cout << "[1]、增加一个新顶点" << '\t' << "[2]、删除顶点v及其相关的边" << endl;
cout << "[3]、增加一条边" << '\t' << '\t' << "[4]、删除一条边" << endl;
cout << "[5]、输出邻接表" << '\t' << '\t' << "[0]、退出" << endl;
cout << "请选择功能键:" << endl;
} while (true);
}
#include <iostream>
using namespace std;
#define MVNum 32
typedef char VerTexType;
typedef int ArcType;
typedef struct
{
VerTexType vexs[MVNum];
ArcType arcs[MVNum][MVNum];
int vexnum, arcnum;
}AMGraph;
void CreateUDN(AMGraph &G);
int LocateVex(AMGraph G, VerTexType v);
void AddVex(AMGraph &G);
void DeleteVex(AMGraph &G);
void AddArc(AMGraph &G);
void DeleteArc(AMGraph &G);
void Show(AMGraph G);
int main()
{
AMGraph G;
CreateUDN(G);
Show(G);
cout << "1.增加一个结点" << endl;
cout << "2.删除一个结点" << endl;
cout << "3.增加一条边" << endl;
cout << "4.删除一条边" << endl;
cout << "0.退出" << endl;
int choose = -1;
while (choose != 0)
{
cout << "请选择:" << endl;
cin >> choose;
switch (choose)
{
case 1:
{
AddVex(G);
Show(G);
break;
}
case 2:
{
DeleteVex(G);
Show(G);
break;
}
case 3:
{
AddArc(G);
Show(G);
break;
}
case 4:
{
DeleteArc(G);
Show(G);
break;
}
}
}
return 0;
}
void CreateUDN(AMGraph &G)
{
int i, j, k;
cout << "请输入总顶点数,总边数,以空格隔开:";
cin >> G.vexnum >> G.arcnum;
cout << endl;
cout << "请输入各个点的名称,如a,中间用空格隔开:" << endl;
for (i = 0; i < G.vexnum; ++i)
cin >> G.vexs[i];
cout << endl;
for (i = 0; i < G.vexnum; ++i)
for (j = 0; j < G.vexnum; ++j)
G.arcs[i][j] = 0;
cout << "输入边依附的顶点,如 a b" << endl;
for (k = 0; k < G.arcnum; ++k)
{
VerTexType v1, v2;
cout << "请输入第" << (k + 1) << "条边依附的顶点:";
cin >> v1 >> v2;
i = LocateVex(G, v1);
j = LocateVex(G, v2);
G.arcs[i][j] = 1;
G.arcs[j][i] = G.arcs[i][j];
}
}
int LocateVex(AMGraph G, VerTexType v)
{
int i;
for (i = 0; i < G.vexnum; ++i)
if (G.vexs[i] == v)
return i;
return -1;
}
void AddVex(AMGraph &G)
{
int i, j, k, n;
cout << "请输入新增点的名称:" << endl;
cin >> G.vexs[G.vexnum];
for (i = G.vexnum; i >= 0; --i)
for (j = G.vexnum; j >= 0; --j)
{
G.arcs[i][j] = 0;
if (i < G.vexnum)
break;
}
G.vexnum = G.vexnum + 1;
cout << "请输入新增边的个数:" << endl;
cin >> n;
for (k = G.arcnum; k < (G.arcnum + n); ++k)
{
VerTexType v1, v2;
cout << "请输入新增第" << (k - G.arcnum + 1) << "条边依附的顶点:";
cin >> v1 >> v2;
i = LocateVex(G, v1);
j = LocateVex(G, v2);
G.arcs[i][j] = 1;
G.arcs[j][i] = G.arcs[i][j];
}
G.arcnum = G.arcnum + n;
}
void DeleteVex(AMGraph &G)
{
int i, j, k, flag, num = 0;
VerTexType v;
cout << "请输入删除结点的名称:" << endl;
cin >> v;
flag = LocateVex(G, v);
for (j = 0; j < G.vexnum; ++j)
if (G.arcs[flag][j] == 1)
num++;
for (i = flag; i < G.vexnum - 1; ++i)
for (j = 0; j < G.vexnum; ++j)
G.arcs[i][j] = G.arcs[i + 1][j];
for (i = 0; i < G.vexnum; ++i)
for (j = flag; j < G.vexnum - 1; ++j)
G.arcs[i][j] = G.arcs[i][j + 1];
G.vexnum = G.vexnum - 1;
G.arcnum = G.arcnum - (2 * num);
}
void AddArc(AMGraph &G)
{
int i, j;
VerTexType v1, v2;
cout << "请输入新增边依附的顶点:";
cin >> v1 >> v2;
i = LocateVex(G, v1);
j = LocateVex(G, v2);
G.arcs[i][j] = 1;
G.arcs[j][i] = G.arcs[i][j];
}
void DeleteArc(AMGraph &G)
{
int i, j;
VerTexType v1, v2;
cout << "请输入删除边依附的顶点:";
cin >> v1 >> v2;
i = LocateVex(G, v1);
j = LocateVex(G, v2);
G.arcs[i][j] = 0;
G.arcs[j][i] = G.arcs[i][j];
}
void Show(AMGraph G)
{
int i, j;
for (i = 0; i < G.vexnum; ++i)
{
for (j = 0; j < G.vexnum; ++j)
{
if (j != G.vexnum - 1)
cout << G.arcs[i][j] << " ";
else
cout << G.arcs[i][j] << endl;
}
}
cout << endl;
}