-
实验目的
-
掌握图的存储结构;
-
掌握利用C/C++编程语言实现数据结构的编程方法;
-
通过上机时间加强利用数据结构解决实际应用问题的能力;
-
实验相关知识
-
图的邻接存储结构实现;
-
Prim算法求图的最小生成树;
-
实验内容与要求
-
利用EasyX绘制图。
-
利用Prim算法求图的最小生成树。
-
实现过程与结构
-
读取文件中图G的顶点信息和边信息,利用EasyX绘制图,并利用Prim算法求出图G的最小生成树,并突出显示。
输入说明:图信息文件 中所包含信息格式为
顶点个数n
n个顶点的坐标
边的条数m
m条边的起点,终点,权重
例如“graph4.txt”文件所示如下,其中红色字体为说明文字,非文档中的内容:
4 (4个顶点)
78 96
129 468
280 450
400 35
6 (6条无向边)
1 2 19 (<1,2> 权重为19)
1 3 23
1 4 30
2 3 17
2 4 13
3 4 12
运行结果说明:
读取图文件中的信息后,利用EasyX进行绘图,如下所示
可以通过鼠标左键拖拽顶点,移动顶点的位置,点击鼠标右键开始求解最小生成树,并突出显示该最小生成树,如下图所示。
-
代码框架与说明
#include <graphics.h> // 引用图形库头文件 #include<string.h> #include<math.h> #include <stdio.h> #include<string> #include<fstream> using namespace std; int win_width = 640; int win_height = 560; int origin_x = 0;// 坐标原点位置x轴 int origin_y = 0;// 坐标原点位置y轴 int R = 20; const int MAX_VERTEX_NUM = 20; typedef struct Node { int x; int y; int r = R; }Node; typedef struct { Node vexs[MAX_VERTEX_NUM]; //顶点集 int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; //邻接矩阵,于无权图1、0表示两个顶点是否相邻,对于有权图为权值 int vexnum, arcnum; //图的顶点数和弧数 }Graph; Graph G; typedef struct Closeedge { int end_ver; int lowcost; int flag; }Closeedge; Closeedge closeedges[MAX_VERTEX_NUM];//最小生成树的边 void init();//初始化窗体 void init_Graph(); void draw_Graph(); void draw_arc(Node v1, Node v2, int weight);//在v1和v2顶点之间绘制一条直线,并在直线的中心出标注边的权重weight void draw_vex(Node v, int i);//绘制第i个顶点v void adjust_Grahp(MOUSEMSG m_down);//可以利用鼠标拖动圆,调整图中顶点的位置 void find_min_tree();// 求解最小生成树 void paint_min_tree();//绘制最小生成树 int main() { init(); init_Graph(); draw_Graph(); MOUSEMSG m_down;//定义一个鼠标消息 while (1) { m_down = GetMouseMsg(); if (m_down.uMsg == WM_LBUTTONDOWN) { adjust_Grahp(m_down); } if (m_down.uMsg == WM_RBUTTONDOWN) { break; } } find_min_tree(); Sleep(100000); closegraph(); } void init()//初始化窗口大小,窗口坐标中心点/画板背景 { initgraph(win_width, win_height); // 创建绘图窗口,大小为 640x480 像素 setorigin(origin_x, origin_y);//设置绘图的中心点为窗体的中心点 setbkcolor(BLACK); cleardevice();//清理窗口 return; } void init_Graph() { int i, j; int v1, v2, weight; string filename = "../graph10.txt"; ifstream infile(filename); infile >> G.vexnum; G.arcnum = 0; for (i = 1; i <= G.vexnum; i++) { infile >> G.vexs[i].x >> G.vexs[i].y; } for (i = 1; i <= G.vexnum; i++) { for (j = 1; j <= G.vexnum; j++) { G.arcs[i][j] = -1; } G.arcs[i][j] = 0; } infile >> G.arcnum; for (i = 1; i <= G.arcnum; i++) { infile >> v1 >> v2 >> weight; G.arcs[v1][v2] = weight; G.arcs[v2][v1] = weight; } } void draw_arc(Node v1, Node v2, int weight)//在v1和v2顶点之间绘制一条直线,并在直线的中心出标注边的权重weight { line(v1.x, v1.y, v2.x, v2.y); TCHAR s[5]; swprintf_s(s, _T("%d"), weight); settextcolor(WHITE); outtextxy((v1.x + v2.x) / 2, (v1.y + v2.y) / 2, s); } void draw_vex(Node v, int i)//绘制第i个顶点v { fillcircle(v.x, v.y, v.r); TCHAR s[5]; swprintf_s(s, _T("%d"), i); settextcolor(WHITE); outtextxy(v.x - R / 4, v.y - R / 4, s); } void draw_Graph()//绘制图 { setlinecolor(RED); for (int i = 1; i <= G.vexnum; i++) { for (int j = 1; j <= G.vexnum; j++) { draw_arc(G.vexs[i], G.vexs[j], G.arcs[i][j]); } } setfillcolor(MAGENTA); for (int i = 1; i <= G.vexnum; i++) { draw_vex(G.vexs[i], i); } } int get_clickcirclenum(double x, double y)//获取所点击圆的编号 { for (int i = 1; i <= G.vexnum; i++) { if ((G.vexs[i].x - x) * (G.vexs[i].x - x) + (G.vexs[i].y - y) * (G.vexs[i].y - y) <= G.vexs[i].r * G.vexs[i].r) return i; } return -1; } void adjust_Grahp(MOUSEMSG m_down)//可以利用鼠标拖动圆,调整图中顶点的位置 { MOUSEMSG m;//定义一个鼠标消息 int node_num; node_num = get_clickcirclenum(m_down.x, m_down.y); if (node_num > 0) { while (true) { m = GetMouseMsg(); if (m.uMsg == WM_LBUTTONUP) { settextcolor(RED); G.vexs[node_num].x = G.vexs[node_num].x + (m.x - m_down.x); G.vexs[node_num].y = G.vexs[node_num].y + (m.y - m_down.y); cleardevice(); draw_Graph();//重绘图 break; } } } return; } void find_min_tree()// 求解最小生成树 { for (int i = 1; i <= G.vexnum; i++) { closeedges[i].end_ver = 1; closeedges[i].lowcost = G.arcs[1][i]; closeedges[i].flag = 0; } closeedges[1].flag = 1; int min; for (int i = 2; i <= G.vexnum; i++) { min = -1; for (int j = 1; j <= G.vexnum; j++) { if (closeedges[j].flag == 0 && (closeedges[j].lowcost > 0 && (min < 0 || closeedges[min].lowcost>closeedges[j].lowcost))) min = j; } closeedges[min].flag = 1; setlinecolor(GREEN); setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 5); draw_arc(G.vexs[closeedges[min].end_ver], G.vexs[min], closeedges[min].lowcost); setlinecolor(RED); setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 1); setfillcolor(MAGENTA); for (int i = 1; i <= G.vexnum; i++) { draw_vex(G.vexs[i], i); } Sleep(1000); for (int j = 2; j <= G.vexnum; j++) { if (closeedges[j].flag == 0 && (G.arcs[j][min] > 0 && (closeedges[j].lowcost < 0 || closeedges[j].lowcost > G.arcs[j][min]))) { closeedges[j].end_ver = min; closeedges[j].lowcost = G.arcs[j][min]; } } getchar(); } }