二叉树前中后遍历、层次遍历及构造写法(C++)

        二叉树遍历时,递归法代码相对简单,递归法是方便程序员自身读取,其保存函数指针到栈等操作相比非迭代法来说,空间损耗严重。

递归法基本写法如下:

TreeNode * preordertraverse(TreeNode * root)
{
    if(root==NULL)
    {
        return root;
    }
    //前序遍历可以执行的一些计算逻辑,注意是计算而不是判断逻辑
    preordertraverse(root->left);
    //中序遍历可以执行的一些计算逻辑,注意是计算而不是判断逻辑
    preordertraverse(root->right);
    //后序遍历可以执行的一些计算逻辑,注意是计算而不是判断逻辑
    return root;
}

二叉树的数据结构在笔面试也是自己必须手写的,如下:

struct TreeNode
{
    int val;
    TreeNode * left;
    TreeNode * right;
    TreeNode(){};
    TreeNode(int v):val(v),left(NULL),right(NULL){};
    TreeNode(int v,TreeNode * &l,TreeNode * &r):val(v),left(l),right(r);
}

这里面之所以C++结构体可以使用构造函数,是因为C++的结构体本质上与函数没有区别,只是初始时结构体的访问类型为public。

前中后序遍历写法很多,但是统一写法有助于理解:

TreeNode * ordertraverse(TreeNode * root)
{
    if(root == NULL)
    {
        return root;
    }
    stack<TreeNode *> st;
    st.push(root);
    while(!st.empty())
    {
        TreeNode * Node = st.top();
        if(Node!=NULL)
        {
            st.pop()
            st.push(Node);        //后序遍历
            st.push(NULL);        //后序遍历
            if(Node->right)
            {
                st.push(Node->right);
            }
            st.push(Node);        //中序遍历
            st.push(NULL);        //中序遍历
            if(Node->left)
            {
                st.push(Node->left);
            }
            st.push(Node);        //前序遍历
            st.push(NULL);        //前序遍历
        }else
        {
            st.pop();
            //这里一般是定义个变量接收Node的节点,然后进行一定的逻辑
            st.pop();
        }
        
    }
}

从代码可以发现,其实我们仅仅是使用了NULL来进行对节点访问的控制,当然这与栈的特性也有关。

层次遍历则是使用了队列的尺寸特性:

TreeNode* leverordertraverse(TreeNode * root)
{
    if(root==NULL)
    {
        return root;
    }
    queue<TreeNode *> que;
    que.push(root);
    while(!que.empty())
    {
        int size = que.size();
        for(int i = 0;i < size;i++)
        {
            TreeNode * Node = que.front();
            que.pop();
            if(Node->left)
            {
                que.push(root->left);
            }
            if(Node->right)
            {
                que.push(root->right);
            }
        //这里一般进行一些计算,比如每层第一个左叶子等
        }
        
    }

}

构造二叉树只有中序遍历和后序遍历结合、中序遍历和前序遍历结合,两者差距不大,仅是前、后序遍历删除当前父节点的方式有所区别,同时方法有很多,本文介绍常用整形和向量表示方式:

向量表达方式,不常用,且每次递归需要创建vector向量,开销较大。

TreeNode* createBinaryTree(vector<int> &preorder,vector<int> &inorder)
{
    TreeNode * Node = new TreeNode(preorder[0]);
    if(preorder.size()==0)
    {
        return NULL;
    }else if(preorder.size()==1)
    {
        return Node;
    }
    int index = 0;
    for(index;index<inorder.size();index++)
    {
        if(preorder[0]==inorder[index])
        {
            break;
        }
    }
    vector<int> leftinorder(inorder.begin(),inorder.begin()+index);
    vector<int> rightinorder(inorder.begin()+index+1,inorder.end());
    vector<int> preorder_new(preorder.begin()+1,preorder.end());
    Node->left = createBinaryTree(preorder_new,leftinorder);
    Node->right = createBinaryTree(preorder_new,rightinorder);
    return Node;
}

整形表示方式:

TreeNode * createBinaryTree(vector<int> preorder,int preleft,int preright,vector<int> inorder,int inorderleft,int inorderright)
{
    TreeNode * Node = new TreeNode[preorder[preleft]];
    if(preright == preleft)
    {
        return NULL;
    }else if
    {
        return Node;
    }
    int index = 0;
    for(;index<inorder.size();index++)
    {
        if(preorder[preleft]==inorder[index])
        {
            break;
        }
    }
    inorderleft_left = inorderleft;
    inorderleft_right = index;
    inorderright_left = index + 1;
    inorderright_right = inorderright;
    preorderleft_left = preleft + 1;
    preorderleft_right = preleft + 1 + (inorderleft_right-inorderleft_left);
    preorderright_left = preleft + 1 + (inorderleft_right-inorderleft_left);
    preorderright_right = preright;
    Node->left = createBinaryTree(preorder,preorderleft_left,preorderleft_right,inorder,inorderleft_left,inorderleft_right);
    Node->right = createBinaryTree(preorder,preorderright_left,preorderright_right,inorder,inorderright_left,inorderright_right);
    return Node;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值