实验目的:
通过上机实验进一步掌握图的存储结构及基本操作的实现。
实验内容与要求:
分别基于邻接矩阵(不用做)和邻接表存储结构实现图的基本运算,要求:
⑴能根据输入的顶点、边/弧的信息建立图;
⑵实现图中顶点、边/弧的插入、删除;
⑶实现对该图的深度优先遍历;
⑷实现对该图的广度优先遍历。
#include<iostream>
#include<vector>
using namespace std;
class Graphic {
private:
struct ANode {
int location; //位置信息
int weight; //权重
ANode* next;
};
struct VNode {
char name; //顶点信息;
ANode* first; //头结点
ANode* temp; //利用临时节点实现尾部插入
VNode() {
name = '0';
first = new ANode;
first->location = -1;
first->weight = -1;
first->next = NULL;
temp = first;
}
};
vector<VNode>ALGraphic;
int vexnum = 0; //顶点数
int arcnum = 0; //边数
public:
void create_Graphic(); //创建图
void insert_VNode(); //插入顶点
void delete_VNode(); //删除顶点及其所属边
void insert_Arc(); //插入边
void delete_Arc(); //删除边
void delete_Arc(int i,int j);
void DFSTraverse(); //深度优先遍历
void BFSTraverse(); //广度优先遍历
void print(); //遍历邻接表
bool exist(char a) { //判断该点是否在图中,若在则为真
int z = 0;
for (unsigned int i = 0; i < ALGraphic.size(); i++) {
if (ALGraphic[i].name == a)z = 1;
}
if (z == 0)return false;
else {
return true;
}
}
bool connect(char a, char b,int &x,int &y) { //判断两个顶点间是否有连接关系,若有则为真
for (unsigned int i = 0; i < ALGraphic.size(); i++) {
if (ALGraphic[i].name == a)x = i;
if (ALGraphic[i].name == b)y = i;
}
ANode* p = ALGraphic[x].first->next;
while (p != NULL) {
if (p->location == y)return true;
p = p->next;
}
return false;
}
};
void Graphic::create_Graphic()
{
cout << "输入顶点数:";
cin >> this->vexnum;
for (int i = 0; i < vexnum; i++) {
cout << "输入第" << i+1 << "个顶点的名称(例:a):";
VNode node;
cin >> node.name;
ALGraphic.push_back(node);
}
cout << endl;
cout << "输入边数:";
cin >> this->arcnum;
for (int i = 0; i < arcnum; i++) {
char a, b;
int x = 0, y = 0;
int w;
cout << "输入第" << i+1 << "条边的信息(顶点1 顶点2 权重)(例:a b 3):";
cin >> a >> b >> w;
if (!exist(a)) {
cout << "顶点" << a << "不存在"<<endl;
i--;
}
else if (!exist(b)) {
cout << "顶点" << b << "不存在"<<endl;
i--;
}
else {
if (!connect(a, b, x, y)) {
ANode* q1 = new ANode;
q1->next = NULL;
q1->location = y;
q1->weight = w;
ALGraphic[x].temp->next = q1;
ALGraphic[x].temp = q1;
ANode* q2 = new ANode;
q2->next = NULL;
q2->location = x;
q2->weight = w;
ALGraphic[y].temp->next = q2;
ALGraphic[y].temp = q2;
}
else {
cout << "该边已存在" << endl;
i--;
}
}
}
cout << "创建成功!"<<endl;
}
void Graphic::insert_VNode()
{
vexnum++;
cout<<endl<< "输入第" << vexnum << "个顶点的名称(例:a):";
VNode node;
cin >> node.name;
ALGraphic.push_back(node);
cout << "插入成功!" << endl;
}
void Graphic::delete_VNode()
{
char a;
cout << "输入要删除的顶点名称:";
cin >> a;
if (!exist(a)) {
cout << "顶点" << a << "不存在" << endl;
}
else {
int x = 0;
for (unsigned int i = 0; i < ALGraphic.size(); i++) {
if (ALGraphic[i].name == a)x = i;
}
for (int i = 0; i < vexnum; i++) {
if (i != x) {
delete_Arc(x, i);
}
}
ALGraphic.erase(ALGraphic.begin() + x);
//更新剩余顶点位置
for (unsigned int i = 0; i < ALGraphic.size(); i++) {
ANode* p = ALGraphic[i].first->next;
while (p != NULL) {
if (p->location >= x)
p->location = p->location - 1;
p = p->next;
}
}
vexnum--;
cout << "顶点" << a << "及其附属边删除成功!" << endl;
}
}
void Graphic::insert_Arc()
{
char a, b; int w;
cout << "插入第" << arcnum << "条边的信息(顶点1 顶点2 权重)(例:a b 3):";
cin >> a >> b >> w;
if (!exist(a)) {
cout << "顶点" << a << "不存在" << endl;
}
else if (!exist(b)) {
cout << "顶点" << b << "不存在" << endl;
}
else {
int x = 0, y = 0;
if (!connect(a, b, x, y)) {
ANode* q1 = new ANode;
q1->next = NULL;
q1->location = y;
q1->weight = w;
ALGraphic[x].temp->next = q1;
ALGraphic[x].temp = q1;
ANode* q2 = new ANode;
q2->next = NULL;
q2->location = x;
q2->weight = w;
ALGraphic[y].temp->next = q2;
ALGraphic[y].temp = q2;
cout << "插入成功!"<<endl;
arcnum++;
}
else {
cout << "该边已存在" << endl;
}
}
}
void Graphic::delete_Arc()
{
char a, b;
cout<< "输入需删除的边(例:a b):";
cin >> a >> b;
int i, j;
if (!exist(a)) {
cout << "顶点" << a << "不存在" << endl;
}
else if (!exist(b)) {
cout << "顶点" << b << "不存在" << endl;
}
else if (!connect(a, b,i,j)) {
cout << "边" << a << b << "不存在"<<endl;
}
else {
ANode* p1 = ALGraphic[i].first;
ANode* q1 = p1->next;
while (q1 != NULL) {
if (q1->location == j) {
p1->next = q1->next;
}
p1 = p1->next;
q1 = q1->next;
}
ANode* p2 = ALGraphic[j].first;
ANode* q2 = p2->next;
while (q2 != NULL) {
if (q2->location == i) {
p2->next = q2->next;
}
p2 = p2->next;
q2 = q2->next;
}
arcnum--;
cout<< "边" << a << b << "删除成功!" << endl;
}
}
void Graphic::delete_Arc(int i, int j) {
if (connect(ALGraphic[i].name, ALGraphic[j].name, i, j)) {
ANode* p1 = ALGraphic[i].first;
ANode* q1 = p1->next;
while (q1 != NULL) {
if (q1->location == j) {
p1->next = q1->next;
}
p1 = p1->next;
q1 = q1->next;
}
ANode* p2 = ALGraphic[j].first;
ANode* q2 = p2->next;
while (q2 != NULL) {
if (q2->location == i) {
p2->next = q2->next;
}
p2 = p2->next;
q2 = q2->next;
}
arcnum--;
}
}
void Graphic::DFSTraverse()
{
cout<< "无向图的深度优先遍历结果为:";
int *v = new int[vexnum](); //记录数组
int i = 0;
while (1) {
if (v[i] != 1) {
cout << ALGraphic[i].name;
v[i] = 1;
ANode *p= ALGraphic[i].first->next;
while (p!=NULL) {
if (v[p->location] != 1) {
i = p->location;
break;
}
p = p->next;
}
}
else {
if(i<vexnum-1)
i++;
}
//判断是否全部遍历
int b = 0;
for (int j = 0; j < vexnum; j++) {
if (v[j] != 1)b = 1;
}
if (b == 0)break;
}
cout << endl;
}
void Graphic::BFSTraverse()
{
cout << "无向图的广度优先遍历结果为:";
int* v = new int[vexnum](); //记录数组
int i = 0;
while (1) {
if (v[i] != 1) {
cout << ALGraphic[i].name;
v[i] = 1;
int j = i;
ANode* p = ALGraphic[i].first->next;
while (p != NULL) {
if (v[p->location] != 1) {
i = p->location;
cout << ALGraphic[i].name;
v[i] = 1;
}
p = p->next;
}
if (i < vexnum - 1)i = j + 1;
}
else {
if (i < vexnum - 1)
i++;
}
//判断是否全部遍历
int b = 0;
for (int j = 0; j < vexnum; j++) {
if (v[j] != 1)b = 1;
}
if (b == 0)break;
}
cout << endl;
}
void Graphic::print()
{
for (unsigned int i = 0; i < ALGraphic.size(); i++) {
cout << ALGraphic[i].name << "(" << i << "):";
ANode* p = ALGraphic[i].first->next;
while (p != NULL) {
cout << ALGraphic[p->location].name << "(" << p->location << ")";
p = p->next;
}
cout << endl;
}
}
//菜单
void show() {
cout << "---邻接表实现无向图的基本运算---" << endl;
cout << "1.创建图" << endl;
cout << "2.插入顶点" << endl;
cout << "3.删除顶点" << endl;
cout << "4.插入边" << endl;
cout << "5.删除边" << endl;
cout << "6.深度优先遍历" << endl;
cout << "7.广度优先遍历" << endl;
cout << "8.遍历邻接表" << endl;
cout << "0.退出" << endl;
}
int main() {
Graphic T;
int n;
show();
while (1) {
cout << endl;
cin >> n;
if (n == 1)T.create_Graphic();
else if (n == 2)T.insert_VNode();
else if (n == 3)T.delete_VNode();
else if (n == 4)T.insert_Arc();
else if (n == 5)T.delete_Arc();
else if (n == 6)T.DFSTraverse();
else if (n == 7)T.BFSTraverse();
else if (n == 8)T.print();
else {
break;
}
}
}