图的基本操作及应用(邻接表&&邻接矩阵)

算法设计与分析

图的基本操作及应用(邻接表&&邻接矩阵)

图的基本操作及应用
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;
	//OtherInfo info;
}ArcNode;
typedef struct VNode
{
	char data;
	ArcNode *firstarc;
}VNode, AdjList[MVNum];
typedef struct
{
	AdjList vertices;
	int vexnum, arcnum;
}ALGraph;
//确定定点在G中的位置
int LocateVex(ALGraph G, char v)
{
	int i;
	for (i = 0; i < G.vexnum; i++)
	{
		if (G.vertices[i].data == v)break;
	}
	return i;
}
//采用邻接表表示法,创建无向图G
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;
}
//删除顶点v及其相关的边
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);		//确定v1和v2在G中的位置,即顶点数组的下标
		G.arcs[i][j] = 1;			//边<v1, v2>的权值置为1
		G.arcs[j][i] = G.arcs[i][j];//置<v1, v2>的对称边<v2, v1>的权值为1
	}
}
//查找点的位置
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);		//确定v1和v2在G中的位置,即顶点数组的下标
		G.arcs[i][j] = 1;			//边<v1, v2>的权值置为1
		G.arcs[j][i] = G.arcs[i][j];//置<v1, v2>的对称边<v2, v1>的权值为1
	}
	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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值