筆記九:二叉樹的創建、遞歸與非遞歸版前序、中序、後序查找、樹高和節點判斷

代碼:

#include<iostream>
#include<vector>
#include<stack>
using namespace std;


template<typename T>
struct binaryTreeNode{
    T element;
    binaryTreeNode<T>  *leftChild;      //左子樹
    binaryTreeNode<T>  *rightChild;     //右子樹
    binaryTreeNode() {
        leftChild = rightChild = NULL;
    }
    binaryTreeNode(const T& theElement)
    {
        element = theElement;
        leftChild = rightChild = NULL;
    }
    binaryTreeNode(const T&  theElement, binaryTreeNode *theLeftChild, binaryTreeNode *theRightChild)
    {
        element(theElement);
        leftChild = theLeftChild;
        rightChild = theRightChild;
    }
};

template <typename T>
class binaryTree{
public:
    virtual ~binaryTree() {}
    virtual bool empty() const = 0;
    virtual int size() const = 0;
    virtual void visit(T *) const = 0;
    virtual void InputBinaryNode() = 0;
    virtual void preCreateBinaryTree(T *&) = 0;

    /*virtual void preOrder(binaryTreeNode<T> *node) = 0;
    virtual void inOrder(binaryTreeNode<T> *node) = 0;
    virtual void postOrder(binaryTreeNode<T> *node) = 0;

    virtual void Iter_preOrder(binaryTreeNode<T> *node) = 0;
    virtual void Iter_inOrder(binaryTreeNode<T> *node) = 0;
    virtual void Iter_postOrder(binaryTreeNode<T> *node) = 0;*/
    virtual void preOrder(T *) = 0;
    virtual void inOrder(T *) = 0;
    virtual void postOrder(T *) = 0;

    virtual void Iter_preOrder(T *) = 0;
    virtual void Iter_inOrder(T *) = 0;
    virtual void Iter_postOrder(T *) = 0;


};

template<typename E>
class linkedBinaryTree : public binaryTree<binaryTreeNode<E> >
{
public:
    linkedBinaryTree(){ root = NULL; treeSize = 0; }
    ~linkedBinaryTree() {};
    bool empty() const { return treeSize == 0; }
    int size() const { return treeSize; }
    void visit(binaryTreeNode<E> *node) const;
    void InputBinaryNode();
    void preCreateBinaryTree(binaryTreeNode<E> *&node);
    int height(binaryTreeNode<E> *&node) const;

    void preOrder(binaryTreeNode<E> *node);
    void inOrder(binaryTreeNode<E> *node);
    void postOrder(binaryTreeNode<E> *node);

    void Iter_preOrder(binaryTreeNode<E> *node);
    void Iter_inOrder(binaryTreeNode<E> *node);
    void Iter_postOrder(binaryTreeNode<E> *node);


private:
    binaryTreeNode<E> *root;
    int treeSize;
    vector<E> vecNode;
};

template<typename E>
void linkedBinaryTree<E>::visit(binaryTreeNode<E> *node) const
{
    //訪問節點*node, 僅輸出element
    cout << node->element << " ";
}

template<typename E>
void linkedBinaryTree<E>::InputBinaryNode()
{
    E elem;
    cout << "!!!注意:(1)#表示空節點;(2)請在輸入的字符串末尾加0,作爲輸入結束的標誌!" << endl;
    while (cin >> elem && elem != '0')
    {
        vecNode.push_back(elem);
    }
}

template<typename E>
void linkedBinaryTree<E>::preCreateBinaryTree(binaryTreeNode<E> *&node)
{
    vector<E>::iterator it = vecNode.begin();
    if (it != vecNode.end())
    {
        if (*it == '#')
        {
            node = NULL;
            vecNode.erase(it);
        }
        else{
            node = new binaryTreeNode<E>(*it);  //生成根節點
            treeSize++;
            vecNode.erase(it);
            preCreateBinaryTree(node->leftChild);   //構造左子樹
            preCreateBinaryTree(node->rightChild);  //構造右子樹
        }
    }
    else{
        node = NULL;
    }
}

template<typename E>
int linkedBinaryTree<E>::height(binaryTreeNode<E> *&node) const
{
    if (!node)
    {
        return 0;
    }

    int hl = height(node->leftChild);   //左子樹的高
    int hr = height(node->rightChild);  //右子樹的高
    if (hl > hr)
    {
        return ++hl;
    }
    else{
        return ++hr;
    }

}

template<typename E>
void linkedBinaryTree<E>::preOrder(binaryTreeNode<E> *node)
{
    //根節點——左子樹——右子樹
    if (node)
    {
        visit(node);
        preOrder(node->leftChild);
        preOrder(node->rightChild);
    }

}

template<typename E>
void linkedBinaryTree<E>::inOrder(binaryTreeNode<E> *node)
{
    //左子樹——根節點——右子樹 
    if (node)
    {
        inOrder(node->leftChild);
        visit(node);
        inOrder(node->rightChild);
    }

}

template<typename E>
void linkedBinaryTree<E>::postOrder(binaryTreeNode<E> *node)
{
    //左子樹——右子樹——根節點
    if (node)
    {
        postOrder(node->leftChild);
        postOrder(node->rightChild);
        visit(node);
    }

}

template<typename E>
void linkedBinaryTree<E>::Iter_preOrder(binaryTreeNode<E> *node)
{
    stack<binaryTreeNode<E>* > stk;     //存儲樹節點
    binaryTreeNode<E> * currNode = node;
    while (currNode || (!stk.empty()))
    {
        if (currNode)
        {
            visit(currNode);            //訪問根節點
            stk.push(currNode);
            currNode = currNode->leftChild; //遍歷左子樹
        }
        else{
            currNode = stk.top();       //節點入棧前已被訪問,故無需再次訪問
            stk.pop();
            currNode = currNode->rightChild;
        }
    }

}

template<typename E>
void linkedBinaryTree<E>::Iter_inOrder(binaryTreeNode<E> *node)
{
    stack<binaryTreeNode<E>* > stk;
    binaryTreeNode<E>* currNode = node;
    while (currNode || (!stk.empty()))
    {
        if (currNode)
        {
            stk.push(currNode);     //先將左子樹全部壓入棧
            currNode = currNode->leftChild;
        }
        else{
            currNode = stk.top();
            stk.pop();
            visit(currNode);        //訪問根節點
            currNode = currNode->rightChild;
        }
    }
}

template<typename E>
void linkedBinaryTree<E>::Iter_postOrder(binaryTreeNode<E> *node)
{
    stack<binaryTreeNode<E>* > stk;
    binaryTreeNode<E>* currNode = node, *rightNode = node;
    while (currNode || (!stk.empty()))
    {
        if (currNode)
        {
            stk.push(currNode);     //遍歷左子樹
            currNode = currNode->leftChild;
        }
        else{
            currNode = stk.top();
            currNode = currNode->rightChild;    //遍歷右子樹
            if (!currNode)          //此時棧頂元素的左孩子、右孩子均爲空,即爲葉子節點
            {
                rightNode = stk.top();
                stk.pop();
                visit(rightNode);   //訪問葉子節點
                //若剛被訪問的葉子節點是此時棧頂元素的右孩子,則說明左、右子樹均被遍歷完
                //循環的目的是爲了找到最終的父結點,當前所有已訪問的節點是作爲其左子樹的節點而存在
                while ((!stk.empty()) && (stk.top()->rightChild == rightNode))
                {
                    rightNode = stk.top();  //由於該節點的右節點已被訪問,說明完成了左右子樹的遍歷
                    stk.pop();
                    visit(rightNode);       //葉子節點已經被訪問,則最後訪問根節點
                }
                if (!stk.empty())           //剛被訪問的是此時棧頂元素的左孩子,則右孩子還未入棧
                {
                    currNode = stk.top();
                    currNode = currNode->rightChild;
                }
            }
        }//else
    }
}

int main(int argc, char* argv[])
{
    linkedBinaryTree<char> LBT;
    binaryTreeNode<char>* root;
    LBT.InputBinaryNode();
    LBT.preCreateBinaryTree(root);
    cout << "二叉樹的總節點數爲:" << LBT.size() << endl;
    cout << "二叉樹的高度爲:"<< LBT.height(root) << endl;

    cout << "\n前序遍歷二叉樹(遞歸):" << endl;
    LBT.preOrder(root);
    cout << "\n中序遍歷二叉樹(遞歸):" << endl;
    LBT.inOrder(root);
    cout << "\n後序遍歷二叉樹(遞歸):" << endl;
    LBT.postOrder(root);

    cout << "\n\n前序遍歷二叉樹(非遞歸):" << endl;
    LBT.Iter_preOrder(root);
    cout << "\n中序遍歷二叉樹(非遞歸):" << endl;
    LBT.Iter_inOrder(root);
    cout << "\n後序遍歷二叉樹(非遞歸):" << endl;
    LBT.Iter_postOrder(root);

    return 0;
}

注:中間註釋代碼部分會造成,純虛函數沒有強制替代項的錯誤。

結果 :
這裏寫圖片描述

注:上述代碼是在我的舊文基礎上改進的http://blog.csdn.net/u014033518/article/details/38844583

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