使用Qt4绘制二叉平衡树

最近在研究树结构,突发奇想将树结构使用Qt绘制出来,二话不说,开始动手。

主要思路:文件avl_tree.h包含树结构的实现,文件paint_tree.cpp和paint_tree.h实现一个由QWidget继承的对象,作为画板,将一棵avl树绘制出来。

注:只求实现功能,不考虑代码美观及效率等问题。

代码在bitbucket上,有兴趣的可以看看。

https://bitbucket.org/realid/painttree

avl_tree.h

#ifndef AVLTREE_H
#define AVLTREE_H
#include <QPoint>
#include <QPainter>
#include <cstdlib>
#include <QString>

template<class T>
class AvlNode {
    public:
        AvlNode():Left(NULL),Right(NULL),Height(0){}
    public:
        T Element;
        AvlNode *Left;
        AvlNode *Right;
        int Height;
};

template<class T>
class AvlTree {
    public:
        AvlTree():pRoot(NULL){}void Insert(T X);
        AvlNode<T>* Delete(T X);
        void Draw(AvlNode<T>* pNode, QPoint pt, QPainter* painter, 
                int scale, int height, int radi);private:
        int Height(AvlNode<T>* Node);
        int Max(int cmpa, int cmpb);
        AvlNode<T>* InsertPri(AvlNode<T>* Node, T X);
        AvlNode<T>* SingleRotateWithLeft(AvlNode<T>* pNode);
        AvlNode<T>* SingleRotateWithRight(AvlNode<T>* pNode);
        AvlNode<T>* DoubleRotateWithLeft(AvlNode<T>* pNode);
        AvlNode<T>* DoubleRotateWithRight(AvlNode<T>* pNode);
    public:
        AvlNode<T>* pRoot;
};

template<class T>
int AvlTree<T>::Height(AvlNode<T>* pNode)
{
    if (pNode == NULL)
        return -1;
    else
        return pNode->Height;
}

template<class T>
int AvlTree<T>::Max(int cmpa, int cmpb)
{
    return cmpa > cmpb ? cmpa : cmpb;
}

template<class T>
AvlNode<T>* AvlTree<T>::SingleRotateWithLeft(AvlNode<T> *pNode)
{
    AvlNode<T> *pLeft = pNode->Left;
    pNode->Left = pLeft->Right;
    pLeft->Right = pNode;

    pNode->Height = Max(Height(pNode->Left), Height(pNode->Right)) + 1;
    pLeft->Height = Max(Height(pLeft->Left), pNode->Height) + 1;

    return pLeft;
}

template<class T>
AvlNode<T>* AvlTree<T>::SingleRotateWithRight(AvlNode<T> *pNode)
{
    AvlNode<T>* pRight = pNode->Right;
    pNode->Right = pRight->Left;
    pRight->Left = pNode;

    pNode->Height = Max(Height(pNode->Left), Height(pNode->Right)) + 1;
    pRight->Height = Max(Height(pRight->Right), pNode->Height) + 1;

    return pRight;
}

template<class T>
AvlNode<T>* AvlTree<T>::DoubleRotateWithLeft(AvlNode<T>* pNode)
{
    pNode->Left = SingleRotateWithRight(pNode->Left);
    return SingleRotateWithLeft(pNode);
}

template<class T>
AvlNode<T>* AvlTree<T>::DoubleRotateWithRight(AvlNode<T>* pNode)
{
    pNode->Right = SingleRotateWithLeft(pNode->Right);
    return SingleRotateWithRight(pNode);
}

template<class T>
AvlNode<T>* AvlTree<T>::InsertPri(AvlNode<T>* pNode, T X)
{
    if (pNode == NULL) {
        pNode = new AvlNode<T>;
        pNode->Element = X;
    } else if (X < pNode->Element) {
        pNode->Left = InsertPri(pNode->Left, X);
        if (Height(pNode->Left) - Height(pNode->Right) > 1) {
            if (X < pNode->Left->Element)
                pNode = SingleRotateWithLeft(pNode);
            else
                pNode = DoubleRotateWithLeft(pNode);
        }
    } else if (X > pNode->Element) {
        pNode->Right = InsertPri(pNode->Right, X);
        if (Height(pNode->Right) - Height(pNode->Left) > 1) {
            if (X > pNode->Right->Element)
                pNode = SingleRotateWithRight(pNode);
            else
                pNode = DoubleRotateWithRight(pNode);
        }
    }
    pNode->Height = Max(Height(pNode->Left), Height(pNode->Right)) + 1;
    return pNode;
}

template<class T>
void AvlTree<T>::Insert(T X)
{ 
    pRoot = InsertPri(pRoot, X);
}

template<class T>
void AvlTree<T>::Draw(AvlNode<T>* pNode, QPoint pt, 
        QPainter* painter, int scale, int height, int radi)
{
    QPoint end;
    QRect rect(QPoint(pt.x()-radi, pt.y()-radi), QPoint(pt.x()+radi, pt.y()+radi));
    QBrush brush(Qt::green, Qt::SolidPattern);
    QString str = QString("%1").arg(pNode->Element, 0, 10);
    QFont font;
    font.setPixelSize(radi-2*str.length());
    if (pNode != NULL) {
        if (pNode->Left != NULL) {
            end.setX(pt.x() - scale);
            end.setY(pt.y() + height);
            painter->setPen(Qt::black);
            painter->drawLine(pt, end);
            Draw(pNode->Left, end, painter, scale/2, height, radi); 
        }
        if (pNode->Right != NULL) {
            end.setX(pt.x() + scale);
            end.setY(pt.y() + height);
            painter->setPen(Qt::black);
            painter->drawLine(pt, end);
            Draw(pNode->Right, end, painter, scale/2, height, radi); 
        }
        painter->setBrush(brush);
        painter->setPen(Qt::black);
        painter->drawEllipse(pt, radi, radi);
        painter->setPen(Qt::red);
        painter->setFont(font);
        painter->drawText(rect, Qt::AlignCenter,  str);
    }
}
#endif

 paint_tree.h

#ifndef PAINTTREE_H
#define PAINTTREE_H

#include <QWidget>
#include "avl_tree.h"

class QPaintEvent;
class QPainter;

class PaintTree : public QWidget
{
    public:
        PaintTree();
        void paintEvent(QPaintEvent *event);
    public:
        AvlTree<int>* pTree;
};
#endif

paint_tree.cpp

#include <QPainter>
#include <QPoint>
#include "paint_tree.h"

PaintTree::PaintTree()
{
    resize(800, 600);
    setWindowTitle(tr("Paint Tree"));
}

void PaintTree::paintEvent(QPaintEvent *)
{
    QSize s = size();
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    pTree->Draw(pTree->pRoot, QPoint(s.width()/2, 25), 
            &painter, s.width()/4, (s.height()-50)/(pTree->pRoot->Height),
            20);
}

最终效果:

再来一张从0-10的

posted @ 2013-05-04 19:51  Dan, Li  阅读(476)  评论(0编辑  收藏  举报