c++数据结构小助手 : 可视化树与图工具

本文介绍了一款使用C++和`graphics.h`实现的可视化图与树工具,通过读取`graph.txt`文件,展示有向边的图,并支持节点拖动布局。重点展示了如何从文件中读取图数据、绘制箭头以及节点操作功能。
摘要由CSDN通过智能技术生成

c++数据结构小助手 : 可视化树与图工具

基于 graphics.h;
从文件 graph.txt 读图
格式如下:
命名:graph.txt
第一行,两个整数,n个点和m条边,边全都是有向边
第二行到第m+1行
每行三个整数
a b c
表示从a到b有一条权重为c的边

在这里插入图片描述
无向边就是两条有向边

效果:
在这里插入图片描述
左键点击点可以拖动改变布局

图中箭头是算出来的

#include <iostream>
#include <stdio.h>
#include <graphics.h>
#include <unordered_map>
#include <vector>
#include <queue>
#include <cmath>
#include <cstring>
#include <conio.h>
#include <functional>
#include <stdio.h>
#include <io.h>
#include <string>
#include <fstream>
#include <sstream>
#include<time.h>

/*
从文件读取

本人平时不太喜欢写注释,特别是在写一些比较小的程序的

左键点击图中的点有惊喜

*/

#define MAX_LINE 1024
#define MAXR 100
#define MINR 1 

using namespace std;

#define WINDOWW 500
#define WINDOWH 500
#define X_AXIS WINDOWH/2
#define Y_AXIS WINDOWW/2
#define MIDW WINDOWW/2
#define MIDH WINDOWH/2
#define PI 3.1415926
#define VER_SIZE 10

#define MAX_VERS 2000

typedef pair<int, int> pii;
typedef pair<int, pii> pi_ii;

int n, m;

double toRadius(double degree){ // 角度转弧度
	double flag = (degree < 0) ? -1.0 : 1.0;
	if (degree < 0){
		degree = degree*-1.0;
	}
	double res = flag*(degree*PI) / 180;
	return res;
}

void intToChar(int i, TCHAR res[]){ // int转char
	char t[33];
	int p = 0, q = 0;
	while (i){
		t[p++] = i % 10 + '0';
		i /= 10;
	}
	for (int i = p - 1; i >= 0; i--){
		res[q++] = t[i];
	}
	res[q] = '\0';
}

bool drawArray(int x1, int y1, int x2, int y2, double breath = 15){ // 画箭头
	int xa, ya, xb, yb, xt, yt;

	if (x1 == x2){
		xt = x1;
		if (y1 > y2){
			y1 -= breath;
			y2 += breath;
			yt = y2 + breath / 2;
		}
		else{
			y1 += breath;
			y2 -= breath;
			yt = y2 - breath / 2;
		}
		xa = xt - breath / 2;
		ya = yt;
		xb = xt + breath / 2;
		yb = yt;
	}
	else{
		double k = (double)(y1 - y2) / (double)(x1 - x2);
		double dx, dy;
		dx = breath / sqrt(1 + k*k);
		dy = fabs(k)*dx;
		if (k >= 0){
			if (y1 < y2){
				x1 += dx;
				y1 += dy;
				x2 -= dx;
				y2 -= dy;
				xt = x2 - dx / 2;
				yt = y2 - dy / 2;
			}
			else{
				x2 += dx;
				y2 += dy;
				x1 -= dx;
				y1 -= dy;
				xt = x2 + dx / 2;
				yt = y2 + dy / 2;
			}
			xa = xt + dy / 3;
			ya = yt - dx / 3;
			xb = xt - dy / 3;
			yb = yt + dx / 3;
		}
		else{
			if (y1 > y2){
				x1 += dx;
				y1 -= dy;
				x2 -= dx;
				y2 += dy;
				xt = x2 - dx / 2;
				yt = y2 + dy / 2;
			}
			else{
				x2 += dx;
				y2 -= dy;
				x1 -= dx;
				y1 += dy;
				xt = x2 + dx / 2;
				yt = y2 - dy / 2;
			}
			xa = xt - dy / 3;
			ya = yt - dx / 3;
			xb = xt + dy / 3;
			yb = yt + dx / 3;
		}

	}
	POINT pts[] = { { x2, y2 }, { xa, ya }, { xb, yb } };
	fillpolygon(pts, 3);
	line(x1, y1, x2, y2);
	return true;
}

unordered_map<int, pii> initVerXY(int vertices){
	double D_degree = 360.0 / (double)vertices;
	double degree = 0;
	unordered_map<int, pii> vers;

	for (int i = 1; i <= vertices; i++){
		int verY, verX;

		double k = tan(toRadius(degree));
		if ((0 <= degree&&degree <= 90) || (270 < degree&&degree <= 360)){
			if (-1 <= k && k <= 1){
				verX = (WINDOWW - MIDW) / 2;
				verY = k*verX;
			}
			else{
				verY = (WINDOWH - MIDH) / 2;
				if (k < 0) verY = -verY;
				verX = verY / k;
			}
		}
		else{
			if (-1 <= k && k <= 1){
				verX = (MIDW - WINDOWW) / 2;
				verY = k*verX;
			}
			else{
				verY = (MIDH - WINDOWH) / 2;
				if (k < 0) verY = -verY;
				verX = verY / k;
			}
		}
		degree += D_degree;

		int num1 = rand() % (MAXR - MINR) + MAXR;
		int num2 = rand() % (MAXR - MINR) + MAXR;
		int num3 = rand() % (MAXR - MINR) + MAXR;
		int num4 = rand() % (MAXR - MINR) + MAXR;
		verX = verX + num1 - num3;
		verY = verY + num2 - num4;

		vers[i] = { verX + MIDW, verY + MIDH };
	}

	return vers;
}

bool drawGraph(unordered_map<int, pii> vers, priority_queue<pi_ii> sides){

	for (int i = 1; i <= vers.size(); i++){
		setcolor(LIGHTRED);
		TCHAR s[32];
		intToChar(i, s);
		int verX = vers[i].first, verY = vers[i].second;
		circle(verX, verY, VER_SIZE);
		setcolor(WHITE);
		settextcolor(GREEN);
		outtextxy(verX - 4, verY - 7, s);
		settextcolor(WHITE);
	}

	while (sides.size()){
		pi_ii t = sides.top();
		sides.pop();
		int verA = t.second.first;
		int verB = t.second.second;
		int len = t.first;
		setcolor(YELLOW);
		drawArray(vers[verA].first, vers[verA].second, vers[verB].first, vers[verB].second);
		setcolor(WHITE);
		TCHAR s[32];
		intToChar(len, s);
		outtextxy(vers[verA].first + vers[verB].first >> 1, vers[verA].second + vers[verB].second >> 1, s);
	}
	return true;
}

template<class out_type, class in_value>
out_type convert(const in_value & t)
{
	stringstream stream;
	stream << t;// 向流中传值
	out_type result;// 这里存储转换结果
	stream >> result;// 向result中写入值
	return result;
}

bool checkIfGetVer(int vx, int vy, int mx, int my){
	double d;
	d = sqrt((double)(vx - mx)*(vx - mx) + (double)(vy - my)*(vy - my));
	if (d < VER_SIZE) return true;
	return false;
}

void dragMove(unordered_map<int, pii> vers, priority_queue<pi_ii> sides){
	MOUSEMSG clickdown;
	MOUSEMSG down;
	while (true){
		clickdown = GetMouseMsg();


		switch (clickdown.uMsg){
		case WM_LBUTTONDOWN: // left click

			for (int i = 1; i <= vers.size(); i++){
				if (checkIfGetVer(vers[i].first, vers[i].second, clickdown.x, clickdown.y)){
					int flag = 0;

					while (true){
						down = GetMouseMsg();
						switch (down.uMsg){
						case WM_MOUSEMOVE:
							BeginBatchDraw(); // double huan chong
							cleardevice();
							vers[i].first = down.x;
							vers[i].second = down.y;
							drawGraph(vers, sides);
							EndBatchDraw();
							break;
						case WM_LBUTTONDOWN:
							flag = 1;
							break;
						}
						if (flag)break;
					}
				}
			}
			break;
		case WM_LBUTTONUP:
			break;
		}

	}

}

int main(){
	srand(time(0));
	char buf[MAX_LINE];
	string buff;
	FILE *fp;
	int len;

	if ((fp = fopen("graph.txt", "r")) == NULL)
	{
		perror("fail to read");
		exit(1);
	}
	fgets(buf, MAX_LINE, fp);
	len = strlen(buf);
	buf[len - 1] = '\0';
	buff = buf;
	stringstream sstream;
	sstream << buff;

	string t;
	sstream >> t;
	n = convert<int>(t);
	//printf("%d ", n);
	sstream >> t;
	m = convert<int>(t);
	//printf("%d\n", m);

	priority_queue<pi_ii> sides;

	while (fgets(buf, MAX_LINE, fp) != NULL)
	{
		stringstream sstream;
		string t;
		len = strlen(buf);
		buf[len - 1] = '\0';
		int a, b, c;
		buff = buf;
		sstream << buff;
		sstream >> t;
		a = convert<int>(t);
		sstream >> t;
		b = convert<int>(t);
		sstream >> t;
		c = convert<int>(t);
		sides.push({ c, { a, b } });
		printf("起点:%d,终点:%d,权重:%d\n", a, b, c);
	}
	unordered_map<int, pii> vers;
	vers = initVerXY(n);
	initgraph(WINDOWW, WINDOWH);
	//circle(0, 0, 10);


	drawGraph(vers, sides);
	dragMove(vers, sides);
	//while (1);
	// printGraph(n, sides);

	// dragMove();

	closegraph();

	getchar();
	getchar();
	return 0;
}
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值