• 3 Prim算法的设计--来源舒姐


    abyssfall的博客_CSDN博客-计科学子的头发账本,代码存档领域博主

    作者: 冯向阳时间限制: 1S章节: 课程设计

    问题描述 :

    在使用图的邻接矩阵ADT的基础上,设计能指定起始结点u的Prim算法,用以求无向网的最小生成树,并以文本形式输出生成树中各条边以及它们的权值。将此算法加入到邻接矩阵ADT中,在邻接矩阵ADT中提供一个公有的成员函数Prim(u, adjvex, lowcost)。

    提示:

    (1)Prim算法的基本思想是从结点的角度出发。初始时,生成树中一个结点也没有,然后将一个个结点加入生成树,直到所有的结点都被加入,生成树就形成了。具体来讲,Prim算法由以下几个步骤组成:

    1)初始时,生成树的结点集U为空;

    2)随意选择一个结点,加入结点集V,然后重复下列工作,直到U=V;

    3)把(u,v)加入生成树的边集,v加入到U。

    (2)在Prim算法的执行过程中,需要保存哪些结点在U中,哪些结点不在U中的信息。这可以用一个布尔型的一维数组flag来保存。如果结点i已在生成树中,则flag[i]的值为true,否则为false。

    (3)在Prim算法的执行过程中,还需要保存U中的结点到V-U中结点的权值最小的边,这可以用2个一维数组lowcost和adjvex来记录。lowcost[i]表示U中的结点到结点i的所有边中的最小权值。adjvex[i]表示从U中的哪一个结点出发到结点i的权值是最小的。

    参考函数原型:

    template

    bool adjmatrix_graph::Prim(int u, int adjvex[], TypeOfEdge lowcost[]);

    输入说明 :

    第一行:图的类型

    第二行:结点数

    第三行:结点集

    第四行:无边标记

    第五行:边数

    第六行:边集

    第七行:权集

    第八行:起始结点序号u

    输出说明 :

    第一行:图的类型

    第二行:顶点集

         空行

    第三行:邻接矩阵(列与列之间用格式控制符'\t'分隔)

    第四行:各条边以及它们的权值,输出格式为:

    (c,b,5),(d,c,3),(e,d,8),(a,e,14),(d,f,21),(e,g,16)

    其中,每个括号内的信息为一条边,格式为(邻接点, 自己, 权值),边的输出顺序为按照(自己这个)点的编号顺序输出。“自己这个”不包括起始点,比如范例中输出的边不包括起始点a,也就是没有(*,a,*)。

    UDN
    7
    a b c d e f g
    9999
    11
    0 1
    0 4
    0 6
    1 2
    1 3
    1 4
    2 3
    3 4
    3 5
    4 6
    5 6
    19 14 18 5 7 12 3 8 21 16 27
    0

    UDN
    a b c d e f g

    9999    19    9999    9999    14    9999    18    
    19    9999    5    7    12    9999    9999    
    9999    5    9999    3    9999    9999    9999    
    9999    7    3    9999    8    21    9999    
    14    12    9999    8    9999    9999    16    
    9999    9999    9999    21    9999    9999    27    
    18    9999    9999    9999    16    27    9999    
    (c,b,5),(d,c,3),(e,d,8),(a,e,14),(d,f,21),(e,g,16)

    1. #include
    2. using namespace std;
    3. const int MAX = 1000;
    4. string kind;
    5. int m = 0;
    6. int arr[MAX][2] = {0}; //输入权集的对应横纵坐标
    7. int none, u; //无边标记
    8. int all[MAX][MAX] = {0};
    9. bool tree_flag[MAX][MAX] = {false};
    10. struct E //边
    11. {
    12. int num;
    13. int weight;
    14. E *next = NULL;
    15. };
    16. struct V //结点
    17. {
    18. string data;
    19. E *next = NULL;
    20. };
    21. struct graph
    22. {
    23. V m[MAX];
    24. int number_of_V;
    25. int number_of_E;
    26. };
    27. void addweight_no_direction(graph &g);
    28. void addweight(graph &g);
    29. void creat_no_directioin(graph &g)
    30. {
    31. int v, f;
    32. cin >> v;
    33. g.number_of_V = v;
    34. for (int i = 0; i < v; i++)
    35. {
    36. cin >> g.m[i].data;
    37. }
    38. //输入顶点字母
    39. cin >> none; //输入无边标记
    40. cin >> f;
    41. g.number_of_E = f;
    42. for (int i = 0; i < f; i++)
    43. {
    44. int v1, v2;
    45. cin >> v1 >> v2;
    46. arr[i][0] = v1;
    47. arr[i][1] = v2;
    48. E *p1 = new E;
    49. p1->num = v2;
    50. p1->next = g.m[v1].next;
    51. g.m[v1].next = p1;
    52. E *p2 = new E;
    53. p2->num = v1;
    54. p2->next = g.m[v2].next;
    55. g.m[v2].next = p2;
    56. }
    57. addweight_no_direction(g);
    58. }
    59. void addweight_no_direction(graph &g)
    60. {
    61. for (int j = 0; j < g.number_of_E; j++)
    62. {
    63. int temp = 0;
    64. cin >> temp;
    65. int number1 = arr[j][0];
    66. int number2 = arr[j][1];
    67. all[number1][number2] = temp;
    68. all[number2][number1] = temp;
    69. E *p;
    70. E *p1;
    71. p = g.m[number1].next;
    72. p1 = g.m[number2].next;
    73. while (p)
    74. {
    75. if (p->num == number2)
    76. {
    77. p->weight = temp;
    78. }
    79. p = p->next;
    80. }
    81. while (p1)
    82. {
    83. if (p1->num == number1)
    84. {
    85. p1->weight = temp;
    86. }
    87. p1 = p1->next;
    88. }
    89. }
    90. }
    91. void creat_direction(graph &g)
    92. {
    93. int v;
    94. int f;
    95. cin >> v;
    96. g.number_of_V = v;
    97. for (int i = 0; i < v; i++)
    98. {
    99. cin >> g.m[i].data;
    100. } //输入顶点字母
    101. cin >> none; //输入无边标记
    102. cin >> f;
    103. g.number_of_E = f;
    104. for (int i = 0; i < f; i++)
    105. {
    106. int v1, v2;
    107. cin >> v1 >> v2;
    108. arr[i][0] = v1;
    109. arr[i][1] = v2;
    110. E *p1 = new E;
    111. p1->num = v2;
    112. p1->next = g.m[v1].next;
    113. g.m[v1].next = p1;
    114. }
    115. addweight(g);
    116. }
    117. void addweight(graph &g)
    118. {
    119. for (int j = 0; j < g.number_of_E; j++)
    120. {
    121. int temp = 0;
    122. cin >> temp;
    123. int number1 = arr[j][0];
    124. int number2 = arr[j][1];
    125. all[number1][number2] = temp;
    126. E *p;
    127. p = g.m[number1].next;
    128. while (p)
    129. {
    130. if (p->num == number2)
    131. {
    132. p->weight = temp;
    133. }
    134. p = p->next;
    135. }
    136. }
    137. }
    138. void printV(graph g)
    139. {
    140. int m = 0;
    141. for (int h = 0; h < g.number_of_V; h++)
    142. {
    143. if (m == 1)
    144. {
    145. cout << " ";
    146. }
    147. m = 1;
    148. cout << g.m[h].data;
    149. }
    150. cout << endl
    151. << endl;
    152. }
    153. void printgraph(graph g)
    154. {
    155. for (int i = 0; i < g.number_of_V; i++)
    156. {
    157. for (int j = 0; j < g.number_of_V; j++)
    158. {
    159. if (all[i][j] == 0)
    160. {
    161. cout << none;
    162. }
    163. else
    164. {
    165. cout << all[i][j];
    166. }
    167. cout << '\t';
    168. }
    169. cout << endl;
    170. }
    171. }
    172. void print_tree(graph g)
    173. {
    174. bool f = false;
    175. for (int i = 0; i < g.number_of_V; i++)
    176. {
    177. if (i == u)
    178. {
    179. continue; //根节点不输出
    180. }
    181. for (int j = 0; j < g.number_of_V; j++)
    182. {
    183. if (tree_flag[i][j] == true)
    184. {
    185. if(f == true)
    186. {
    187. cout<<",";
    188. }
    189. else
    190. {
    191. f = true;
    192. }
    193. cout << "(" << g.m[j].data << "," << g.m[i].data << "," << all[i][j] << ")";
    194. }
    195. }
    196. }
    197. }
    198. int find(graph g, string data)
    199. {
    200. for (int i = 0; i < g.number_of_V; i++)
    201. {
    202. if (g.m[i].data == data)
    203. {
    204. return i;
    205. }
    206. }
    207. return -1;
    208. }
    209. void prim(graph g, int u)
    210. //核心思路:划分已添加和未添加两部分,
    211. {
    212. bool flag_judge[g.number_of_V] = {false};
    213. //标记已添加至二叉树的结点,每个点都要被添加且仅添加一次,以true的结点遍历寻找指向false结点的最小边
    214. //int flag_num[g.number_of_V] = {0};
    215. //标记已添加结点的已连接边,一旦到2,不再加边;结束后为0,视为叶子结点
    216. int now_node = 1; //记录一下循环结束条件
    217. vector now_tree;
    218. now_tree.push_back(g.m[u]);
    219. flag_judge[u] = true; //从这里开始
    220. while (now_node < g.number_of_V) //还有节点没有被加入二叉树
    221. {
    222. int start_node = -1, min_node = -1, min_value = none;
    223. for (int i = 0; i < now_node; i++)
    224. {
    225. //注意一下这里 是不是把nowtree的编号和g的编号弄混了
    226. //if (flag_num[find(g, now_tree[i].data)] == 2)
    227. //{
    228. // continue;
    229. //} //这个结点已经到达构建二叉树的上限了
    230. //最小生成树不用限死在二叉树啊!!!!!!!!!啊!!!!!!!
    231. E *p = now_tree[i].next;
    232. while (p != NULL)
    233. {
    234. if (p->weight < min_value && flag_judge[p->num] == false) //比现在的边小,且终点未被加入
    235. {
    236. min_value = p->weight;
    237. min_node = p->num;
    238. start_node = i;
    239. }
    240. p = p->next;
    241. }
    242. } //找出指向未加入结点的最小边
    243. start_node = find(g, now_tree[start_node].data);
    244. flag_judge[min_node] = true;
    245. //flag_num[start_node]++;
    246. tree_flag[min_node][start_node] = true;
    247. //标记该条边和该点入选
    248. now_tree.push_back(g.m[min_node]);
    249. now_node++;
    250. }
    251. }
    252. int main()
    253. {
    254. cin >> kind;
    255. if (kind == "DN")
    256. {
    257. cout << "DN" << endl;
    258. graph g;
    259. creat_direction(g);
    260. printV(g);
    261. printgraph(g);
    262. cin >> u;
    263. prim(g, u);
    264. print_tree(g);
    265. }
    266. else if (kind == "UDN")
    267. {
    268. cout << "UDN" << endl;
    269. graph g;
    270. creat_no_directioin(g);
    271. printV(g);
    272. printgraph(g);
    273. cin >> u;
    274. prim(g, u);
    275. print_tree(g);
    276. }
    277. getchar();
    278. getchar();
    279. return 0;
    280. }

  • 相关阅读:
    360度无死角刨析C++STL中list的使用和实现,list与vector的对比
    java进阶编程思想(七天)
    nProgress的简单使用
    filter与coalesce的配合使用_尚硅谷大数据培训
    触控笔有必要买吗?便宜好用的手写笔推荐
    科技云报道:云巨头的中场战事:PaaS、SaaS成为关键破局点?
    java计算机毕业设计风情旅游网站MyBatis+系统+LW文档+源码+调试部署
    sqlserver==索引解析,执行计划,索引大小
    每日一练——有效的括号
    Redis分布式锁及其常见问题解决方案
  • 原文地址:https://blog.csdn.net/Ultravioletrays/article/details/126799719