1. 程式人生 > >基於Qt的二叉樹的繪製

基於Qt的二叉樹的繪製

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函式中的引數修改二叉樹的形態。