二叉树的创建和递归遍历

来源:互联网 发布:linux 启动oracle实例 编辑:程序博客网 时间:2024/06/05 21:49
/*!
  二叉树的学习以及使用
  1.使用字符串构造二叉树
  2.二叉树的遍历
  made by davidsu33
*/
#include <functional>
#include <stack>
#include <queue>

#include <QtDebug>
#include <QString>
#include <QCoreApplication>

using namespace std;
struct BNode
{
    int m_data {-1};
    BNode *m_lchild {Q_NULLPTR}, *m_rchild {Q_NULLPTR};
};

enum class VisitOrder
{
    VO_PreOrder,
    VO_InOrder,
    VO_PostOrder,
    VO_LayerOrder,
};

//typedef void (*BTREE_CALLBACK)();
typedef function<void(BNode*)> BTREE_CALLBACK;

class BTree
{
public:
    explicit BTree(const char *);
    ~BTree();
    void preOrder(BNode *n, BTREE_CALLBACK bc);
    void inOrder(BNode* n, BTREE_CALLBACK bc);
    void postOrder(BNode* n, BTREE_CALLBACK bc);
    void layerOrder(BNode* n, BTREE_CALLBACK bc);
    void dumpNode(BNode *n);
    void dumpNodeByVisitOrder(BNode *n, VisitOrder vo);
    void dumpTree();
    void drawTree();
    BNode* getRoot() const {return m_root;}
private:
    void layerOrder_private(queue<BNode*> n, BTREE_CALLBACK bc);
    void createTree(BNode *&n);
    void releaseNode(BNode* n) ;
    BNode* createNode();
    char feedChar();
private:
    BNode *m_root {Q_NULLPTR};
    char *m_tree;
};


//==================================================
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    /*
     * 如下错误写法,g是叶子节点,没有注明叶子节点的子节点
       constexpr char *t = "abdh##i##e##cf##jg#";
       在编写树的结构字符串的时候保证一点如果节点数是N,那么
       填充的字符数目是N+1,分支数目是N-1,总共是2N,N+1相当于
       是空白的区域,可以利用空白区域来建立二叉索引树。
    */

//    constexpr char *t = "abdh##i##e##cf##jg###";
    constexpr char *t = "ABDH##I##E##CF##G##";
    BTree bt(t);
//    bt.dumpTree();
    bt.dumpNodeByVisitOrder(bt.getRoot(), VisitOrder::VO_PreOrder);
    bt.dumpNodeByVisitOrder(bt.getRoot(), VisitOrder::VO_InOrder);
    bt.dumpNodeByVisitOrder(bt.getRoot(), VisitOrder::VO_PostOrder);
    bt.dumpNodeByVisitOrder(bt.getRoot(), VisitOrder::VO_LayerOrder);
    return 0;
}

BTree::BTree(const char *t)
{
    m_tree = strdup(t);
    createTree(m_root);
    Q_ASSERT(m_root);
}

BTree::~BTree()
{
    postOrder(m_root, bind(&BTree::releaseNode, this, placeholders::_1));
    free(m_tree);
}

void BTree::preOrder(BNode *n, BTREE_CALLBACK bc)
{
    if(!n) return;
    bc(n);
    preOrder(n->m_lchild, bc);
    preOrder(n->m_rchild, bc);
}

void BTree::inOrder(BNode *n, BTREE_CALLBACK bc)
{
    if(!n) return;
    inOrder(n->m_lchild, bc);
    bc(n);
    inOrder(n->m_rchild, bc);
}

void BTree::postOrder(BNode *n, BTREE_CALLBACK bc)
{
    if(!n) return;
    postOrder(n->m_lchild, bc);
    postOrder(n->m_rchild, bc);
    bc(n);
}

void BTree::layerOrder(BNode *n, BTREE_CALLBACK bc)
{
    if(!n) return;
    queue<BNode*> q;
    q.push(n);
    layerOrder_private(q, bc);
}

void BTree::layerOrder_private(queue<BNode*> n, BTREE_CALLBACK bc)
{
   if(n.empty()) return;

   queue<BNode*> nextQ;
   while(!n.empty()){
       BNode* node = n.front();
       bc(node);
       if(node->m_lchild) nextQ.push(node->m_lchild);
       if(node->m_rchild) nextQ.push(node->m_rchild);
       n.pop();
   }

   layerOrder_private(nextQ, bc);
}

void BTree::dumpNode(BNode *n)
{
    qDebug()<<"node-pointer="<<n<<" node-data="<<char(n->m_data);
}

void BTree::dumpNodeByVisitOrder(BNode *n, VisitOrder vo)
{
    if(!n) return;

    function<void (BNode*, BTREE_CALLBACK)> f;
    QString s;
    switch (vo) {
       case VisitOrder::VO_PreOrder:
        {
            s = "前序遍历";
            f = bind(&BTree::preOrder, this, placeholders::_1, placeholders::_2);
            break;
        }
       case VisitOrder::VO_InOrder:
        {
            s = "中序遍历";
            f = bind(&BTree::inOrder, this, placeholders::_1, placeholders::_2);
            break;
        }
       case VisitOrder::VO_PostOrder:
        {
            s = "后序遍历";
            f = bind(&BTree::postOrder, this, placeholders::_1, placeholders::_2);
            break;
        }
       case VisitOrder::VO_LayerOrder:
        {
            s = "按层遍历";
            f = bind(&BTree::layerOrder, this, placeholders::_1, placeholders::_2);
            break;
        }
    }

    qDebug()<<"遍历方式:"<<s;
    f(n, bind(&BTree::dumpNode, this, placeholders::_1));
}

void BTree::dumpTree()
{
    preOrder(m_root, bind(&BTree::dumpNode, this, placeholders::_1));
}

void BTree::drawTree()
{

}

void BTree::createTree(BNode *& n)
{
    char c = feedChar();
    qDebug()<<"c="<<c;
    //*******正确的情况c不可能等于字符串以外的内容*****
    if(c == '#')
    {
       n = Q_NULLPTR;
    }
    else
    {
        n = createNode();
        n->m_data = static_cast<int>(c);
        createTree(n->m_lchild);
        createTree(n->m_rchild);
    }
}

void BTree::releaseNode(BNode *n)
{
    if(n) delete n;
}

BNode *BTree::createNode()
{
   BNode *n = new BNode();
   return n;
}

char BTree::feedChar()
{
   static int index = 0;
   if(strlen(m_tree) <= index)
   {
       return 0;
   }

   return m_tree[index++];
}