二叉樹的創建和遞歸遍歷

/*!
  二叉樹的學習以及使用
  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++];
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章