栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

三种算法的同步演示

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

三种算法的同步演示

需求:

  1、基于下图构造图;

  2、分别使用深度优先遍历(DFS)、Prim、Dijkstra算法从任意用户输入的节点开始对图进行遍历、求MST及最短路径;

  3、三个算法同时动态显示构造过程(非节点动态打印);

  4、每一步都要求显示/打印所有试探的路径。

三个算法同时运行,每一步需要把所有试探/考虑的边突出显示(上图中的绿色边),并分别基于三个算法打印出辅助数据以便进行下一步路径的判定

 补充需求:

  1、鼓励使用MFC进行可视化,如使用命令行

          程序,必须使用EGE等图形库绘图;

  2、如果能同时实现A*算法的可视化可加分。

graph.h

#ifndef GRAPH01
#define GRAPH01
#include
const int maxweight = 65535;
using namespace std;
class graph
{
public:
    graph(int sz);
    ~graph() { delete[]edge; }
    
    int getweight(int v1, int v2) { if (v1 != -1 && v2 != -1) return edge[v1][v2]; else return 0; }//取得两节点之间边的权值
    int getfirstnei(int v);//得到第一个相邻结点
    int getnextnei(int v, int w);//得到下一个相邻节点
    int numedg;//边总数
    int numver;//结点总数
    int maxver;//最大结点数
    string verlist;//结点数组
    int** edge;//边的邻接矩阵

};
class node//结点类
{
public:
    friend graph;
    node() {};
    ~node() {};
    int x;//结点的X坐标
    int y;//结点的Y坐标
    string data;//结点的数据
    int sign = 0;//判断是否被访问过的标志
};


#endif


#define SHOW_CONSOLE
#include
#include 
#include
using namespace std;
graph::graph(int sz)//初始化一个图
{
    maxver = sz; numedg = 0; numver = 0;
    int i, j;
    edge = (int**)new int* [maxver];
    for (i = 0; i < maxver; i++)
        edge[i] = new int[maxver];
    for (i = 0; i < maxver; i++)
        for (j = 0; j < maxver; j++)
            edge[i][j] = (i == j) ? 0 : maxweight;
    numver = 10;
    numedg = 17;
    verlist = "ABCDEFGHIJ";
    edge[0][1] = edge[1][0] = 750;
    edge[0][2] = edge[2][0] = 680;
    edge[1][2] = edge[2][1] = 800;
    edge[1][4] = edge[4][1] = 970;
    edge[1][3] = edge[3][1] = 650;
    edge[3][2] = edge[2][3] = 820;
    edge[3][4] = edge[4][3] = 570;
    edge[3][6] = edge[6][3] = 530;
    edge[3][5] = edge[5][3] = 975;
    edge[4][8] = edge[8][4] = 840;
    edge[2][5] = edge[5][2] = 960;
    edge[6][5] = edge[5][6] = 680;
    edge[9][5] = edge[5][9] = 990;
    edge[6][7] = edge[7][6] = 900;
    edge[6][9] = edge[9][6] = 980;
    edge[7][8] = edge[8][7] = 840;
    edge[7][9] = edge[9][7] = 985;
}
int graph::getfirstnei(int v)
{
    if (v != -1)
    {
        for (int num = 0; num < numver; num++)
            if (edge[v][num] > 0 && edge[v][num] < maxweight)return num;
        return -1;
    }
}
int graph::getnextnei(int v, int w)
{
    if (v != -1 && w != -1)
    {
        for (int num = w + 1; num < numver; num++)
            if (edge[v][num] > 0 && edge[v][num] < maxweight)return num;
    }
    return -1;
}

Graph.cpp

#define SHOW_CONSOLE
#include"graph.h"
#include
#include 
#include
#include
using namespace std;
void show(graph& gra, int& num, node* n);
void DFS(graph& gra, node* n, int m)//深度优先遍历算法
{
	cout << n[m].data << endl;
	n[m].sign = 1;
	int temp = gra.getfirstnei(m);
	setlinewidth(5);
	setcolor(RED);
	while (temp != -1) {
		if (n[temp].sign == 0) { Sleep(500); line(n[m].x, n[m].y, n[temp].x, n[temp].y); DFS(gra, n, temp); }//递归
		temp = gra.getnextnei(m, temp);

	}
}
int prim(graph& gra, node* n, int m, int* d)//prim算法
{
	for (int p = 0; p < gra.numver; p++)//将所有的距离初始化,设置为int类型最大值
	{
		d[p] = INT_MAX;
	}
	d[m] = 0;//到自己的距离为0
	int sum = 0;
	for (int i = 0; i < gra.numver; i++)
	{
		int u = -1;//u点到某一结点最小
		int min = INT_MAX;
		for (int j = 0; j < gra.numver; j++)
		{
			if (n[j].sign == 0 && d[j] < min) {
				min = d[j];
				u = j;
			}
		}
		if (u == -1) { return -1; }//找不到d[j]说明不连通
		n[u].sign = 1;
		setlinewidth(5);
		setcolor(RED);
		sum += d[u];
		for (int l = 0; l < gra.numver; l++)//画边
		{
			for (int k = l + 1; k < gra.numver; k++)
			{
				if (gra.edge[l][k] == d[u]) {
					Sleep(500);
					line(n[l].x, n[l].y, n[k].x, n[k].y);
				}
			}
		}
		for (int v = 0; v < gra.numver; v++) //寻找该结点相邻的最小边
		{
			if (n[v].sign == 0 && gra.edge[u][v] < d[v]) {
				d[v] = gra.edge[u][v];
			}
		}
	}
	cout << sum << endl;//输出最小生成树的总权值
	return sum;
}
void dijkstra(graph& gra, node* n, int* d, int ch, int path[])//ch是终点,d为存储最短距离的数组,path是存储最短路径所经结点的数组
{
	int min;
	for (int i = 0; i < gra.numver; i++)
	{
		d[i] = gra.getweight(ch, i);
		if (i != ch && d[i] < INT_MAX)path[i] = ch;
		else path[i] = -1;
	}
	n[ch].sign = 1; d[ch] = 0;//将标志置为1,到自己距离为0
	for (int i = 0; i < gra.numver - 1; i++)
	{
		min = INT_MAX;
		int u = ch;
		for (int j = 0; j < gra.numver; j++)
		{
			if (n[j].sign == 0 && d[j] < min) {
				u = j; min = d[j];
			}
			n[u].sign = 1;
			for (int k = 0; k < gra.numver; k++)
			{
				int w = gra.getweight(u, k);
				if (n[k].sign == 0 && w < INT_MAX && d[u] + w < d[k])
				{
					d[k] = d[u] + w;//最短路径权值的累加
					path[k] = u;
				}
			}
		}
	}
	setlinewidth(5);
	setcolor(RED); 
	line(n[3].x, n[3].y, n[6].x, n[6].y);
	line(n[6].x, n[6].y, n[9].x, n[9].y);
}
void printpath(graph& gra, node* n, int v, int* dist, int path[], int zhongdian)//输出最短路径所经过的结点
{
	int i, j, k, num = gra.numver;
	int* d = new int[num];
	for (i = 0; i < num; i++)
	{
		if (i != v && i == zhongdian) {
			j = i; k = 0;
			while (j != v) { d[k++] = j; j = path[j]; }
			cout << n[v].data << " ";
			while (k > 0) {
				cout << n[d[--k]].data << " ";

			}
			cout << "最短路径长度:" << dist[i] << endl;
		}
	}
	
}
int main()
{
	initgraph(1000, 1000, INIT_RENDERMANUAL);	//初始化窗口
	setfillcolor(YELLOW);
	setbkcolor(WHITE);
	setfontbkcolor(WHITE);
	cout << "结点:0-A;1-B;2-C;3-D;4-E;5-F;6-G;7-H;8-I;9-J" << endl;
	int num = 0;
	graph gra(20);
	cout << "结点总数:" << gra.numver << " " << "边总数:" << gra.numedg << endl;//输出结点总数,边总数
	for (int i = 0; i < gra.numver; i++)//输出有权值的边
		for (int j = i + 1; j < gra.numver; j++)
		{
			int w = gra.getweight(i, j);
			if (w > 0 && w < maxweight) {
				char e1 = gra.verlist[i]; char e2 = gra.verlist[j];
				cout << "(" << e1 << "," << e2 << "," << w << ")" << endl;
			}
		}


	system("pause");
	node* no = new node[10];//创建十个结点
	for (int p = 0; p < gra.numver; p++)
	{
		no[p].data = gra.verlist[p];
	}
	show(gra, num, no);
	cout << "请选择算法:1.DFS算法   2.Prim算法   3.Dijkstra算法" << endl;
	int choice;
	cin >> choice;
	if (choice == 1)
	{
		int start;
		cout << "输入初始节点(0-9)" << endl;
		cin >> start;
		DFS(gra, no, start);
	}
	if (choice == 2)
	{
		int* vec = new int[10];//用于prim算法
		int start;
		cout << "输入初始节点(0-9)" << endl;
		cin >> start;
		prim(gra, no, start, vec);
	}
	if (choice == 3)
	{
		int start, end;
		cout << "请输入:" << endl;
		cin >> start >> end;
		int* arr = new int[10];
		int path[10];
		dijkstra(gra, no, arr, start, path);
		printpath(gra, no, start, arr, path, end);
	}
	//line(num[4].x, num[4].y, num[7].x, num[7].y);
	getch();
	closegraph();
}
void show(graph& gra, int& num, node* n)//构建图
{
	if (gra.numver == 0)return;
	fillellipse(800, 100, 23, 23);//A
	n[0].x = 800; n[0].y = 100;
	char ch[100] = { NULL };
	for (int i = 0; i < 1; i++)
	{
		ch[i] = gra.verlist[num];
	}
	xyprintf(800, 100, ch);
	num++;
	Sleep(500);
	fillellipse(700, 160, 23, 23);//B
	n[1].x = 700; n[1].y = 160;
	for (int i = 0; i < 1; i++)
	{
		ch[i] = gra.verlist[num];
	}
	xyprintf(700, 160, ch);
	num++;
	Sleep(500);
	fillellipse(780, 220, 23, 23);//C
	n[2].x = 780; n[2].y = 220;
	for (int i = 0; i < 1; i++)
	{
		ch[i] = gra.verlist[num];
	}
	xyprintf(780, 220, ch);
	num++;
	Sleep(500);
	fillellipse(700, 250,23,23);//D
	n[3].x = 700; n[3].y = 250;
	for (int i = 0; i < 1; i++)
	{
		ch[i] = gra.verlist[num];
	}
	xyprintf(700, 250, ch);
	num++;
	Sleep(500);
	fillellipse(580, 260, 23, 23);//E
	n[4].x = 580; n[4].y = 260;
	for (int i = 0; i < 1; i++)
	{
		ch[i] = gra.verlist[num];
	}
	xyprintf(580, 260, ch);
	num++;
	Sleep(500);
	fillellipse(800, 400,23,23);//F
	n[5].x = 800; n[5].y = 400;
	for (int i = 0; i < 1; i++)
	{
		ch[i] = gra.verlist[num];
	}
	xyprintf(800, 400, ch);
	num++;
	Sleep(500);
	fillellipse(700, 420,23,23);//G
	n[6].x = 700; n[6].y = 420;
	for (int i = 0; i < 1; i++)
	{
		ch[i] = gra.verlist[num];
	}
	xyprintf(700, 420, ch);
	num++;
	Sleep(500);
	fillellipse(520, 440, 23,23);//H
	n[7].x = 520; n[7].y = 440;
	for (int i = 0; i < 1; i++)
	{
		ch[i] = gra.verlist[num];
	}
	xyprintf(520, 440, ch);
	num++;
	Sleep(500);
	fillellipse(480, 380,23,23);//I
	n[8].x = 480; n[8].y = 380;
	for (int i = 0; i < 1; i++)
	{
		ch[i] = gra.verlist[num];
	}
	xyprintf(480, 380, ch);
	num++;
	Sleep(500);
	
	fillellipse(680, 600,23, 23);//J
	n[9].x = 680; n[9].y = 600;
	for (int i = 0; i < 1; i++)
	{
		ch[i] = gra.verlist[num];
	}
	xyprintf(680, 600, ch);
	Sleep(500);
	//num++;
	//下面要输出每一条路径上的权值,因为没有找到更好方法,所以只能让数字的位数保持一致,其实可以不用显示权值
	//这样,题目中原值可以保留
	char c[4];
	for (int i = 0; i < gra.numver; i++)
		for (int j = i + 1; j < gra.numver; j++)
		{
			int w = gra.getweight(i, j);
			if (w > 0 && w < maxweight) {
				line(n[i].x, n[i].y, n[j].x, n[j].y);
				for (int p = 0; p < 4; p++)
				{
					c[p] = to_string(gra.edge[i][j])[p];
					c[3] = '';
				}
				outtextxy((n[i].x + n[j].x) / 2, (n[i].y + n[j].y) / 2, c);
			}
		}



}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/883463.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号