zoukankan      html  css  js  c++  java
  • 二叉树的生成

    1. 通过前序和中序生成

      中序:leftTree, root, rightTree

      前序:root, leftTree, rightTree

      思路:很显然,通过前序序列,我们可以很容易知道树的root,然后通过查找中序序列中相应的root位置,便可以确定该root的左右子树。然后借助递归思想,对左右子树进行相同的操作,便能够构造出这棵树。为此,我们需要确定几个位置,即前序遍历的根节点位置rootPos,其左子树的根节点位置和右节点位置;以及对应的中序遍历序列中树的左右边界,以及根节点的位置。

    先根据递归思想,写出递归方程:

     1 Bitree *buildTree(vector<int> preOrder, int preRootPos, vector<int> inOrder, int inOrderLeftBound, int inOrderRightBound){
     2   if(inOrderLeftBound > inOrderRightBound){
     3     return nullptr;
     4   }
     5   Bitree *root = new Bitree(preOrder[preRootPos]);
     6   int inOrderRootPos = inOrder.find();
     7   root->left = buildTree(preOrder, leftTreeRootPos, inOrder, inOrderLeftBound, inOrderRootPos-1);
     8   root->right = buildTree(preOrder, rightTreeRootPos, inOrder, inOrderRootPos+1, inOrderRightBound);
     9   return root;
    10 }

    可知,我们需要确定leftTreeRootPOS、rightTreeRootPOS来正确定位左右子树在前序序列中的位置,以完成递归算法的正确分割。为了确定这两个值,先画图:

      其中,leftTreeRootPos很好确定,即preRootPos+1;对rightTreeRootPos,则需要先知道左子树的长度,为此,可使用图中中序序列的inOrderRoot-leftBound求解,即rightTreeRootPos=preRoot+(inOrderRoot-leftBound)+1。到此,递归便能正常进行下去。

    由此,算法为

     1 Bitree *buildTree(vector<int> preOrder, int preRootPos, vector<int> inOrder, int inOrderLeftBound, int inOrderRightBound){
     2   if(inOrderLeftBound > inOrderRightBound){
     3     return nullptr;
     4   }
     5   Bitree *root = new Bitree(preOrder[preRootPos]);
     6   int inOrderRootPos = find(inOrder.begin(), inOrder.end(), root->val)-inOrder.begin();//find has to be used like this
     7   root->left = buildTree(preOrder, preRootPos+1, inOrder, inOrderLeftBound, inOrderRootPos-1);
     8   root->right = buildTree(preOrder, preRootPos+(inOrderRootPos-inOrderLeftBound)+1, inOrder, inOrderRootPos+1, inOrderRightBound);
     9   return root;
    10 }

    注意:上图中的省略号不能省略,它反映了递归过程中的一般情况。在递归过程中,一棵小子树的序列在前序和中序序列中并非是左边界对其(及前序中的root位置和中序中的leftBound位置相同)的,若没有省略号,那么容易造成左对齐的误解,对后来左右子树的在前序序列中的位置产生误判。

    2. 通过中序和后续生成

      中序:leftTree, root, rigthTree

      后续:leftTree, rightTree, root

      和上面算法思想相似,只是注意左子树和右子树中的root在后序后列中的位置就好了。直接上代码:

     1 Bitree *buildTree(vector<int> postOrder, int postRootPos, vector<int> inOrder, int inOrderLeftBound, int inOrderRightBound){
     2   if(inOrderLeftBound > inOrderRightBound){
     3     return nullptr;
     4   }
     5   Bitree *root = new Bitree(preOrder[postRootPos]);
     6   int inOrderRootPos = find(inOrder.begin(), inOrder.end())-inOrder.begin();
     7   root->left = buildTree(postOrder, postRootPos-(inOrderRootPos-inOrderLeftBound)-1, inOrder, inOrderLeftBound, inOrderRootPos-1);
     8   root->right = buildTree(preOrder, postRootPos-1, inOrder, inOrderRootPos+1, inOrderRightBound);
     9   return root;
    10 }

     当然,最后提醒一句,生成了勿忘销毁。

  • 相关阅读:
    3-剑指Offer: 连续子数组的最大和
    2-剑指offer: 最小的K个数
    1-剑指offer: 数组中出现次数超过一半的数字
    django中运行定时任务脚本
    django+sqlite进行web开发(二)
    django+sqlite3进行web开发(一)
    TL-WDN5200H无线usb网卡在Linux上的使用
    比较好用的C++11在线编译器
    MarkDown中如何加入上标和下标
    3. 卷积神经网络(CNN)
  • 原文地址:https://www.cnblogs.com/wuiCoding/p/6671057.html
Copyright © 2011-2022 走看看