• 最小生成树动态演示


    1. 实验目的

    1. 掌握图的存储结构;

    2. 掌握利用C/C++编程语言实现数据结构的编程方法;

    3. 通过上机时间加强利用数据结构解决实际应用问题的能力;

    1. 实验相关知识

    1. 图的邻接存储结构实现;

    2. Prim算法求图的最小生成树;

    1. 实验内容与要求

    1. 利用EasyX绘制图。

    2. 利用Prim算法求图的最小生成树。

    1. 实现过程与结构

    1. 读取文件中图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进行绘图,如下所示

    可以通过鼠标左键拖拽顶点,移动顶点的位置,点击鼠标右键开始求解最小生成树,并突出显示该最小生成树,如下图所示。

     

    1. 代码框架与说明

    #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();
        }
    }
  • 相关阅读:
    【洛谷4657】[CEOI2017] Chase(一个玄学的树形DP)
    Tarjan在图论中的应用(二)——用Tarjan来求割点与割边
    Tarjan在图论中的应用(一)——用Tarjan来实现强连通分量缩点
    jquery放大镜
    自定义上传按钮样式
    一些设计理论资料
    jquery滚动条
    全栈工程师到底有什么用(转)
    巧用CSS文件愚人节恶搞(转)
    仿双色球-随机产生7个数字
  • 原文地址:https://www.cnblogs.com/xxxsans/p/14214486.html
Copyright © 2020-2023  润新知