zoukankan      html  css  js  c++  java
  • 二叉树

    一、二叉树简介

      二叉树节点定义为:

    1 struct TreeNode 
    2 {
    3     int val;
    4     TreeNode *left;
    5     TreeNode *right;
    6     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
    7 };

    有时需要增加parent等其他信息。

    二叉树的创建采用输入满二叉树数组的形式,例如 A = [1, -2, -3, 1, 3, 2, NIL, -1], 表示为:

            1

         -2      -3

        1  3    2

      -1

    由数组A构建一颗二叉树:

     1 TreeNode* create_node(int x)
     2 {
     3     if (x == NIL) /* means null */
     4         return NULL;
     5     else
     6         return new TreeNode(x);
     7 }
     8 
     9 TreeNode* btree_create(TreeNode *root, int va[], int n)
    10 {
    11     TreeNode *nt = NULL, *pt = NULL;
    12     queue<TreeNode *> qtree;
    13     int i = 1;
    14     
    15     root = new TreeNode(va[0]);
    16     qtree.push(root);
    17     while (qtree.size() > 0)
    18     {
    19         pt = qtree.front();
    20         qtree.pop();
    21         if (pt == NULL)
    22             continue;        
    23         /* create left node */
    24         if (i >= n)
    25             break;
    26         pt->left = create_node(va[i]);
    27         i++;
    28         qtree.push(pt->left);        
    29         /* create right node */
    30         if (i >= n)
    31             break;
    32         pt->right = create_node(va[i]);
    33         i++;
    34         qtree.push(pt->right);
    35     }
    36     return root;
    37 }

    二、二叉树基本操作

    1、min/max depth

    int minDepth(TreeNode *root) 
        {
            if (root == NULL)
                return 0;
            int ml = minDepth(root->left);
            int mr = minDepth(root->right);
            
            if (ml == 0)        /* the min depth should contain leaf, not only the root node. */
                return (mr + 1);
            if (mr == 0)
                return (ml + 1);
                
            return min(ml, mr) + 1;
        }
    
    int maxDepth(TreeNode *root) 
        {
            if (root == NULL)
                return 0;
                
            return max(maxDepth(root->left), maxDepth(root->right)) + 1;
        }

    2、二叉树广度优先/深度优先遍历

    2.1、BFS

    二叉树的bfs记为层次遍历,使用队列做辅助,如下:

    a)将root放入队列queue

    b)queue不为空,取出队列元素node,并访问

    c)node左右节点入队,重复b

     1 vector<int> btree_bfs(TreeNode* root)
     2 {
     3     vector<int> tree_nodes;
     4     queue<TreeNode*> qtree;
     5     TreeNode* pt = root;
     6     
     7     if (pt == NULL)
     8         return tree_nodes;
     9         
    10     qtree.push(pt);
    11     while (!qtree.empty())
    12     {
    13         pt = qtree.front();
    14         qtree.pop();
    15         tree_nodes.push_back(pt->val);
    16         
    17         if (pt->left != NULL)
    18             qtree.push(pt->left);
    19         if (pt->right != NULL)
    20             qtree.push(pt->right);
    21     }
    22     
    23     return tree_nodes;
    24 }

    2.2 DFS

    二叉树深度优先遍历,不妨以左节点优先,即左子树存在则先查询左节点,如下:

    a) 当前节点不为空,访问之。并将右节点压栈,继续访问左节点。

    b)节点为空,则从栈中取出node,继续a,直至访问完。

     1 vector<int> btree_dfs(TreeNode* root)
     2 {
     3     vector<int> tree_nodes;
     4     stack<TreeNode*> stree;
     5     TreeNode* pcur = root;
     6     
     7     if (pcur == NULL)
     8         return tree_nodes;
     9     
    10     while (!stree.empty() || (pcur != NULL))
    11     {
    12         if (pcur != NULL)
    13         {
    14             tree_nodes.push_back(pcur->val); // visit current
    15             if (pcur->right != NULL)
    16                 stree.push(pcur->right);
    17             pcur = pcur->left;
    18         }
    19         else
    20         {
    21             pcur = stree.top();
    22             stree.pop();
    23         }
    24     }
    25     
    26     return tree_nodes;
    27 }

    3、pre/in/post order traverse

    这三种方式遍历二叉树,递归遍历比较简单,非递归遍历则需要借助queue/stack。

    3.1、preorder

    1 void preorder(TreeNode *root, vector <int> &ret)
    2     {
    3         if (root == NULL)
    4             return;
    5         ret.push_back(root->val);
    6         preorder(root->left, ret);
    7         preorder(root->right, ret);
    8     }

    preorder迭代形式和dfs完全一致。

    3.2、inorder

    void inorder(TreeNode *root, vector <int> &ret)
        {
            if (root == NULL)
                return;
            inorder(root->left, ret);
            ret.push_back(root->val);
            inorder(root->right, ret);
        }

    迭代方式遍历:

    a)当前节点不为空,则压栈并访问左子树。

    b)否则,出栈并访问元素,再访问右子树,重复a。

     1 vector<int> inorderTraversal(TreeNode *root) 
     2     {
     3         vector<int> tree_nodes;
     4         stack<TreeNode*> stree;
     5         TreeNode* pcur = root;
     6             
     7         while (!stree.empty() || (pcur != NULL))
     8         {
     9             if (pcur != NULL)
    10             {
    11                 stree.push(pcur);
    12                 pcur = pcur->left;  //left
    13             }
    14             else
    15             {
    16                 pcur = stree.top(); 
    17                 stree.pop();
    18                 tree_nodes.push_back(pcur->val); 
    19                 pcur = pcur->right; //right
    20             }
    21         }
    22         return tree_nodes;
    23     }

    3.3 post order

    void inorder(TreeNode *root, vector <int> &ret)
        {
            if (root == NULL)
                return;
            inorder(root->left, ret);
            inorder(root->right, ret);
            ret.push_back(root->val);
        }

    后序遍历非递归形式:

    a)当前节点pcur不为空,节点入栈,访问左节点

    b)否则,获取栈顶节点peek,如果peek->right不为空且不是last_vist_node, pcur变为peek->right

    c)否则last_vist_node为栈顶元素,并访问last_vist_node,继续a)

     1 vector<int> postorderTraversal(TreeNode *root) 
     2     {
     3         vector<int> tree_nodes;
     4         stack<TreeNode *> stree;
     5         TreeNode *current = root, *last_visit_node = NULL, *peek_node = NULL;
     6         
     7         while (!stree.empty() || (current != NULL))
     8         {
     9             if (current != NULL)
    10             {
    11                 stree.push(current);
    12                 current = current->left;
    13             }
    14             else
    15             {
    16                 peek_node = stree.top();
    17                 if ((peek_node->right != NULL) && (peek_node->right != last_visit_node))
    18                 { // peek's right child exists and it's not come from last child
    19                     current = peek_node->right;
    20                 }
    21                 else
    22                 {
    23                     last_visit_node = peek_node;
    24                     stree.pop();
    25                     tree_nodes.push_back(last_visit_node->val);
    26                 }
    27             }
    28         }
    29         
    30         return tree_nodes;
    31     }
  • 相关阅读:
    BZOJ3252攻略——长链剖分+贪心
    BZOJ3522[Poi2014]Hotel——树形DP
    BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector
    BZOJ3626[LNOI2014]LCA——树链剖分+线段树
    BZOJ2157旅游——树链剖分+线段树
    BZOJ3531[Sdoi2014]旅行——树链剖分+线段树
    BZOJ2243[SDOI2011]染色——树链剖分+线段树
    zookeeper(1)初识zookeeper
    任督二脉
    RPC框架之RMI
  • 原文地址:https://www.cnblogs.com/ym65536/p/4115904.html
Copyright © 2011-2022 走看看