当前位置:   article > 正文

【邻接表】75 邻接表:删除边_基于邻接表边的删除

基于邻接表边的删除

问题描述 :

目的:使用C++模板设计并逐步完善图的邻接表抽象数据类型(ADT)。

内容:(1)请参照图的邻接矩阵模板类原型,设计并逐步完善图的邻接表ADT。(由于该环境目前仅支持单文件的编译,故将所有内容都集中在一个源文件内。在实际的设计中,推荐将抽象类及对应的派生类分别放在单独的头文件中。)

(2)设计并实现一个算法,在已存在的图中删除边边。删除成功,返回true;否则返回false。图的存储结构采用邻接表。将其加入到ADT中。

 

注意:DG(有向图), DN(有向网), UDG(无向图), UDN(无向网)

 

参考函数原型:

//删除边 (外壳:有向(删除1条边), 无向(删除2条边),公有成员函数) 

template<class TypeOfVer, class TypeOfEdge>

bool adjlist_graph<TypeOfVer, TypeOfEdge>::DeleteEdge( int u, int v );

 

//删除单条边(私有成员函数)

template<class TypeOfVer, class TypeOfEdge>

bool adjlist_graph<TypeOfVer, TypeOfEdge>::Delete_Edge( int u, int v );

 

图的邻接表模板类原型参考如下:

 

/* 边表的结点定义 */

 

template<class TypeOfEdge>

struct edgeNode

{

    int data;

    TypeOfEdge weight;

    edgeNode<TypeOfEdge> *next;

    edgeNode(const int &d, edgeNode<TypeOfEdge> *ptr = NULL) //构造函数,用于构造其他结点(无权图) 

    //函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面

    {

        next = ptr;

        data = d;

    }

    edgeNode(const int &d, const TypeOfEdge &w, edgeNode<TypeOfEdge> *ptr = NULL) //构造函数,用于构造其他结点(带权图) 

    //函数参数表中的形参允许有默认值,但是带默认值的参数需要放后面

    {

        next = ptr;

        data = d;

        weight = w;

    }

    int getData(){ return data;}  //取得结点的序号(顶点集) 

    TypeOfEdge getWeight(){ return weight;}  //取得边集中对应边的权值 

    void SetLink( edgeNode<TypeOfEdge> *link ){ next = link; }  //修改结点的next域 

    void SetData( int value ){ data = value; }   //修改结点的序号(顶点集) 

    void SetWeight(TypeOfEdge value ){ weight = value; }   //修改边集中对应边的权值   

};

 

//图的邻接表类

template<class TypeOfVer, class TypeOfEdge>

struct verNode

{

    TypeOfVer ver;

    edgeNode<TypeOfEdge> *head;

    

    verNode(edgeNode<TypeOfEdge> *h = NULL){head = h;} 

    TypeOfVer getVer(){ return ver;}  //取得结点值(顶点集) 

    edgeNode<TypeOfEdge> getHead(){ return head;}  //取得对应的边表的头指针 

    void setVer(TypeOfVer value){ ver = value;}  //设置结点值(顶点集) 

    void setHead(edgeNode<TypeOfEdge> value){ head = value;}  //设置对应的边表的头指针

 

};

 

template <class TypeOfVer, class TypeOfEdge>

class adjlist_graph{

    private:

       int Vers;           //顶点数 

       int Edges;          //边数 

       verNode<TypeOfVer,TypeOfEdge> *verList;

       

       string GraphKind;     //图的种类标志 

       

       bool Delete_Edge( int u, int v ); 

       bool DFS(int u, int &num, int visited[]); //DFS遍历(递归部分)

 

    public:

       adjlist_graph( const string &kd, int vSize, const TypeOfVer d[]); //构造函数构造一个只有结点没有边的图。 

       adjlist_graph( const string &kd, int vSize, int eSize, const TypeOfVer d[], int **e); 构造函数构造一个无权图。5个参数的含义:图的类型、结点数、边数、结点集和边集 

       adjlist_graph( const string &kd, int vSize, int eSize, const TypeOfVer d[], int **e, const TypeOfEdge w[]); //构造函数构造一个有权图。

       bool GraphisEmpty() { return Vers == 0; }  //判断图空否

       string GetGraphKind(){ return GraphKind; }

       bool GetVer(int u, TypeOfVer &data); //取得G中指定顶点的值 

       int GetFirstAdjVex(int u, int &v); //返回G中指定顶点u的第一个邻接顶点的位序(顶点集)。若顶点在G中没有邻接顶点,则返回-1

       int GetNextAdjVex(int u, int v, int &w); //返回G中指定顶点u的下一个邻接顶点(相对于v)的位序(顶点集)。若顶点在G中没有邻接顶点,则返回false

       bool PutVer(int u, TypeOfVer data); //对G中指定顶点赋值 

       bool InsertVer(const TypeOfVer &data); //往G中添加一个顶点 

       int LocateVer(TypeOfVer data); //返回G中指定顶点的位置 

       bool ExistEdge(int u, int v);

       bool PrintVer();  //输出顶点集 

       bool PrintAdjList();  //输出邻接矩阵 

       int GetVerNum(){ return Vers;}    //取得当前顶点数 

       int GetEdgeNum(){ return Edges;}  //取得当前边数 

       bool Insert_Edge(int u, int v); //无权图插入一条边

       bool Insert_Edge(int u, int v, TypeOfEdge w); //有权图插入一条边

       bool DeleteVer(const TypeOfVer &data); //往G中删除一个顶点 

       bool DeleteEdge( int u, int v ); //删除边 (外壳:有向(删除1条边), 无向(删除2条边))

       void DFS_Traverse(int u); //DFS遍历(外壳部分)

       void BFS_Traverse(int u); //BFS遍历

       ~adjlist_graph(); //析构函数 

};

 

输入说明 :

建图的输入数据格式参见建图的算法说明。(以无权图为例,有权图类似)

 

第一行:图的类型

第二行:结点数

第三行:结点集

第四行:边数

第五行:边集

第六行:邻接顶点1

第七行:邻接顶点2

 

输出说明 :

第一行:顶点集

第二行:删除边前的边数

第三行:删除边前的邻接表

空行

第四行:true(false)

第五行:删除边后的边数

第六行:删除边后的邻接表

 

输入范例 :

UDG
6
A B C D E F
6
0 1
0 2
1 3
2 3
3 4
3 5

1

输出范例 :

A B C D E F
6
A->2->1
B->3->0
C->3->0
D->5->4->2->1
E->3
F->3

true
A B C D E F
5
A->2
B->3
C->3->0
D->5->4->2->1
E->3
F->3

解题代码:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <algorithm>
  5. #include <cmath>
  6. #include <cstring>
  7. #include <string>
  8. #include <vector>
  9. #include <queue>
  10. #include <sstream>
  11. #include <stack>
  12. #include <map>
  13. #include <ctime>
  14. #include <array>
  15. #include <set>
  16. #include <list>
  17. using namespace std;
  18. //边的定义
  19. template<class TypeOfEdge>
  20. struct Edge_pair
  21. {
  22. int point = 0;
  23. TypeOfEdge length = 0;
  24. //=================
  25. };
  26. //顶点的定义
  27. template<class TypeOfVer, class TypeOfEdge>
  28. struct verNode
  29. {
  30. TypeOfVer ver_data;
  31. list<Edge_pair<TypeOfEdge> > group;
  32. //构造函数,默认会讲头指针设为空.
  33. verNode()
  34. {
  35. group.clear();
  36. ver_data = 0;
  37. }
  38. //取得结点值(顶点) 估计是为了安全吧???
  39. TypeOfVer getVer()
  40. {
  41. return ver_data;
  42. }
  43. //取得对应的边表
  44. list<Edge_pair<TypeOfEdge> > getHead()
  45. {
  46. return group;
  47. }
  48. //设置结点值(顶点集) 估计是为了安全吧???
  49. void setdata(TypeOfVer value)
  50. {
  51. ver_data = value;
  52. return;
  53. }
  54. //=====================================================
  55. void creat_Point(int new_point, TypeOfEdge new_length)
  56. {
  57. Edge_pair<TypeOfEdge> Next_p;
  58. Next_p.point = new_point;
  59. Next_p.length = new_length;
  60. group.insert(group.begin(), Next_p);
  61. return;
  62. }
  63. //删除指定位置顶点
  64. void del_Point(int n)
  65. {
  66. return;
  67. }
  68. };
  69. template <class TypeOfVer, class TypeOfEdge>//顶点元素类型,边权值类型
  70. class adjlist_graph {
  71. private:
  72. int Vers;//顶点数
  73. int Edges;//边数
  74. vector<verNode<TypeOfVer, TypeOfEdge> >ver;//顶点存储
  75. string GraphKind;//图的种类标志
  76. bool have_dir = false, have_w = false;//图类型参数
  77. //======================================================================
  78. bool Delete_Edge(int u, int v)//删除一条边
  79. {
  80. return false;
  81. }
  82. bool DFS(int u, int& num, int visited[])//DFS遍历(递归部分)
  83. {
  84. return false;
  85. }
  86. public:
  87. //一个空的构造函数
  88. adjlist_graph()
  89. {
  90. Edges = 0;
  91. Vers = 0;
  92. }
  93. //假的析构函数
  94. ~adjlist_graph()
  95. {
  96. ;//你电脑内存就640K吗?
  97. }
  98. //判断图空否
  99. bool GraphisEmpty()
  100. {
  101. return Vers == 0;
  102. }
  103. //获取图的类型
  104. string GetGraphKind()
  105. {
  106. return GraphKind;
  107. }
  108. //取得当前顶点数
  109. int GetVerNum()
  110. {
  111. return Vers;
  112. }
  113. //取得当前边数
  114. int GetEdgeNum()
  115. {
  116. return Edges;
  117. }
  118. //自动建立临接表
  119. bool Auto_build(void)
  120. {
  121. //DG(有向图), DN(有向网), UDG(无向图), UDN(无向网)
  122. /*第一行:图的类型 DN UDN
  123. 第二行:结点数
  124. 第三行:结点集
  125. 第四行:无边标记
  126. 第五行:边数
  127. 第六行:边集
  128. 第七行:权集*/
  129. /*第一行:图的类型 DG UDG
  130. 第二行:结点数
  131. 第三行:结点集
  132. 第四行:边数
  133. 第五行:边集*/
  134. cin >> GraphKind;//图的类型
  135. cin >> Vers;//结点数
  136. ver.resize(Vers);//开辟节点空间
  137. for (int i = 0; i < Vers; i++)//结点集
  138. {
  139. TypeOfVer now;
  140. cin >> now;
  141. ver[i].setdata(now);
  142. }
  143. cin >> Edges;//边数
  144. vector<int> x_p, y_p, w_p;
  145. for (int i = 0; i < Edges; i++)
  146. {
  147. int c_x, c_y;
  148. cin >> c_x >> c_y;
  149. x_p.push_back(c_x);
  150. y_p.push_back(c_y);
  151. }
  152. //图的类型识别
  153. if (GraphKind == "DG")//DG(有向图)
  154. have_dir = true, have_w = false;
  155. if (GraphKind == "DN")//DN(有向网)
  156. have_dir = true, have_w = true;
  157. if (GraphKind == "UDG")//UDG(无向图)
  158. have_dir = false, have_w = false;
  159. if (GraphKind == "UDN")//UDN(无向网)
  160. have_dir = false, have_w = true;
  161. if (have_w)
  162. for (int i = 0; i < Edges; i++)
  163. {
  164. int c_w;
  165. cin >> c_w;
  166. w_p.push_back(c_w);
  167. }
  168. for (int i = 0; i < Edges; i++)
  169. {
  170. if (have_dir)
  171. if (have_w)
  172. ver[x_p[i]].creat_Point(y_p[i], w_p[i]);
  173. else
  174. ver[x_p[i]].creat_Point(y_p[i], 0);
  175. else
  176. if (have_w)
  177. ver[x_p[i]].creat_Point(y_p[i], w_p[i]), ver[y_p[i]].creat_Point(x_p[i], w_p[i]);
  178. else
  179. ver[x_p[i]].creat_Point(y_p[i], 0), ver[y_p[i]].creat_Point(x_p[i], 0);
  180. }
  181. return 1;
  182. }
  183. //取得G顶点的组
  184. vector<TypeOfVer> GetVer(void)
  185. {
  186. vector<TypeOfVer> head_group;
  187. for (int i = 0; i < Vers; i++)
  188. {
  189. head_group.push_back(ver[i].getVer());
  190. }
  191. return head_group;
  192. }
  193. //输出邻接表
  194. bool Print_photo()
  195. {
  196. int i;
  197. for (i = 0; i < Vers; i++)
  198. {
  199. cout << ver[i].getVer();
  200. if (ver[i].group.size() != 0)
  201. cout << "->";
  202. else
  203. {
  204. cout << endl;
  205. continue;
  206. }
  207. vector<Edge_pair<TypeOfEdge> > out_lis;
  208. out_lis.clear();
  209. for (auto j = ver[i].group.begin(); j != ver[i].group.end(); j++)
  210. {
  211. out_lis.push_back(*j);
  212. }
  213. int j;
  214. for (j = 0; j < out_lis.size() - 1; j++)
  215. if (have_w)
  216. cout << out_lis[j].point << "(" << out_lis[j].length << ")" << "->";
  217. else
  218. cout << out_lis[j].point << "->";
  219. if (have_w)
  220. cout << out_lis[j].point << "(" << out_lis[j].length << ")" << endl;
  221. else
  222. cout << out_lis[j].point << endl;
  223. }
  224. return 1;
  225. }
  226. //往G中添加一个顶点
  227. bool InsertVer(const TypeOfVer& data)
  228. {
  229. verNode<TypeOfVer, TypeOfEdge> new_e;
  230. new_e.setdata(data);
  231. ver.push_back(new_e);
  232. Vers++;
  233. return true;
  234. }
  235. //寻找顶点位置
  236. int Look_Ver(const TypeOfVer& data)
  237. {
  238. int i;
  239. for (i = 0; i < Vers; i++)
  240. if (ver[i].ver_data == data)
  241. return i;
  242. return -1;
  243. }
  244. //删除一个顶点
  245. bool del_Point(int place)
  246. {
  247. int need_del = 0;
  248. if (!(0 <= place && place < Vers))
  249. return false;
  250. int i;
  251. for (i = 0; i < Vers; i++)
  252. {
  253. for (auto j = ver[i].group.begin(); j != ver[i].group.end(); j++)
  254. {
  255. if (j->point == place)
  256. {
  257. need_del++;
  258. ver[i].group.erase(j);
  259. break;
  260. }
  261. }
  262. for (auto j = ver[i].group.begin(); j != ver[i].group.end(); j++)
  263. {
  264. if (j->point > place)
  265. j->point--;
  266. }
  267. }
  268. need_del += ver[place].group.size();
  269. ver.erase(ver.begin() + place);
  270. Vers--;
  271. if (have_dir)
  272. Edges -= need_del;
  273. else
  274. Edges -= (need_del / 2);
  275. return true;
  276. }
  277. //无权图插入一条边
  278. bool Insert_Edge(int u, int v)
  279. {
  280. if (!(0 <= u && u < Vers))
  281. return false;
  282. if (!(0 <= v && v < Vers))
  283. return false;
  284. for (auto i = ver[u].group.begin(); i != ver[u].group.end(); i++)
  285. {
  286. if (i->point == v)
  287. return false;
  288. }
  289. for (auto i = ver[v].group.begin(); i != ver[v].group.end(); i++)
  290. {
  291. if (i->point == u)
  292. return false;
  293. }
  294. if (u == v)
  295. return false;
  296. if (have_dir)
  297. {
  298. Edges++;
  299. ver[u].creat_Point(v, 1);
  300. return true;
  301. }
  302. else
  303. {
  304. Edges++;
  305. ver[u].creat_Point(v, 1);
  306. ver[v].creat_Point(u, 1);
  307. return true;
  308. }
  309. return true;
  310. }
  311. //有权图插入一条边
  312. bool Insert_Edge(int u, int v, TypeOfEdge w)
  313. {
  314. if (!(0 <= u && u < Vers))
  315. return false;
  316. if (!(0 <= v && v < Vers))
  317. return false;
  318. for (auto i = ver[u].group.begin(); i != ver[u].group.end(); i++)
  319. {
  320. if (i->point == v)
  321. return false;
  322. }
  323. for (auto i = ver[v].group.begin(); i != ver[v].group.end(); i++)
  324. {
  325. if (i->point == u)
  326. return false;
  327. }
  328. if (u == v)
  329. return false;
  330. if (have_dir)
  331. {
  332. Edges++;
  333. ver[u].creat_Point(v, w);
  334. return true;
  335. }
  336. else
  337. {
  338. Edges++;
  339. ver[u].creat_Point(v, w);
  340. ver[v].creat_Point(u, w);
  341. return true;
  342. }
  343. return true;
  344. }
  345. //删除边 (外壳:有向(删除1条边), 无向(删除2条边))
  346. bool del_Edge(int u, int v)
  347. {
  348. if (!(0 <= u && u < Vers))
  349. return false;
  350. if (!(0 <= v && v < Vers))
  351. return false;
  352. if (u == v)
  353. return false;
  354. bool ok = true;
  355. if(have_dir)
  356. for (auto i = ver[u].group.begin(); i != ver[u].group.end(); i++)
  357. {
  358. if (i->point == v)
  359. {
  360. ver[u].group.erase(i);
  361. Edges--;
  362. return true;
  363. }
  364. }
  365. else
  366. {
  367. for (auto i = ver[u].group.begin(); i != ver[u].group.end(); i++)
  368. {
  369. if (i->point == v)
  370. {
  371. ver[u].group.erase(i);
  372. break;
  373. }
  374. }
  375. for (auto i = ver[v].group.begin(); i != ver[v].group.end(); i++)
  376. {
  377. if (i->point == u)
  378. {
  379. ver[v].group.erase(i);
  380. Edges--;
  381. return true;
  382. }
  383. }
  384. }
  385. return false;
  386. }
  387. /*+++++++++++====分割线====++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
  388. //返回G中指定顶点u的第一个邻接顶点的位序(顶点集)。若顶点在G中没有邻接顶点,则返回-1
  389. int GetFirstAdjVex(int u, int& v)
  390. {
  391. return 0;
  392. }
  393. //返回G中指定顶点u的下一个邻接顶点(相对于v)的位序(顶点集)。若顶点在G中没有邻接顶点,则返回false
  394. int GetNextAdjVex(int u, int v, int& w)
  395. {
  396. return 0;
  397. }
  398. //对G中指定顶点赋值
  399. bool PutVer(int u, TypeOfVer data)
  400. {
  401. return false;
  402. }
  403. //返回G中指定顶点的位置
  404. int LocateVer(TypeOfVer data)
  405. {
  406. return -1;
  407. }
  408. //存在边
  409. bool ExistEdge(int u, int v)
  410. {
  411. return 0;
  412. }
  413. //DFS遍历(外壳部分)
  414. void DFS_Traverse(int u)
  415. {
  416. return;
  417. }
  418. //BFS遍历
  419. void BFS_Traverse(int u)
  420. {
  421. return;
  422. }
  423. };
  424. int main()
  425. {
  426. int i;
  427. adjlist_graph<char, int> a;
  428. a.Auto_build();
  429. int u, v, w;
  430. cin >> u >> v;
  431. //cout << a.GetGraphKind() << endl;
  432. vector <char> ans;
  433. ans = a.GetVer();
  434. for (i = 0; i < ans.size() - 1; i++)
  435. cout << ans[i] << " ";
  436. cout << ans[i] << endl;
  437. //cout << a.GetVerNum() << endl;
  438. cout << a.GetEdgeNum() << endl;
  439. a.Print_photo();
  440. cout << endl;
  441. if (a.del_Edge(u, v))
  442. cout << "true" << endl;
  443. else
  444. cout << "false" << endl;
  445. ans = a.GetVer();
  446. for (i = 0; i < ans.size() - 1; i++)
  447. cout << ans[i] << " ";
  448. cout << ans[i] << endl;
  449. //cout << a.GetVerNum() << endl;
  450. cout << a.GetEdgeNum() << endl;
  451. a.Print_photo();
  452. return 0;
  453. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/天景科技苑/article/detail/934845
推荐阅读
相关标签
  

闽ICP备14008679号