关于二叉树的操作

根据前序遍历和中序遍历构建二叉树

#include <iostream>
#include <vector>
using namespace std;
struct Node
{
    Node* pLeft;
    Node* pRight;
    char chValue;
    Node(char ch) : chValue(ch), pLeft(NULL), pRight(NULL){}
};
void Rebuild(char* pPreOrder, char* pInOrder, int nTreeLen, Node** pRoot)
{
    /*
    pPreOrder:以null为结尾的前序遍历结果的字符串数组
    pInOrder: 以null为结尾的中序遍历结果的字符串数组
    nTreeLen: 树的长度
    pRoot:    返回node**类型,根据前序和中序遍历结构重构树的根节点
    */
    //检查边界条件
    if (pPreOrder == NULL || pInOrder == NULL)
    {
        return;
    }
    //获得前序遍历的第一个节点
    Node* pTemp = new Node(*pPreOrder);
    if (*pRoot == NULL)
    {
        *pRoot = pTemp;
    }
    //如果树的长度是1,那么已经到了最后一个节点
    if (nTreeLen == 1)
    {
        return;
    }
    //寻找子树长度
    char* pOrgInOrder = pInOrder;
    char* pLeftEnd = pInOrder;
    int nTempLen = 0;

    //寻找左子树的结尾
    while (*pPreOrder != *pLeftEnd)
    {
        if (pPreOrder == NULL || pLeftEnd == NULL)
        {
            return;
        }
        nTempLen++;
        //记录临时长度,避免溢出
        if (nTempLen > nTreeLen)
        {
            break;
        }
        pLeftEnd++;
    }

    //寻找左子树的长度
    int nLeftLen = 0;
    nLeftLen = (int)(pLeftEnd - pOrgInOrder);
    //寻找右子树的长度
    int nRightLen = 0;
    nRightLen = nTreeLen - nLeftLen - 1;

    //重建左子树
    if (nLeftLen>0)
    {
        Rebuild(pPreOrder + 1, pInOrder, nLeftLen, &((*pRoot)->pLeft));
    }
    //重建右子树
    if (nRightLen > 0)
    {
        Rebuild(pPreOrder + nLeftLen + 1, pInOrder + nLeftLen + 1, nRightLen, &((*pRoot)->pRight));
    }
}
void PreOrderTraversal(Node* root, vector<char> &data)
{
    /*前序遍历*/
    if (root == NULL)
    {
        return;
    }
    data.push_back(root->chValue);
    PreOrderTraversal(root->pLeft, data);
    PreOrderTraversal(root->pRight, data);
}
void InOrderTraversal(Node* root, vector<char> &data)
{
    /*中序遍历*/
    if (root == NULL)
    {
        return;
    }
    PreOrderTraversal(root->pLeft, data);
    data.push_back(root->chValue);
    PreOrderTraversal(root->pRight, data);
}
void PostOrderTraversal(Node* root, vector<char> &data)
{
    /*后序遍历*/
    if (root == NULL)
    {
        return;
    }
    PostOrderTraversal(root->pLeft, data);
    PostOrderTraversal(root->pRight, data);
    data.push_back(root->chValue);
}
void LayerTraversal(Node* root)
{
    //分层访问二叉树
    vector<Node *> vec;
    if (root == NULL)
    {
        return;
    }
    vec.push_back(root);
    int cur = 0;
    int last = 1;
    while (cur < vec.size())
    {
        last = vec.size();
        while (cur < last)
        {
            cout << vec[cur]->chValue << "  ";
            if (vec[cur]->pLeft != NULL)
            {
                vec.push_back(vec[cur]->pLeft);
            }
            if (vec[cur]->pRight != NULL)
            {
                vec.push_back(vec[cur]->pRight);
            }
            cur++;
        }
        cout << endl;
    }
}
int main(int argc,char* argv[])
{
    const int testLen = 6;
    char szPreOrder[testLen] = { 'a', 'b', 'd', 'c', 'e', 'f' };
    char szInOrder[testLen] = { 'd', 'b', 'a', 'e', 'c', 'f' };
    vector<char> szPostOrder;
    Node* pRoot = NULL;
    Rebuild(szPreOrder, szInOrder, testLen, &pRoot);
    LayerTraversal(pRoot);
    PostOrderTraversal(pRoot, szPostOrder);
    for (auto i : szPostOrder)
    {
        cout << i << "     ";
    }
    cout << endl;
    system("pause");
    return 0;
}

这是一个关于二叉树的大的程序,首先我们要知道二叉树的三种遍历:前序遍历、中序遍历、后序遍历,其中,前序遍历的顺序是根左右;中序遍历的顺序是左根右;后序遍历的顺序是左右根。可以得到简单的函数
前序遍历:

void PreOrderTraversal(Node* root, vector<char> &data)
{
    /*前序遍历*/
    if (root == NULL)
    {
        return;
    }
    data.push_back(root->chValue);
    PreOrderTraversal(root->pLeft, data);
    PreOrderTraversal(root->pRight, data);
}

中序遍历

void InOrderTraversal(Node* root, vector<char> &data)
{
    /*中序遍历*/
    if (root == NULL)
    {
        return;
    }
    PreOrderTraversal(root->pLeft, data);
    data.push_back(root->chValue);
    PreOrderTraversal(root->pRight, data);
}

后序遍历

void PostOrderTraversal(Node* root, vector<char> &data)
{
    /*后序遍历*/
    if (root == NULL)
    {
        return;
    }
    PostOrderTraversal(root->pLeft, data);
    PostOrderTraversal(root->pRight, data);
    data.push_back(root->chValue);
}

二叉树的分层遍历

void LayerTraversal(Node* root)
{
    //分层访问二叉树
    vector<Node *> vec;
    if (root == NULL)
    {
        return;
    }
    vec.push_back(root);
    int cur = 0;
    int last = 1;
    while (cur < vec.size())
    {
        last = vec.size();
        while (cur < last)
        {
            cout << vec[cur]->chValue << "  ";
            if (vec[cur]->pLeft != NULL)
            {
                vec.push_back(vec[cur]->pLeft);
            }
            if (vec[cur]->pRight != NULL)
            {
                vec.push_back(vec[cur]->pRight);
            }
            cur++;
        }
        cout << endl;
    }
}

根据前序遍历和中序遍历得到二叉树:

void Rebuild(char* pPreOrder, char* pInOrder, int nTreeLen, Node** pRoot)
{
    /*
    pPreOrder:以null为结尾的前序遍历结果的字符串数组
    pInOrder: 以null为结尾的中序遍历结果的字符串数组
    nTreeLen: 树的长度
    pRoot:    返回node**类型,根据前序和中序遍历结构重构树的根节点
    */
    //检查边界条件
    if (pPreOrder == NULL || pInOrder == NULL)
    {
        return;
    }
    //获得前序遍历的第一个节点
    Node* pTemp = new Node(*pPreOrder);
    if (*pRoot == NULL)
    {
        *pRoot = pTemp;
    }
    //如果树的长度是1,那么已经到了最后一个节点
    if (nTreeLen == 1)
    {
        return;
    }
    //寻找子树长度
    char* pOrgInOrder = pInOrder;
    char* pLeftEnd = pInOrder;
    int nTempLen = 0;

    //寻找左子树的结尾
    while (*pPreOrder != *pLeftEnd)
    {
        if (pPreOrder == NULL || pLeftEnd == NULL)
        {
            return;
        }
        nTempLen++;
        //记录临时长度,避免溢出
        if (nTempLen > nTreeLen)
        {
            break;
        }
        pLeftEnd++;
    }

    //寻找左子树的长度
    int nLeftLen = 0;
    nLeftLen = (int)(pLeftEnd - pOrgInOrder);
    //寻找右子树的长度
    int nRightLen = 0;
    nRightLen = nTreeLen - nLeftLen - 1;

    //重建左子树
    if (nLeftLen>0)
    {
        Rebuild(pPreOrder + 1, pInOrder, nLeftLen, &((*pRoot)->pLeft));
    }
    //重建右子树
    if (nRightLen > 0)
    {
        Rebuild(pPreOrder + nLeftLen + 1, pInOrder + nLeftLen + 1, nRightLen, &((*pRoot)->pRight));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值