数据结构实验-无向图-通信网络的建立

内容:

项目名称:通信网构建 项目内容:
在 n 个城市之间建立通信联络网,则连通 n 个城市只需要 n-1 条线路。
要求在 最节省经费的前提下建立这个通信网。
(1) 完成城市信息的输入。
(2) 完成城市信息的编辑,包括城市以及城市间距离的增加,删除,信息修改等。
(3) 允许用户指定下列两种策略进行通信网的构建
1.采用 Prim 算法进行通信网的构建;
2.采用 Kruskal 算法进行通信网的构建;

代码实现:

main函数:

#include<iostream>
#include<string>
#include"Graph.h"
#include"SqList.hpp"
using namespace std;

void test01(Graph* graph) {
 //输入测试数据
 Vex v1; v1.code = "V1"; v1.Name = "北京";
 Vex v2; v2.code = "V2"; v2.Name = "成都";
 Vex v3; v3.code = "V3"; v3.Name = "武汉";
 Vex v4; v4.code = "V4"; v4.Name = "上海";
 Vex v5; v5.code = "V5"; v5.Name = "广州";
 Vex v6; v6.code = "V6"; v6.Name = "深圳";
 graph->InsertVex(v1);
 graph->InsertVex(v2);
 graph->InsertVex(v3);
 graph->InsertVex(v4);
 graph->InsertVex(v5);
 graph->InsertVex(v6);
 Edge e1; e1.vex1 = v1; e1.vex2 = v2; e1.weight = 6;
 Edge e2; e2.vex1 = v1; e2.vex2 = v3; e2.weight = 1;
 Edge e3; e3.vex1 = v1; e3.vex2 = v4; e3.weight = 5;
 Edge e4; e4.vex1 = v2; e4.vex2 = v3; e4.weight = 5;
 Edge e5; e5.vex1 = v2; e5.vex2 = v5; e5.weight = 3;
 Edge e6; e6.vex1 = v3; e6.vex2 = v4; e6.weight = 5;
 Edge e7; e7.vex1 = v3; e7.vex2 = v5; e7.weight = 6;
 Edge e8; e8.vex1 = v3; e8.vex2 = v6; e8.weight = 4;
 Edge e9; e9.vex1 = v4; e9.vex2 = v6; e9.weight = 2;
 Edge e10; e10.vex1 = v5; e10.vex2 = v6; e10.weight = 6;
 graph->InsertEdges(e1);
 graph->InsertEdges(e2);
 graph->InsertEdges(e3);
 graph->InsertEdges(e4);
 graph->InsertEdges(e5);
 graph->InsertEdges(e6);
 graph->InsertEdges(e7);
 graph->InsertEdges(e8);
 graph->InsertEdges(e9);
 graph->InsertEdges(e10);
 cout << "添加成功" << endl;
 system("pause");
}
int main() {
 Graph *graph = new Graph();
 Edge a[10];
 while (1) {
  system("cls");
  cout << "1.测试案例" << endl;
  cout << "2.添加顶点" << endl;
  cout << "3.添加边" << endl;
  cout << "4.prim算法" << endl;
  cout << "5.kruskal算法" << endl;
  cout << "6.删除修改信息" << endl;
  cout << "7.打印顶点和边的信息" << endl;
  cout << "8.退出" << endl;
  int m;
  cin >> m;
  switch (m) {
  case 1: {
   test01(graph);
   break;
  }
  case 2: {
   cout << "输入要添加的顶点数:" << endl;
   int n = 0;
   cin >> n;
   for (int i = 0; i < n; i++) {
    Vex v;
    cout << "输入顶点编号" << endl;
    cin >> v.code;
    cout << "输入顶点名称" << endl;
    cin >> v.Name;
    graph->InsertVex(v);
   }
   break;
  }
  case 3: {
   cout << "输入要添加的边数:" << endl;
   int n = 0;
   cin >> n;
   for (int i = 0; i < n; i++) {
    Edge e;
    cout << "输入边的一个顶点" << endl;
    cin >> e.vex1.code;
    cout << "输入另一个顶点" << endl;
    cin >> e.vex2.code;
    cout << "输入权值" << endl;
    cin >> e.weight;
    graph->InsertEdges(e);
   }
   break;
  }
  case 4: {
   graph->PrimMinTree(a);
   system("pause");
   break;
  }
  case 5: {
   graph->KruskalMinTree(a);
   system("pause"); 
   break;
  }
  case 6: {
   cout << "1.修改顶点" << endl;
   cout << "2.删除顶点" << endl;
   cout << "3.修改边" << endl;
   cout << "4.删除边" << endl;
   int m;
   cin >> m;
   if (m == 1) {
    Vex a;
    cout << "输入修改的顶点的编号" << endl;
    cin >> a.code;
    cout << "输入修改的顶点的名称" << endl;
    cin >> a.Name;
    graph->UpdateVex(a);
   }
   else if (m == 2) {
    Vex b;
    cout << "输入修改的顶点的编号" << endl;
    cin >> b.code;
    graph->DeleteVex(b);
   }
   else if (m == 3) {
    Edge c;
    cout << "输入修改边的第一个顶点编号" << endl;
    cin >> c.vex1.code;
    cout << "输入修改边的第二个顶点编号" << endl;
    cin >> c.vex2.code;
    cout << "输入修改边的权值" << endl;
    cin >> c.weight;
    graph->UpdateEdges(c);
   }
   else if (m == 4) {
    Edge d;
    cout << "输入修改边的第一个顶点编号" << endl;
    cin >> d.vex1.code;
    cout << "输入修改边的第二个顶点编号" << endl;
    cin >> d.vex2.code;
    graph->DeleteEdges(d);
   }
   else {
    cout << "输入错误" << endl;
   }
   system("pause");
   break;
  }
  case 7: {
   graph->showMassage();
   system("pause");
   break;
  }
  case 8: {
   return 0;
   break;
  }
  }
 }
}

图的头文件声明Graph.h:

#pragma once
#define numMAX 20
#define StrMAX 100
#define MAX 1000
#include<iostream>
#include<string>
#include"SqList.hpp"
#include<vector>
using namespace std;
//节点结构体
struct Vex {
 string code;
 string Name;
};
//边结构体
struct Edge {
 Vex vex1;
 Vex vex2;
 int weight=-1;
};
class Graph {
private:
 int AdjMatrix[numMAX][numMAX];//邻接矩阵
 SqList<Vex>Vexs;   //点的集合
 SqList<Edge>Edges;   //边的集合
 int VexNum;     //点的个数
 public:
 Graph();
 ~Graph();
 bool InsertVex(Vex svex);    //增加节点
 bool DeleteVex(Vex svex);    //删除节点
 bool UpdateVex(Vex svex);    //更新节点
 bool InsertEdges(Edge sedge);   //增加边
 bool DeleteEdges(Edge sedge);   //删除边
 bool UpdateEdges(Edge sedge);   //更新边
 Edge GetEdge(char* vex1Code, char* vex2Code);//得到边
 Vex GetVex(char*vex1Code);    //得到点
 void SetVexNum(int);     //更新节点数
 int PrimMinTree(Edge aPath[]);   //prim算法实现最小生成树
 int KruskalMinTree(Edge aPath[]);  //kruskal算法实现最小生成树
 void showMassage();      //打印顶点和边的信息
private:
 bool isConnect(Edge b,Edge outEdges[],int n);
};

头文件的实现Graph.cpp

#include"Graph.h"
Graph::Graph(){
 for (int i = 0; i < numMAX; i++) {
  for (int j = 0; j < numMAX; j++) {
   if (i == j)
    this->AdjMatrix[i][j] = 0;
   else
    this->AdjMatrix[i][j] = 10000;
  }
 }
 this->VexNum = 0;
}
Graph::~Graph() {
}

bool Graph::InsertVex(Vex svex) {
 for (int i = 0; i < this->Vexs.GetLength(); i++) {
  Vex a;
  this->Vexs.GetElem(i, a);
  if (a.code == svex.code && a.Name == svex.Name)
   cout << "顶点存在" << endl;
 }
 if (this->VexNum < numMAX) {
  this->Vexs.InsertElem(svex);
  this->VexNum++;
  return 1;
 }
 else {
  cout << "顶点达到最大容量" << endl;
  return 0;
 }
}

bool Graph::DeleteVex(Vex svex) {
 int sign = 0;
 Vex a;
 for (int i = 0; i < this->Vexs.GetLength(); i++) {
  this->Vexs.GetElem(i, a);
  if (a.code._Equal(svex.code)) {
   this->Vexs.DeleteElem(i, a);
   this->VexNum--;
   sign = 1;
   break;
  }
 }
  for (int m = 0; m < this->Edges.GetLength(); m++) {
   Edge e;
   this->Edges.GetElem(m, e);
   if (e.vex1.code._Equal(a.code) | a.code._Equal(e.vex2.code)) {
    Edges.DeleteElem(m, e);
    m--;
    int p = (int)(e.vex1.code[1] - '0');
    int n = (int)(e.vex2.code[1] - '0');
    this->AdjMatrix[p][n] = 1000;
    this->AdjMatrix[n][p] = 1000;
   }
  }
 if (sign == 0)
  return 0;
 else
  return 1;
}

bool Graph::UpdateVex(Vex svex) {
 int sign = 0;
 Vex a;
 for (int i = 0; i < this->Vexs.GetLength(); i++) {
  this->Vexs.GetElem(i, a);
  if (a.code == svex.code) {
   this->Vexs.SetElem(i, svex);
   sign = 1;
   break;
  }
 }
 if (sign == 0)
  return 0;
 else
  return 1;
}

bool Graph::InsertEdges(Edge sedge) {
 int sign = 0;
 Edge a;
 for (int i = 0; i < this->Edges.GetLength(); i++) {
  this->Edges.GetElem(i, a);
  if (a.vex1.code == sedge.vex1.code && a.vex2.code == sedge.vex2.code)
   sign = 1;
  if (a.vex1.code == sedge.vex2.code && a.vex2.code == sedge.vex2.code)
   sign = 1;
 }
 if (sign == 0) {
  this->Edges.InsertElem(sedge);
  int m = (int)(sedge.vex1.code[1] - '0');
  int n = (int)(sedge.vex2.code[1] - '0');
  this->AdjMatrix[m][n] = sedge.weight;
  this->AdjMatrix[n][m] = sedge.weight;
  return 1;
 }
 else {
  cout << "这条边已经存在" << endl;
  return 0;
 }
 }
 bool Graph::DeleteEdges(Edge sedge) {
 int sign = 0;
 Edge a;
 for (int i = 0; i < this->Edges.GetLength(); i++) {
  this->Edges.GetElem(i, a);
  if ((a.vex1.code == sedge.vex1.code && a.vex2.code == sedge.vex2.code)
   || (a.vex1.code == sedge.vex2.code && a.vex2.code == sedge.vex2.code)) {
   Edges.DeleteElem(i, a);
   sign = 1;
  }
 }
 if (sign == 1) {
  int m = (int)(sedge.vex1.code[1] - '0');
  int n = (int)(sedge.vex2.code[1] - '0');
  this->AdjMatrix[m][n] = 1000;
  this->AdjMatrix[n][m] = 1000;
  cout << "删除成功" << endl;
  return 1;
 }
 else {
  cout << "这条边不存在" << endl;
  return 0;
 }
}

bool Graph::UpdateEdges(Edge sedge) {
 int sign = 0;
 Edge a;
 for (int i = 0; i < this->Edges.GetLength(); i++) {
  this->Edges.GetElem(i, a);
  if ((a.vex1.code == sedge.vex1.code && a.vex2.code == sedge.vex2.code)
   || (a.vex1.code == sedge.vex2.code && a.vex2.code == sedge.vex2.code)) {
   Edges.SetElem(i, sedge);
   sign = 1;
  }
 }
 if (sign == 1) {
  cout << "更新成功" << endl;
  return 1;
 }
 else {
  cout << "更新失败" << endl;
  return 0;
 }
}

Edge Graph::GetEdge(char* vex1Code, char* vex2Code) {
 int sign = 0;
 Edge a;
 for (int i = 0; i < this->Edges.GetLength(); i++) {
  this->Edges.GetElem(i, a);
  if ((a.vex1.code[1] ==*vex1Code && a.vex2.code[1] ==*vex2Code)
   || (a.vex1.code[1] == *vex2Code && a.vex2.code[1] == *vex2Code)) {
   Edges.GetElem(i, a);
   sign = 1;
  }
 }
 if (sign == 0) {
  return a;
 }
 else {
  cout << "查找失败" << endl;
  return a;
 }
}

Vex Graph::GetVex(char* vex1Code) {
 int sign = 0;
 Vex a;
 for (int i = 0; i < this->Vexs.GetLength(); i++) {
  this->Vexs.GetElem(i, a);
  if (a.code[1] == *vex1Code) {
   Vexs.GetElem(i, a);
   sign = 1;
  }
 }
 if (sign == 0) {
  return a;
 }
 else {
  cout << "查找失败" << endl;
  return a;
 }
}

void Graph::SetVexNum(int) {
 this->VexNum = Vexs.GetLength();
}
int Graph::PrimMinTree(Edge aPath[]) {
 cout << "prim算法实现最小生成树" << endl;
 //从第一个点出发
 int x = 1;
 //记录他的链接顶点
 int closest[numMAX];
 //记录最短边
 int min;
 //记录链接点上的权值
 int lowcost[numMAX];
 //数组初始化
 for (int i = 1; i <= this->VexNum; i++) {
  lowcost[i] = AdjMatrix[x][i];
  closest[i] = x;
 }
 int i = 1;
 int j;
 int k;
 for (j = 2; j <= this->VexNum; j++) {
  min = 10000;
  for (k = 1; k <= this->VexNum; k++) {
   if ((lowcost[k] < min) && (lowcost[k] != 0)) {
    min = lowcost[k];
    i = k;
   }
  }
  lowcost[i] = 0;
  for (k = 1; k <= this->VexNum; k++) {
   if (lowcost[k] > AdjMatrix[k][i]) {
    lowcost[k] = AdjMatrix[k][i];
    closest[k] = i;
   }
  }
 }
 for (j = 2; j <= this->VexNum; j++) {
   cout << "v"<<j << "-" << "v"<<closest[j] << endl;
 }
 return 0;
}
int Graph::KruskalMinTree(Edge aPath[]) {
 cout << "Kruskal算法实现最小生成树" << endl;
 //取出边
 Edge mEdges[MAX];
 int numEdges = this->Edges.GetLength();
 for (int i = 0; i < numEdges; i++) {
  Edges.GetElem(i, mEdges[i]);
 }
 //把边按从小到大排列
 for (int i = 0; i < numEdges; i++) {
  for (int j = 0; j < numEdges - 1; j++) {
   Edge a;
   if (mEdges[j].weight > mEdges[j + 1].weight) {
    a = mEdges[j];
    mEdges[j] = mEdges[j + 1];
    mEdges[j + 1] = a;
   }
  }
 }
 //定义一个边数组
 Edge outEdges[MAX];
 //记录合格的边
 int outNumber = 0;
 int numberEdges = 0;
 //循环判断合格边并加入
 while (outNumber < this->VexNum-1&&numberEdges<=this->Edges.GetLength()) {
   outEdges[outNumber] = mEdges[numberEdges];
   outNumber++;
  if (isConnect(mEdges[numberEdges], outEdges,outNumber)) {
   outNumber--;
  }
  numberEdges++;
 }
 //达标输出,不达标则不输出
 if (outNumber == this->Vexs.GetLength() - 1) {
  for (int i = 0; i < outNumber; i++) {
   cout<<outEdges[i].vex1.code << "-" << outEdges[i].vex2.code << "权值:" << outEdges[i].weight << endl;
  }
 }
 else {
  cout << "这些边构不成一颗最小生成树" << endl;
 }
 return 0;
}
bool Graph::isConnect(Edge b, Edge outEdges[], int n) {
 typedef struct d {
  Vex a;
  int num=0;
 }D;
 D d[MAX];
 int sumD = 0;
 //统计顶点和度
 for (int i = 0; i < n; i++) {
  int sign = 0;
  int sign2 = 0;
  for (int j = 0; j < sumD; j++) {
   if (d[j].a.code == outEdges[i].vex1.code) {
    d[j].num++;
    sign = 1;
   }
   if (d[j].a.code == outEdges[i].vex2.code) {
    d[j].num++;
    sign2 = 1;
   }
  }
  if (sign == 0) {
   d[sumD].a.code = outEdges[i].vex1.code;
   d[sumD].a.Name = outEdges[i].vex1.Name;
   d[sumD].num++;
   sumD++;
  }
  if (sign2 == 0) {
   d[sumD].a.code = outEdges[i].vex2.code;
   d[sumD].a.Name = outEdges[i].vex2.Name;
   d[sumD].num++;
   sumD++;
  }
 }
 
 //利用拓扑排序判断是否有环路
 while (1) {
  //判断是否结束循环
  int sign = 0;
  for (int i = 0; i < sumD; i++) {
   if (d[i].num == 1)
   sign = 1; 
  }
  if (sign == 0) {
   if (sumD == 0||sumD==1)
    return 0;
   else
    return 1;
  }
  else {
   for (int j = 0; j < sumD; j++) {
    if (d[j].num == 1) {
     for (int m = 0; m < n; m++) {
      if (outEdges[m].vex1.code == d[j].a.code) {
       for (int p = 0; p < sumD; p++) {
        if (d[p].a.code == outEdges[m].vex2.code)
         d[p].num--;
       }
      }
      if (outEdges[m].vex2.code == d[j].a.code) {
       for (int p = 0; p < sumD; p++) {
        if (d[p].a.code == outEdges[m].vex1.code)
         d[p].num--;
       }
      }
     }
     for (int p = j; p < sumD-1; p++) {
      d[p] = d[p + 1];
     }
     sumD--;
    }
   }
   //去掉度为0的顶点
   for (int q = 0; q < sumD; q++) {
    if (d[q].num == 0) {
     for (int k = q; k < sumD - 1; k++) {
      d[k] = d[k + 1];
     }
     sumD--;
    }
   }
  }
 }
}
void Graph::showMassage() {
 cout << "顶点信息:" << endl;
 for (int i = 0; i < this->Vexs.GetLength(); i++) {
  Vex a;
  this->Vexs.GetElem(i, a);
  cout << a.code << "--" << a.Name << endl;
 }
 cout << "边信息:" << endl;
 for (int j = 0; j < this->Edges.GetLength(); j++) {
  Edge b;
  this->Edges.GetElem(j, b);
  cout << b.vex1.code << "--" << b.vex2.code << "权值:" << b.weight << endl;
 }
}

栈的实现SqList.hpp

#pragma once
#ifndef __SQ_LIST_H__
#endif
#define __SQ_LIST_H__
// ANSI C++标准库头文件
#include <cstring>     // 标准串操作
#include <iostream>     // 标准流操作
using namespace std;
// 宏定义
#define DEFAULT_SIZE 1000   // 缺省元素个数
#define DEFAULT_INFINITY 1000000 // 缺省无穷大
// 顺序表模板类的申明 
template <class ElemType>
class SqList
{
protected:
 // 顺序表的数据成员
 int length;     // 顺序表的当前长度 
 int maxLength;    // 顺序表的最大容量
 ElemType* data;   // 元素存储空间的首地址 
public:
 // 顺序表的函数成员
 SqList(int size = DEFAULT_SIZE); // 构造一个空表 
 virtual ~SqList();   // 析构函数
 int GetLength() const;  // 取顺序表长度    
 int GetElem(int i, ElemType& e) const; // 取顺序表中第i个元素的值 
 int SetElem(int i, const ElemType& e); // 修改顺序表中第i个元素的值
 int DeleteElem(int i, ElemType& e);      // 删除顺序表中第i个元素  
 int InsertElem(const ElemType& e);        // 在顺序表表尾插入元素
};
// 构造一个空表
template<class ElemType>
SqList<ElemType>::SqList(int size) {
  this->length = 0;
  this->maxLength = size;
  data = new ElemType[DEFAULT_SIZE];
 }
 // 析构函数
template<class ElemType>
SqList<ElemType>::~SqList() {
}
// 取顺序表长度 
template<class ElemType>
int SqList<ElemType>::GetLength() const {
  return this->length;
}
// 取顺序表中第i个元素的值
template<class ElemType>
int SqList<ElemType>::GetElem(int i, ElemType& e) const {
  if ((i<this->length)&&i>=0)
   e = data[i];
  else
   cout << "没有找到" << endl;
  return 0;
 }
// 修改顺序表中第i个元素的值
template<class ElemType>
int SqList<ElemType>::SetElem(int i, const ElemType& e) {
  if ((i  < this->length) && i >= 0)
   this->data[i] = e;
  else
   cout << "没有找到" << endl;
  return 0;
}
// 删除顺序表中第i个元素  
template<class ElemType>
int SqList<ElemType>::DeleteElem(int i, ElemType& e) {
  e = this->data[i];
  if ((i < this->length) && i >= 0) {
   for (int j = i; j < this->length - 1; j++)
    this->data[j] = this->data[j + 1];
   this->length--;
  }
  else
   cout << "没有找到" << endl;
  return 0;
 }
// 在顺序表表尾插入元素
template<class ElemType>
int SqList<ElemType>::InsertElem(const ElemType& e) {
  this->data[this->length] = e;
  this->length++;
  return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值