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
输入说明 :
第一行:图的类型
第二行:结点数
第三行:结点集
第四行:无边标记
第五行:边数
第六行:边集
第七行:权集
第八行:起始结点序号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)
- #include
- using namespace std;
-
- const int MAX = 1000;
-
- string kind;
- int m = 0;
- int arr[MAX][2] = {0}; //输入权集的对应横纵坐标
- int none, u; //无边标记
- int all[MAX][MAX] = {0};
- bool tree_flag[MAX][MAX] = {false};
-
- struct E //边
- {
- int num;
- int weight;
- E *next = NULL;
- };
-
- struct V //结点
- {
- string data;
- E *next = NULL;
- };
-
- struct graph
- {
- V m[MAX];
- int number_of_V;
- int number_of_E;
- };
-
- void addweight_no_direction(graph &g);
- void addweight(graph &g);
-
- void creat_no_directioin(graph &g)
- {
- int v, f;
-
- cin >> v;
- g.number_of_V = v;
- for (int i = 0; i < v; i++)
- {
- cin >> g.m[i].data;
- }
- //输入顶点字母
-
- cin >> none; //输入无边标记
-
- cin >> f;
- g.number_of_E = f;
- for (int i = 0; i < f; i++)
- {
- int v1, v2;
- cin >> v1 >> v2;
- arr[i][0] = v1;
- arr[i][1] = v2;
-
- E *p1 = new E;
- p1->num = v2;
- p1->next = g.m[v1].next;
- g.m[v1].next = p1;
-
- E *p2 = new E;
- p2->num = v1;
- p2->next = g.m[v2].next;
- g.m[v2].next = p2;
- }
- addweight_no_direction(g);
- }
- void addweight_no_direction(graph &g)
- {
- for (int j = 0; j < g.number_of_E; j++)
- {
- int temp = 0;
- cin >> temp;
- int number1 = arr[j][0];
- int number2 = arr[j][1];
-
- all[number1][number2] = temp;
- all[number2][number1] = temp;
-
- E *p;
- E *p1;
- p = g.m[number1].next;
- p1 = g.m[number2].next;
- while (p)
- {
- if (p->num == number2)
- {
- p->weight = temp;
- }
- p = p->next;
- }
-
- while (p1)
- {
- if (p1->num == number1)
- {
- p1->weight = temp;
- }
- p1 = p1->next;
- }
- }
- }
-
- void creat_direction(graph &g)
- {
- int v;
- int f;
-
- cin >> v;
- g.number_of_V = v;
- for (int i = 0; i < v; i++)
- {
- cin >> g.m[i].data;
- } //输入顶点字母
-
- cin >> none; //输入无边标记
-
- cin >> f;
- g.number_of_E = f;
- for (int i = 0; i < f; i++)
- {
- int v1, v2;
- cin >> v1 >> v2;
- arr[i][0] = v1;
- arr[i][1] = v2;
- E *p1 = new E;
- p1->num = v2;
- p1->next = g.m[v1].next;
- g.m[v1].next = p1;
- }
-
- addweight(g);
- }
-
- void addweight(graph &g)
- {
- for (int j = 0; j < g.number_of_E; j++)
- {
- int temp = 0;
- cin >> temp;
- int number1 = arr[j][0];
- int number2 = arr[j][1];
-
- all[number1][number2] = temp;
-
- E *p;
- p = g.m[number1].next;
-
- while (p)
- {
- if (p->num == number2)
- {
- p->weight = temp;
- }
- p = p->next;
- }
- }
- }
-
- void printV(graph g)
- {
- int m = 0;
- for (int h = 0; h < g.number_of_V; h++)
- {
- if (m == 1)
- {
- cout << " ";
- }
- m = 1;
- cout << g.m[h].data;
- }
- cout << endl
- << endl;
- }
-
- void printgraph(graph g)
- {
- for (int i = 0; i < g.number_of_V; i++)
- {
- for (int j = 0; j < g.number_of_V; j++)
- {
- if (all[i][j] == 0)
- {
- cout << none;
- }
-
- else
- {
- cout << all[i][j];
- }
- cout << '\t';
- }
- cout << endl;
- }
- }
-
- void print_tree(graph g)
- {
- bool f = false;
- for (int i = 0; i < g.number_of_V; i++)
- {
- if (i == u)
- {
- continue; //根节点不输出
- }
- for (int j = 0; j < g.number_of_V; j++)
- {
- if (tree_flag[i][j] == true)
- {
- if(f == true)
- {
- cout<<",";
- }
- else
- {
- f = true;
- }
- cout << "(" << g.m[j].data << "," << g.m[i].data << "," << all[i][j] << ")";
- }
- }
- }
- }
-
- int find(graph g, string data)
- {
- for (int i = 0; i < g.number_of_V; i++)
- {
- if (g.m[i].data == data)
- {
- return i;
- }
- }
-
- return -1;
- }
-
- void prim(graph g, int u)
- //核心思路:划分已添加和未添加两部分,
- {
- bool flag_judge[g.number_of_V] = {false};
- //标记已添加至二叉树的结点,每个点都要被添加且仅添加一次,以true的结点遍历寻找指向false结点的最小边
- //int flag_num[g.number_of_V] = {0};
- //标记已添加结点的已连接边,一旦到2,不再加边;结束后为0,视为叶子结点
-
- int now_node = 1; //记录一下循环结束条件
-
- vector
now_tree; - now_tree.push_back(g.m[u]);
- flag_judge[u] = true; //从这里开始
-
- while (now_node < g.number_of_V) //还有节点没有被加入二叉树
- {
- int start_node = -1, min_node = -1, min_value = none;
- for (int i = 0; i < now_node; i++)
- {
- //注意一下这里 是不是把nowtree的编号和g的编号弄混了
- //if (flag_num[find(g, now_tree[i].data)] == 2)
- //{
- // continue;
- //} //这个结点已经到达构建二叉树的上限了
- //最小生成树不用限死在二叉树啊!!!!!!!!!啊!!!!!!!
-
- E *p = now_tree[i].next;
- while (p != NULL)
- {
- if (p->weight < min_value && flag_judge[p->num] == false) //比现在的边小,且终点未被加入
- {
- min_value = p->weight;
- min_node = p->num;
- start_node = i;
- }
- p = p->next;
- }
- } //找出指向未加入结点的最小边
-
- start_node = find(g, now_tree[start_node].data);
-
- flag_judge[min_node] = true;
-
- //flag_num[start_node]++;
-
- tree_flag[min_node][start_node] = true;
-
- //标记该条边和该点入选
- now_tree.push_back(g.m[min_node]);
- now_node++;
- }
- }
-
- int main()
- {
- cin >> kind;
- if (kind == "DN")
- {
- cout << "DN" << endl;
- graph g;
- creat_direction(g);
- printV(g);
-
- printgraph(g);
-
- cin >> u;
- prim(g, u);
-
- print_tree(g);
- }
-
- else if (kind == "UDN")
- {
- cout << "UDN" << endl;
- graph g;
- creat_no_directioin(g);
- printV(g);
-
- printgraph(g);
-
- cin >> u;
- prim(g, u);
-
- print_tree(g);
- }
-
- getchar();
- getchar();
-
- return 0;
- }