C++實現二叉樹的相應操做

1. 二叉樹的遍歷:先序(遞歸、非遞歸),中序(遞歸、非遞歸),後序(遞歸、非遞歸)。node

#include <iostream>
#include <string>
#include <stack>

using namespace std;

struct BiTree
{
    int NodeData = 0;
    struct BiTree *pLeft = nullptr;
    struct BiTree *pRight = nullptr;
};

//遍歷二叉樹:
void show(struct BiTree *pRoot, int n)
{
    if (pRoot == nullptr)
    {
        return;
    }
    else
    {
        show(pRoot->pLeft, n + 1);

        for (int i = 0; i < n; i++)
            cout << "   ";
        cout << pRoot->NodeData << endl;

        show(pRoot->pRight, n + 1);
    }

}
//--------------------------------------------------------------
//遞歸中序遍歷:
void RecMidTravel(struct BiTree *pRoot)
{
    if (pRoot == nullptr)
    {
        return;
    }
    else  
    {
        if (pRoot->pLeft != nullptr)
        {
            RecMidTravel(pRoot->pLeft);
        }

        cout << pRoot->NodeData << endl;

        if (pRoot->pRight != nullptr)
        {
            RecMidTravel(pRoot->pRight);
        }
    }
} 

//中序非遞歸
void MidTravel(struct BiTree *pRoot)
{
    if (pRoot == nullptr)
    {
        return;
    }
    else
    {

        struct BiTree *pcur = pRoot;
        stack<BiTree *> mystack;

        while (!mystack.empty() || pcur != nullptr)
        {
            while (pcur != nullptr)
            {
                mystack.push(pcur);
                pcur = pcur->pLeft;    //左節點所有進棧
            }

            if (!mystack.empty())
            {
                pcur = mystack.top();
                cout << pcur->NodeData << endl;
                mystack.pop();                    //出棧
                pcur = pcur->pRight;            //右節點
            }
        }

    }
}
//--------------------------------------------------------------
//遞歸先序遍歷:
void RecPreTravel(struct BiTree *pRoot)
{
    if (pRoot == nullptr)
    {
        return;
    }
    else
    {
        cout << pRoot->NodeData << endl;

        if (pRoot->pLeft != nullptr)
        {
            RecPreTravel(pRoot->pLeft);
        }

        if (pRoot->pRight != nullptr)
        {
            RecPreTravel(pRoot->pRight);
        }
    }
}
//先序非遞歸
void PreTravel(struct BiTree *pRoot)
{
    if (pRoot == nullptr)
    {
        return;
    }
    else
    {

        struct BiTree *pcur = pRoot;
        stack<BiTree *> mystack;

        while (!mystack.empty() || pcur != nullptr)
        {
            while (pcur != nullptr)
            {
                cout << pcur->NodeData << endl;

                mystack.push(pcur);
                pcur = pcur->pLeft;    //左節點所有進棧
            }

            if (!mystack.empty())
            {
                pcur = mystack.top();
                
                mystack.pop();                    //出棧
                pcur = pcur->pRight;            //右節點
            }
        }

    }
}

//--------------------------------------------------------------
//遞歸後序遍歷:
void RecPostTravel(struct BiTree *pRoot)
{
    if (pRoot == nullptr)
    {
        return;
    }
    else
    {
        if (pRoot->pLeft != nullptr)
        {
            RecPostTravel(pRoot->pLeft);
        }

        if (pRoot->pRight != nullptr)
        {
            RecPostTravel(pRoot->pRight);
        }

        cout << pRoot->NodeData << endl;
    }
}
//後序非遞歸
struct nosame    //標識節點是否反覆出現
{
    struct BiTree *pnode;
    bool issame;
};

void PostTravel(struct BiTree *pRoot)
{
    if (pRoot == nullptr)
    {
        return;
    }
    else
    {

        struct BiTree *pcur = pRoot;
        stack<nosame *> mystack;    //避免重複出現
        nosame *ptemp;

        while (!mystack.empty() || pcur != nullptr)
        {
            while (pcur != nullptr)
            {
                nosame *ptr = new nosame;
                ptr->issame = true;
                ptr->pnode = pcur;//節點


                //cout << pcur->NodeData << endl;

                mystack.push(ptr);
                pcur = pcur->pLeft;    //左節點所有進棧
            }

            if (!mystack.empty())
            {
                ptemp = mystack.top();
                mystack.pop();                    //出棧

                if (ptemp->issame == true)        //第一次出現
                {
                    ptemp->issame = false;
                    mystack.push(ptemp);
                    pcur = ptemp->pnode->pRight;//跳到右節點
                }
                else
                {
                    cout << ptemp->pnode->NodeData << endl;//打印數據
                    pcur = nullptr;
                }

            }
        }

    }
}


void main()
{
    struct BiTree *pRoot;

    struct BiTree node1;
    struct BiTree node2;
    struct BiTree node3;
    struct BiTree node4;
    struct BiTree node5;
    struct BiTree node6;
    struct BiTree node7;
    struct BiTree node8;

    node1.NodeData = 1;
    node2.NodeData = 2;
    node3.NodeData = 3;
    node4.NodeData = 4;
    node5.NodeData = 5;
    node6.NodeData = 6;
    node7.NodeData = 7;
    node8.NodeData = 8;

    pRoot = &node1;
    node1.pLeft = &node2;
    node1.pRight = &node3;

    node2.pLeft = &node4;
    node2.pRight = &node5;

    node3.pLeft = &node6;
    node3.pRight = &node7;

    node4.pLeft = &node8;

    show(pRoot, 1);

    cout << "中序遞歸:" << endl;
    RecMidTravel(pRoot);    //中序遞歸
    cout << "中序非遞歸:" << endl;
    MidTravel(pRoot);        //中序非遞歸

    cout << "先序遞歸:" << endl;
    RecPreTravel(pRoot);
    cout << "先序非遞歸:" << endl;
    PreTravel(pRoot);        //先序非遞歸

    cout << "後序遞歸:" << endl;
    RecPostTravel(pRoot);
    cout << "後序非遞歸:" << endl;
    PostTravel(pRoot);        //後序非遞歸


    cin.get();
}

     

 2. 獲取二叉樹節點個數:ios

//遞歸獲取二叉樹節點個數
int getNodeCount(BiTree *pRoot)
{
    if (pRoot == nullptr)
    {
        return 0;
    }
    else
    {
        return getNodeCount(pRoot->pLeft) + getNodeCount(pRoot->pRight) + 1;
    }
}

    

3. 判斷二叉樹是否爲徹底二叉樹:spa

//判斷二叉樹是否爲徹底二叉樹
bool isCompleteBiTree(BiTree *pRoot)
{
    if (pRoot == nullptr)
    {
        return false;
    }
    else
    {
        queue<BiTree *> myq;
        myq.push(pRoot);
        bool mustHaveChild = false;    //必須有子節點
        bool result = true;            //結果

        while (!myq.empty())
        {
            BiTree *node = myq.front();//頭結點
            myq.pop();                    //出隊

            if (mustHaveChild)    //必須有孩子
            {
                if (node->pLeft != nullptr || node->pRight != nullptr)
                {
                    result = false;
                    break;

                }

            } 
            else
            {
                if (node->pLeft != nullptr && node->pRight != nullptr)
                {
                    myq.push(node->pLeft);
                    myq.push(node->pRight);
                }
                else if (node->pLeft != nullptr && node->pRight == nullptr)
                {
                    mustHaveChild = true;
                    myq.push(node->pLeft);
                }
                else if (node->pLeft == nullptr && node->pRight != nullptr)
                {
                    result = false;
                    break;
                }
                else
                {
                    mustHaveChild = true;
                }
            }
        }

        return result;
    }
}

    

4. 求二叉樹兩個節點的最小公共祖先:3d

//求二叉樹兩個節點的最小公共祖先
bool findnode(BiTree *pRoot, BiTree *node)    //判斷節點是否在某個節點下
{
    if (pRoot == nullptr || node == nullptr)
    {
        return false;
    }
    if (pRoot == node)
    {
        return true;
    }

    bool isfind = findnode(pRoot->pLeft, node);
    if (!isfind)
    {
        isfind = findnode(pRoot->pRight, node);
    }

    return isfind;
}

BiTree *getParent(BiTree *pRoot, BiTree *pChild1, BiTree *pChild2)
{
    if (pRoot == pChild1 || pRoot == pChild2)
    {
        return pRoot;
    }

    if (findnode(pRoot->pLeft, pChild1))
    {
        if (findnode(pRoot->pRight, pChild2))
        {
            return pRoot;
        } 
        else
        {
            return getParent(pRoot->pLeft, pChild1, pChild2);
        }
    } 
    else
    {
        if (findnode(pRoot->pLeft, pChild2))
        {
            return pRoot;
        }
        else
        {
            return getParent(pRoot->pRight, pChild1, pChild2);
        }
    }
}

    

5. 二叉樹的翻轉:code

//二叉樹的翻轉
BiTree *revBiTree(BiTree *pRoot)
{
    if (pRoot==nullptr)
    {
        return nullptr;
    }

    BiTree *leftp = revBiTree(pRoot->pLeft);
    BiTree *rightp = revBiTree(pRoot->pRight);

    pRoot->pLeft = rightp;
    pRoot->pRight = leftp;    //交換

    return pRoot;
}

    

6. 求二叉樹第k層的節點個數:blog

//求二叉樹第K層的節點個數
int getLevelConut(BiTree *pRoot, int k)
{
    if (pRoot == nullptr || k < 1)
    {
        return 0;
    }
    if (k == 1)
    {
        return 1;
    }
    else
    {
        int left = getLevelConut(pRoot->pLeft, k - 1);
        int right = getLevelConut(pRoot->pRight, k - 1);

        return (left + right);
    }
}

    

7. 求二叉樹中節點的最大距離(相距最遠的兩個節點之間的距離):遞歸

//求二叉樹中節點的最大距離
struct res    //用以遞歸間傳遞距離
{
    int maxDistance = 0;
    int maxDepth = 0;
};

res getMaxDistance(BiTree *pRoot)
{
    if (pRoot == nullptr)
    {
        res r1;
        return r1;
    }

    res leftr = getMaxDistance(pRoot->pLeft);
    res rightr = getMaxDistance(pRoot->pRight);

    res last;    //最終結果
    last.maxDepth = max(leftr.maxDepth + 1, rightr.maxDepth + 1);//求最大深度
    last.maxDistance = max(max(leftr.maxDistance, rightr.maxDistance), leftr.maxDepth + rightr.maxDepth + 2);//求最大距離

    return last;
}

    

8. 判斷二叉樹是否爲平衡二叉樹:ci

//判斷二叉樹是否爲平衡二叉樹:
bool isAVL(BiTree *pRoot, int & depth)    //須要引用來傳遞數據
{
    if (pRoot == nullptr)
    {
        depth = 0;
        return true;
    }

    int leftdepth = 0;
    int rightdepth = 0;
    bool left = isAVL(pRoot->pLeft, leftdepth);
    bool right = isAVL(pRoot->pRight, rightdepth);

    if (left && right && abs(leftdepth - rightdepth) <= 1)
    {
        depth = 1 + (leftdepth > rightdepth ? leftdepth : rightdepth);//深度
        return true;
    }
    else
    {
        return false;
    }
}

        

相關文章
相關標籤/搜索