基於Qt的二叉樹的繪製
阿新 • • 發佈:2018-11-07
1.這是一個典型的課程設計的題目。根據先序序列和中序序列建樹之後在輸出。為了避免程式碼的重複以及前篇一律,我在這個演示中只做99%,剩下關於圖形的調整大家自己完成。首先給出專案的結構設計。
UI設計(這裡大家就自由發揮了)
下面分別給出每個模組的程式碼以及修改的地方:
樹類的定義以及實現:
#ifndef LINKEDBINARYTREE_H #define LINKEDBINARYTREE_H #include<c++/algorithm> #include<c++/cstdio> #include<string> #include<c++/string> #include<c++/vector> #include<vector> using namespace std; struct BinTreeNode { char data; BinTreeNode*leftChild, *rightChild; BinTreeNode() { leftChild = NULL; rightChild = NULL; } BinTreeNode(char x, BinTreeNode*l = NULL, BinTreeNode *r = NULL) { data = x; leftChild = l; rightChild = r; } }; class linkedBinaryTree { private: BinTreeNode * root; public: linkedBinaryTree() {} BinTreeNode* Rebuild(vector<char>pre, vector<char>mid); void set(vector<char>pre, vector<char>mid) { root = this->Rebuild(pre, mid); } BinTreeNode*getRoot(){return root;} int getHeight(){int num=this->getHeight(root);return num;} int getHeight(BinTreeNode*subTree) { if (subTree == NULL)return 0; int i = getHeight(subTree->leftChild); int j = getHeight(subTree->rightChild); return (i < j) ? j + 1 : i + 1; } }; #endif // LINKEDBINARYTREE_H
CPP檔案:
#include"BinaryTree.h" #include<c++/vector> #include<c++/string> #include<c++/algorithm> using namespace std; BinTreeNode* linkedBinaryTree::Rebuild(vector<char> pre, vector<char> mid) { int nodeSize = mid.size(); if (nodeSize == 0) return NULL; vector<char> leftPre, leftMid, rightPre, rightMid; BinTreeNode* Root = new BinTreeNode(pre[0]); int rootPos = 0; for (int i = 0; i < nodeSize; i++) { if (mid[i] == pre[0]) { rootPos = i; break; } } for (int i = 0; i < nodeSize; i++) { if (i < rootPos) { leftMid.push_back(mid[i]); leftPre.push_back(pre[i + 1]); } else if (i > rootPos) { rightMid.push_back(mid[i]); rightPre.push_back(pre[i]); } } Root->leftChild = Rebuild(leftPre, leftMid); Root->rightChild = Rebuild(rightPre, rightMid); return Root; }
paint.h:
#ifndef PAINT_H #define PAINT_H #include"BinaryTree.h" #include <QWidget> class Paint : public QWidget { Q_OBJECT public: explicit Paint(QWidget *parent = 0); bool setInput(QString input1, QString input2); protected: void paintEvent(QPaintEvent *); void draw(BinTreeNode *node, int x, int y, int angle, bool isLeft, int depth, QPainter *p); BinTreeNode* test(); private: linkedBinaryTree* myTree; const int rootLengt=160; const double PI=3.1415926; }; #endif // PAINT_H
paint.cpp:
#include"paint.h"
#include <QPainter>
#include<stack>
#include<cstdio>
#include<QStack>
#include<QStack>
#include"BinaryTree.h"
#include<QPoint>
Paint::Paint(QWidget *parent) : QWidget(parent)
{
resize(600, 400);
myTree = new linkedBinaryTree();
}
bool Paint::setInput(QString input1, QString input2)
{
std::string s1 = input1.toStdString();
std::string s2 = input2.toStdString();
vector<char>v1;
vector<char>v2;
for(int i=0;i<s1.size();i++){v1.push_back(s1[i]);};
for(int i=0;i<s2.size();i++){v2.push_back(s2[i]);};
myTree->set(v1,v2);
return true;
}
BinTreeNode*Paint::test()
{
BinTreeNode*root=NULL;
root=new BinTreeNode('A');
root->leftChild=new BinTreeNode('B');
root->rightChild=new BinTreeNode('C');
root->leftChild->leftChild=new BinTreeNode('D');
root->leftChild->rightChild=new BinTreeNode('E');
root->rightChild->leftChild=new BinTreeNode('F');
root->rightChild->rightChild=new BinTreeNode('G');
return root;
}
void Paint::draw(BinTreeNode *node, int x, int y, int angle, bool isLeft, int depth, QPainter *p)
{
int leftAngle, rightAngle;
int dx,dy,nx,ny;
if (node==NULL)
return;
p->drawText(x,y,QChar(node->data));
if (node->leftChild!=NULL)
{
if (depth<2)
{
leftAngle = angle + rand()%15;
} else
{
if (!isLeft) {
leftAngle = angle + rand()%5 + 10;
} else {
leftAngle = rand()%45;
}
}
int lenEdge = rootLengt-depth*35;
dx = -cos(leftAngle*PI/180)*lenEdge;
dy = sin(leftAngle*PI/180)*lenEdge;
nx = x+dx;
ny = y+dy;
p->drawLine(x,y,nx,ny);
draw(node->leftChild,nx,ny,leftAngle,true,depth+1,p);
}
if (node->rightChild!=NULL)
{
if (depth<2)
{
rightAngle = angle + rand()%15;
} else
{
if (isLeft)
{
rightAngle = angle + rand()%5 + 10;
}
else
{
rightAngle = rand()%45;
}
}
int lenEdge = rootLengt-depth*15;
dx = cos(rightAngle*PI/180)*lenEdge;
dy = sin(rightAngle*PI/180)*lenEdge;
nx = x+dx;
ny = y+dy;
p->drawLine(x,y,nx,ny);
draw(node->rightChild,nx,ny,rightAngle,false,depth+1,p);
}
if (node->leftChild==NULL && node->rightChild==NULL) {return ; }
}
void Paint::paintEvent(QPaintEvent *e)
{
QPainter p(this);
draw(myTree->getRoot(), width()/2, height()/2, 10, true, 0, &p);
}
widget.h:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
public slots:
void on_btnCreat_clicked();
void on_clear_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
widget.cpp:
#include "widget.h"
#include"paint.h"
#include "ui_widget.h"
#include<c++/vector>
#include<QMessageBox>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
connect(ui->Create,SIGNAL(clicked(bool)),this,SLOT(on_btnCreat_clicked()));
connect(ui->clear,SIGNAL(clicked(bool)),this,SLOT(on_clear_clicked()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_btnCreat_clicked()
{
QString input1 = ui->lEdInput1->text();
QString input2 = ui->lEdInput2->text();
Paint *p = new Paint();
p->setInput(input1,input2);
p->show();
}
void Widget::on_clear_clicked()
{
ui->lEdInput2->clear();
ui->lEdInput1->clear();
}
main:
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
畫出來是一個很好看的二叉樹,大家可以根據paintEvent函式中的引數修改二叉樹的形態。