Qt使用深度优先搜索和广度优先搜索遍历图

图是一种很重要的数据结构,图的存储方式通常使用邻接矩阵的方式存储:
连通的设为1 ,不连通设为-1 ,自己到自己为0。如下图所示:
在这里插入图片描述
通过图可以看到这是一个关于对角线对称的表格。

深度优先搜索效果:搜索顺序:0-1-2-4-3-5
在这里插入图片描述
广度优先搜索效果:搜索顺序:0-1-5-2-4-3
在这里插入图片描述
定义图:

#pragma once
#include "GraphVertex.h"
#include "ITraversal.h"

//图的定义

#define VERTEX_NUM 6

class QPainter;
class QtTraversal;
class IUpdateGraph;

class Graph :public ITraversal {
public:
	Graph();
	~Graph();

	void setCallback(IUpdateGraph* update);

	void drawGraph(QPainter* painter);

	void ergodic();

	virtual void startErgodic();
private:
	void init();
	void initGrah();
	QPoint getCirclePoint(QPoint center,double r , double angle);

	void drawVertex(QPainter* p);
	void drawEdge(QPainter* p);

	void dfs(GraphVertex vertex);
	void bfs();
private:
	//边之间的关系 - 邻接矩阵存储
	int _vertex[VERTEX_NUM][VERTEX_NUM];
	//具体的顶点
	GraphVertex _graphVertex[VERTEX_NUM];
	bool _book[VERTEX_NUM];

	//遍历线程
	QtTraversal* _traversalThread = nullptr;

	IUpdateGraph* _update = nullptr;
};

#include "Graph.h"
#include <QPainter>
#include <QtMath>
#include <QThread>
#include <queue>
#include "QtTraversal.h"
#include "ITraversal.h"
#include "IUpdateGraph.h"

Graph::Graph() {
	init();
	initGrah();
	_traversalThread = new QtTraversal(this);
}

Graph::~Graph() {
}

void Graph::setCallback(IUpdateGraph* update) {
	_update = update;
}

void Graph::drawGraph(QPainter* painter) {
	//绘制边
	drawEdge(painter);
	//绘制顶点
	drawVertex(painter);
}

void Graph::ergodic() {
	_traversalThread->start();
}

void Graph::startErgodic() {
#if 0
	bfs();
#else
	_graphVertex[0].setDrawBK(true);
	_book[0] = true;
	dfs(_graphVertex[0]);
#endif
}

void Graph::init() {
	for (int i =0;i< VERTEX_NUM;i++){
		for (int j =0;j< VERTEX_NUM;j++){
			if (i == j){
				_vertex[i][j] = 0;//自己到自己为0
			} else {
				_vertex[i][j] = -1;//-1代表无穷距离
			}
		}
	}

	for (int i = 0; i < VERTEX_NUM; i++) {
		_book[i] = false;
	}
}

void Graph::initGrah() {
	for (int i = 0; i < VERTEX_NUM; i++) {
		_graphVertex[i].setID(i);
	}
	_vertex[0][1] = 1;
	_vertex[1][0] = 1;

	_vertex[0][2] = 1;
	_vertex[2][0] = 1;

	_vertex[0][5] = 1;
	_vertex[5][0] = 1;

	_vertex[2][4] = 1;
	_vertex[4][2] = 1;

	_vertex[3][4] = 1;
	_vertex[4][3] = 1;
}

QPoint Graph::getCirclePoint(QPoint center, double r, double angle) {
	QPoint pt;
	pt.setX(center.x() + r*cos(qDegreesToRadians(angle)));
	pt.setY(center.y() + r*sin(qDegreesToRadians(angle)));
	return pt;
}

void Graph::drawVertex(QPainter* painter) {
	for (int i = 0; i < VERTEX_NUM; i++) {
		double a = i * 360.0 / VERTEX_NUM;
		QPoint vertexPt = getCirclePoint(QPoint(200, 200), 100, a);
		_graphVertex[i].setCenter(vertexPt);
		_graphVertex[i].drawVertex(painter);
	}
}

void Graph::drawEdge(QPainter* p) {
	QPen penLine(QBrush(Qt::red), 2, Qt::SolidLine);
	p->setPen(penLine);

	for (int i = 0; i < VERTEX_NUM; i++) {
		for (int j = 0; j < VERTEX_NUM; j++) {
			if (_vertex[i][j] != 0 && _vertex[i][j] != -1) {
				p->drawLine(_graphVertex[i].getCenter(), _graphVertex[j].getCenter());
			}
		}
	}
}

void Graph::dfs(GraphVertex vertex) {
	for (int i = 0; i < VERTEX_NUM; i++) {
		if (_vertex[i][vertex.getID()] == 1 && _book[i] == false) {
			_book[i] = true;
			_graphVertex[i].setDrawBK(true);
			_update->updateMap();
			QThread::msleep(1000);
			dfs(_graphVertex[i]);
		}
	}
}

void Graph::bfs() {
	std::queue<GraphVertex> queueVertex;

	queueVertex.push(_graphVertex[0]);
	_graphVertex[0].setDrawBK(true);
	_book[0] = true;
	_update->updateMap();
	QThread::msleep(1000);

	while (queueVertex.size()) {

		GraphVertex first = queueVertex.front();

		for (int i = 0; i < VERTEX_NUM; i++) {
			if (_vertex[i][first.getID()] == 1 && _book[i] == false) {
				_book[i] = true;
				_graphVertex[i].setDrawBK(true);
				_update->updateMap();
				QThread::msleep(1000);
				queueVertex.push(_graphVertex[i]);
			}
		}

		queueVertex.pop();
	}
}

定义顶点:

#pragma once
#include <QRect>
#include <QColor>
#include <QPoint>

class QPainter;

//图的顶点

class GraphVertex {
public:
	GraphVertex();
	~GraphVertex();

	void setID(int id);
	int getID();

	void setCenter(QPoint pt);
	QPoint getCenter();

	void setDrawBK(bool b);

	void drawVertex(QPainter* p);
private:
	int _id = -1;
	QRect _rect;//圆的外接矩形
	QColor _lineColor = QColor(255, 0, 0);//线色

	bool _isDrawBK = false;//绘制背景
	QColor _bkColor = QColor(255, 255, 0);//背景色
};


#include "GraphVertex.h"
#include <QPainter>
#include <QBrush>

#define LENGTH 20

GraphVertex::GraphVertex() {

}

GraphVertex::~GraphVertex() {

}

void GraphVertex::setID(int id) {
	_id = id;
}

int GraphVertex::getID() {
	return _id;
}

void GraphVertex::setCenter(QPoint pt) {
	_rect.setLeft(pt.x() - LENGTH / 2);
	_rect.setTop(pt.y() - LENGTH / 2);
	_rect.setWidth(LENGTH);
	_rect.setHeight(LENGTH);
}

QPoint GraphVertex::getCenter() {
	return _rect.center();
}

void GraphVertex::setDrawBK(bool b) {
	_isDrawBK = b;
}

void GraphVertex::drawVertex(QPainter * p) {
	if (_isDrawBK){
		QBrush bkBrush(_bkColor);
		p->setPen(Qt::NoPen);
		p->setBrush(bkBrush);
		p->drawEllipse(_rect);
	} else {
		p->setPen(Qt::NoPen);
		p->setBrush(Qt::NoBrush);
	}

	QPen linePen(QBrush(_lineColor), 5, Qt::SolidLine);
	p->setPen(linePen);
	p->drawEllipse(_rect);

	QPen fontPen(Qt::black);
	p->setPen(fontPen);
	p->drawText(_rect, Qt::AlignCenter, QString::number(_id));
}

定义遍历线程:

#pragma once
#include <QThread>

class ITraversal;

class QtTraversal :public QThread {
public:
	QtTraversal(ITraversal* traversal);
	~QtTraversal();

	void run()override;

private:
	ITraversal* _traversal = nullptr;
};


#include "QtTraversal.h"
#include "ITraversal.h"

QtTraversal::QtTraversal(ITraversal* traversal) {
	_traversal = traversal;
}

QtTraversal::~QtTraversal() {
}

void QtTraversal::run() {
	_traversal->startErgodic();
}

定义线程调用接口:

#pragma once

//遍历接口

class ITraversal {
public:
	ITraversal();
	~ITraversal();

	virtual void startErgodic() = 0;

};


#include "ITraversal.h"

ITraversal::ITraversal() {
}


ITraversal::~ITraversal() {
}

定义地图刷新接口:

#pragma once

//更新图

class IUpdateGraph {
public:
	IUpdateGraph();
	~IUpdateGraph();

	virtual void updateMap() = 0;

};


#include "IUpdateGraph.h"

IUpdateGraph::IUpdateGraph() {
}


IUpdateGraph::~IUpdateGraph() {
}

定义主界面:

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_GraphTraversal.h"
#include "IUpdateGraph.h"

class Graph;

class GraphTraversal : public QMainWindow, public IUpdateGraph {
	Q_OBJECT

public:
	GraphTraversal(QWidget *parent = Q_NULLPTR);

	virtual void paintEvent(QPaintEvent *event)override;

	virtual void updateMap()override;
private slots:
	void slotStart();
	void slotUpdateGraph();
signals:
	void sigUpdateGraph();
private:
	Ui::GraphTraversalClass ui;

	Graph* _graph = nullptr;
};

#include "GraphTraversal.h"
#include <QPainter>
#include "Graph.h"

GraphTraversal::GraphTraversal(QWidget *parent)
	: QMainWindow(parent) {
	ui.setupUi(this);

	setMouseTracking(true);
	ui.centralWidget->setMouseTracking(true);
	connect(ui.pushButtonStart, SIGNAL(clicked()), this, SLOT(slotStart()));
	connect(this, SIGNAL(sigUpdateGraph()), this, SLOT(slotUpdateGraph()), Qt::BlockingQueuedConnection);

	_graph = new Graph;
	_graph->setCallback(this);
}

void GraphTraversal::paintEvent(QPaintEvent *event) {
	QPainter painter(this);
	painter.setRenderHint(QPainter::Antialiasing);
	_graph->drawGraph(&painter);
}

void GraphTraversal::updateMap() {
	emit sigUpdateGraph();
}

void GraphTraversal::slotStart() {
	_graph->ergodic();
}

void GraphTraversal::slotUpdateGraph() {
	update();
}

源码下载
aaa

  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wb175208

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值