图是一种很重要的数据结构,图的存储方式通常使用邻接矩阵的方式存储:
连通的设为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