二叉树面试题

1.根据前序遍历序列和中序遍历序列求一棵二叉树。

那么我们就是很容易的写出完整代码。

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. template<typename T>  
  2. struct BinaryTreeNode  
  3. {  
  4.     T _data;  
  5.     BinaryTreeNode<T>* _left;  
  6.     BinaryTreeNode<T>* _right;  
  7.     BinaryTreeNode(const T& data = T())  
  8.        :_data(data)  
  9.        ,_left(NULL)  
  10.        ,_right(NULL)  
  11.     {}  
  12. };  
  13. template<typename T>  
  14. class RebuildTree  
  15. {  
  16.    typedef BinaryTreeNode<T> Node;  
  17. public:  
  18.     RebuildTree(T* pre,T* in,size_t size)  
  19.     {  
  20.        assert(pre && in);  
  21.        _root = new Node(pre[0]);  
  22.        _CreateTree(pre,in,size,_root);  
  23.     }  
  24.     void PreOrder()  
  25.     {  
  26.        _PreOrder(_root);  
  27.     }  
  28. protected:  
  29.     void _CreateTree(T* pre,T* in,size_t size,Node*& root)  
  30.     {  
  31.        if(size <= 0)  
  32.            return;  
  33.        if(root == NULL)  
  34.            root = new Node(pre[0]);  
  35.        int index = 0;  
  36.        for(index = 0; index < size; ++index)  
  37.        {  
  38.            if(pre[0] == in[index])//根节点  
  39.                break;  
  40.        }  
  41.        int leftNum = index;  
  42.        int rightNum = size - leftNum - 1;  
  43.         _CreateTree(pre+1,in,leftNum,root->_left);  
  44.        _CreateTree(pre+index+1,in + index + 1,rightNum,root->_right);  
  45.     }  
  46.     void _PreOrder(Node* root)  
  47.     {  
  48.        if(NULL == root)  
  49.            return;  
  50.        cout<<root->_data<<" ";  
  51.        _PreOrder(root->_left);  
  52.        _PreOrder(root->_right);  
  53.     }  
  54. private:  
  55.     Node* _root;  
  56. };  
  57. void TestRebuildTree()  
  58. {  
  59.     int pre[] = {1,2,3,4,5,6};  
  60.     int in[] = {3,2,4,1,6,5};  
  61.     RebuildTree<int> rt(pre,in,6);  
  62.     rt.PreOrder();  

  1. }  
  2. 2.判断一棵二叉树是否是完全二叉树。
  3. 思路:层序遍历(将空节点也入队),如果遇到空节点时,队列中还有非空结点,那么就说明不是完全二叉树;如果队列中没有非空结点,那么就是完全二叉树。

    1.     bool _IsComplete_2()  
    2.     {  
    3.         if(_bt._root == NULL)  
    4.             return false;  
    5.         queue<Node*> q;  
    6.         q.push(_bt._root);  
    7.         while(!q.empty())  
    8.         {  
    9.             Node* top = q.front();  
    10.             if(top != NULL)  
    11.             {  
    12.                 q.pop();  
    13.                 q.push(top->_left);  
    14.                 q.push(top->_right);  
    15.             }  
    16.             else  
    17.                 break;  
    18.         }  
    19.         //计算队列中非空节点的个数  
    20.         int i = 0;  
    21.         while(i++ < q.size())  
    22.         {  
    23.             if(q.front() != NULL)  
    24.                 return false;  
    25.             else  
    26.                 q.pop();  
    27.         }  
    28.         return true;  
    29.     }  
    4.求两个结点的最低公共祖先。
    分析:对于这样的问题,就要考虑到各种情况。
    1)二叉搜索树的情况:根据二叉搜索树的性质(左孩子的值小于根节点的值,右孩子的值大于根节点的值),如果给定的两个结点的值都大于当前子树的根节点的值,那么这两个结点必然都位于当前子树的右子树上;如果给定的两个结点的值都小于当前子树的根节点,那么这两个结点都在当前子树的左子树上;如果给定的两个结点的值一个大于当前子树的根节点的值,一个小于当前子树的根节点的值,那么当前的子树的根节点就是所要找的最低公共祖先。
    完整代码:
    1. template<typename T>  
    2. class CommonParent  
    3. {  
    4.     typedef TreeNode<T> Node;  
    5. public:  
    6.     CommonParent(T* array,size_t size,const T& invalid)  
    7.        :_bt(array,size,invalid)  
    8.     {}  
    9.     //是二叉搜索树的情况  
    10.     Node*  LeastCommonParent(const T& a, const T& b)  
    11.     {  
    12.        if(_bt._root == NULL || (_bt.Find(a)&& _bt.Find(b)))  
    13.        {  
    14.            return  NULL;  
    15.        }  
    16.        Node* cur = _bt._root;  
    17.        //当前子树的根的值比两个节点的值都要大,说明两个节点都在当前根的左子树上  
    18.        if(cur->_data > a && cur->_data > b)  
    19.        {  
    20.            cur = cur->_left;  
    21.        }  
    22.        //当前子树的根的值比两个节点的值都要小,说明两个节点都在当前根的右子树上  
    23.        else if(cur->_data < a && cur->_data < b)  
    24.        {  
    25.            cur = cur->_right;  
    26.        }  
    27.        else  
    28.            return cur;  
    29.     }  
    30. private:  
    31.     BinaryTree<T> _bt;  
    32. };  
    33. void TestCommonParent_1()  
    34. {  
    35.     int array[] = {8,7,5,'#','#','#',12,11,'#','#',18};  
    36.     CommonParent<int> cp(array,11,'#');  
    37.     TreeNode<int>* ret = cp.LeastCommonParent(7,20);  
    38.     if(ret == NULL)  
    39.        cout<<"没有公共祖先";  
    40.     else  
    41.        cout<<ret->_data<<endl;  
    42. }  
    2)非搜索树的情况:
    a、树中有指向父节点的指针:从给定的两个结点开始,反向遍历,找到路径。。然后求出两个链表的第一个公共结点。
    b、树中没有指向父节点的指针:从根节点分别找出给定结点的路径,然后求出两个链表的最后一个交点。这样做的话,就需要遍历树一次,遍历两个链表。下边提供一种新的高效的方法~~

    代码:

  4. bool GetNodePath1(Node *root,int data,list<Node*>&path)
    {
    if (root == NULL)
    return NULL;
    path.push_back(root);
    if (root->_value == data)
    return true;
    else
    {
    bool found = false;
    found = GetNodePath(root->_lchild,data,path);
    if (!found)
    {
    found = GetNodePath(root->_rchild,data,path);
    }
    if (!found)
    path.pop_back();
    return found;
    }
    }
    Node* GetLastComNode2( list<Node*>l1, list<Node*>l2)
    {
    
    list<Node*>::iterator it1 = l1.begin();
    list<Node*>::iterator it2 = l2.begin();
    Node* Plist = NULL;
    while ((it1 != l1.end()) && (it2 !=l2.end()))
    {
       if (*it1 == *it2)
       Plist = *it1;
    it1++;
    it2++;
    }
    return Plist;
    }
    Node* GetComParent(int data1,int data2)
    {
    if (!GetNodePath1(_root, data1, path1))
    {
    IsExistData1 = false;
    return NULL;
    }
    if (!GetNodePath1(_root, data1, path2))
    {
    IsExistData2 = false;
    return NULL;
    
    
    }
    return GetLastComNode2(path1,path2);
    }


  1. 5.将二叉搜索树改为有序的双向链表。
    分析:二叉搜索树的中序遍历就是一个升序序列。像前边线索化二叉树那样,如果可以让一个结点的left指向其中序遍历的前一个结点(当该结点不是第一个结点的时候),将该结点的right指向其后序遍历的下一个结点。遍历完了之后,我们还是需要沿着树的方向,一直向左走,找到链表的第一个结点。
    代码:
    [cpp]  view plain  copy
      在CODE上查看代码片 派生到我的代码片
    1. void _ToList(Node* root,Node*& prev)  
    2.     {  
    3.         if (root == NULL)  
    4.             return;  
    5.         _ToList(root->_left,prev);  
    6.         root->_left = prev;  
    7.         if (prev)  
    8.             prev->_right = root;  
    9.          prev = root;  
    10.         _ToList(root->_right,prev);  
    11.     }  
    给出完整代码
  2. #include<assert.h>
    template<class T>
    struct TreeNode
    {
    TreeNode(const T& value = T())
    :_value(value)
    , _lchild(0)
    , _rchild(0)
    {}
    T _value;
    TreeNode <T>*_lchild;
    TreeNode <T>*_rchild;
    int nMaxLeft;
    int nMaxRight;
    };
    bool IsExistData1 = true;
    bool IsExistData2 = true;
    
    
    template<class T>
    class Binarytree
    {
    public:
    typedef TreeNode<T> Node;
    Binarytree()
    :_root(NULL)
    {}
    Binarytree(const T*a,size_t size,const T&invalid)
    {
    assert(a);
    size_t index = 0;
    _root = CreatTree(a,size,invalid,index);
    }
    Binarytree(const Binarytree<T> &b)
    {
    _root = _Copy(b._root);
    }
    Binarytree& operator=(const Binarytree<T> &b)
    {
    if (this != &b)
    {
    Node* tmp = _Copy(b._root);
    Destroy(_root);
    _root = tmp;
    }
    return *this;
    }
    
    
    ~Binarytree()
    {
    Destroy(_root);
    _root = NULL;
    }
    void _prevPrint()
    {
    cout << "先序遍历"<<" ";
    preorder(_root);
    cout << endl;
    }
    void levePrint()
    {
    cout << " 层序遍历" << " ";
    leveorder(_root);
    }
    size_t _size()
    {
    return Size(_root);
    }
    size_t _depth()
    {
    return depth(_root);
    }
    size_t _Getleaf()
    {
    return Getleaf(_root);
    }
    size_t _Getllevesize(int k)
    {
    return getklevesize(_root,k);
    }
    
    bool _IsComplete_2()
    {
    if (_root == NULL)
    return false;
    queue<Node*> q;
    q.push(_root);
    while (!q.empty())
    {
    Node* top = q.front();
    if (top != NULL)
    {
    q.pop();
    q.push(top->_lchild);
    q.push(top->_rchild);
    }
    else
    break;
    }
    //计算队列中非空节点的个数  
    int i = 0;
    while (i++ < q.size())
    {
    if (q.front() != NULL)
    return false;
    else
    q.pop();
    }
    return true;
    }
    list<Node*> path1;
    list<Node*> path2;
    bool _IsComplete()
    {
    if (_root == NULL)
    return false;
    queue<Node*>q;
    q.push(_root);
    while (!q.empty())
    {
    Node*top = q.front();
    if (top != NULL)
    {
    q.pop();
    q.push(top->_lchild);
    q.push(top->_rchild);
    }
    else
    break;
    }
    int i = 0;
    
    
    
    while (i < q.size())
    {
    if (q.front() != NULL)
    return false;
    q.pop();
    i++;
    }
    return true;
    }
    //求两个节点最近的父节点
    bool GetNodePath1(Node *root,int data,list<Node*>&path)
    {
    if (root == NULL)
    return NULL;
    path.push_back(root);
    if (root->_value == data)
    return true;
    else
    {
    bool found = false;
    found = GetNodePath(root->_lchild,data,path);
    if (!found)
    {
    found = GetNodePath(root->_rchild,data,path);
    }
    if (!found)
    path.pop_back();
    return found;
    }
    }
    Node* GetLastComNode2( list<Node*>l1, list<Node*>l2)
    {
    
    list<Node*>::iterator it1 = l1.begin();
    list<Node*>::iterator it2 = l2.begin();
    Node* Plist = NULL;
    while ((it1 != l1.end()) && (it2 !=l2.end()))
    {
    if (*it1 == *it2)
       Plist = *it1;
    it1++;
    it2++;
    }
    return Plist;
    }
    Node* GetComParent(int data1,int data2)
    {
    if (!GetNodePath1(_root, data1, path1))
    {
    IsExistData1 = false;
    return NULL;
    }
    if (!GetNodePath1(_root, data1, path2))
    {
    IsExistData2 = false;
    return NULL;
    
    
    }
    return GetLastComNode2(path1,path2);
    }
    
    
    bool GetNodePath(Node* root,int data,list<Node*>&path)
    {
    if (root == NULL)
    return false;
    path.push_back(root);
    if (root->_value == data)
    return true;
    else 
    {
    bool found = false;
     found= GetNodePath(root->_lchild,data,path);
    if (!found)
    found=GetNodePath(root->_rchild, data, path);
    if (!found)
    path.pop_back();
    return found;
    }
    }
    Node*GetLastComNode(const list< Node*> &list1, const list<Node*> &list2)
    {
    list<Node *>::const_iterator it1 = list1.begin();
    list<Node *>::const_iterator it2 = list2.begin();
    Node *pLast = NULL;
    while (it1 != list1.end() && it2 != list2.end())
    {
    if (*it1 == *it2)
    pLast = *it1;
    break;
    it1++;
    it2++;
    }
    return  pLast;
    }
    //3.组合1,2,返回公共结点;
    Node *GetLastCommParent(Node *root, int data1, int data2)
    {
    if (NULL == root)
    return NULL;
    //得到路径
    if (!GetNodePath(root, data1, path1))
    {
    IsExistData1 = false;
    return NULL;
    }
    if (!GetNodePath(root, data2, path2))
    {
    IsExistData2 = false;
    return NULL;
    }
    //得到最低公共祖先;
    return GetLastComNode(path1, path2);
    }
    Node* GetCommentParent(int data1,int data2)
    {
    return GetLastCommParent(_root,data1,data2);
    }
    void _ToList(Node* root, Node*& prev)
    {
    if (root == NULL)
    return;
    _ToList(root->_lchild, prev);
    root->_lchild = prev;
    if (prev)
    prev->_rchild = root;
    prev = root;
    _ToList(root->_rchild, prev);
    }
    Node* Tolist()
    {
    Node*prev = NULL;
    _ToList(_root,prev);
    while (prev)
    {
    if (prev->_lchild == NULL)
    return prev;
    prev = prev->_lchild;
    }
    }
    
    protected:
    void Destroy(Node *&root)
    {
    if (root)
    {
    Destroy(root->_lchild);
    Destroy(root->_rchild);
    delete root;
    root = NULL;
    }
    }
    void leveorder(Node* root)
    {
    queue<Node*> q;
    if (root)
    {
    q.push(root);
    }
    while (!q.empty())
    {
    Node* front = q.front();
    q.pop();
    cout << front->_value << " ";
    if (front->_lchild)
    {
    q.push(front->_lchild);
    }
    if (front->_rchild)
    {
    q.push(front->_rchild);
    }
    } 
    }
    void preorder(Node *root)
    {
    if (root)
    {
    cout << root->_value << " ";
    preorder(root->_lchild);
    preorder(root->_rchild);
    }
    }
    Node* CreatTree(const T*a,size_t size,const T& invalid,size_t &index)
    {
    assert(a);
    Node*root = NULL;
    if (a[index]!=invalid&&(index<size))
    {
    root = new Node(a[index]);
    root->_lchild = CreatTree(a, size, invalid, ++index);
    root->_rchild = CreatTree(a, size, invalid, ++index);
    }
    return root;
    }
    Node* _Copy(Node *root)
    {
    Node*tmp = NULL;
    if (root)
    {
    tmp = new Node(root->_value);
    tmp->_lchild = _Copy(root->_lchild);
    tmp->_rchild = _Copy(root->_rchild);
    }
    return tmp;
    }
    
    
    size_t Size(Node*root)
    {
    size_t count = 0;
    if (root == NULL)
    {
    return 0;
    }
    else
    {
    count = Size(root->_lchild) + Size(root->_rchild) + 1;
    }
    return count;
    }
    size_t depth(Node* root)
    {
    
    if (root==NULL)
    {
    return 0;
    }
    return depth(root->_lchild) > depth(root->_rchild) ? (depth(root->_lchild) + 1) : (depth(root->_rchild) + 1);
    
    
    }
    size_t Getleaf(Node*root)
    {
    if (root == NULL)
    return 0;
    if (root->_lchild == NULL&&root->_rchild == NULL)
    return 1;
    else
    return Getleaf(root->_lchild) + Getleaf(root->_rchild);
    }
    size_t getklevesize(Node*root,size_t k)
    {
    assert(k>=1);
    size_t count = 0;
    if (root == NULL)
    return 0;
    if (k == 1)
    {
    count++;
    }
    else
    {
      count=getklevesize(root->_lchild, k-1)  + getklevesize(root->_rchild,k-1);
    }
    
    return count;
    }
    protected:
    Node* _root;
    };
    int main()
    {
    int arr1[] = {30,10,9,'#','#',11,'#','#',50,49,'#','#',51,'#','#'};
    int arr[] = {1,2,3,'#','#','#',5,6,'#','#','#'};
    char invalid = '#';
    Binarytree<int> b(arr1,sizeof(arr)/arr[0],invalid);
    b._prevPrint();
    cout << endl;
    b.levePrint();
    cout << endl;
    cout << b._size();
    cout << endl;
    cout << b._depth();
    cout << endl;
    cout << b._Getleaf();
    cout << endl;
    cout<<b._Getllevesize(2);
    cout << endl;
    if (b._IsComplete())
    {
    printf("是完全二叉树\n");
    }
    //if (IsExistData1 == true && IsExistData2==true)
    //cout << b.GetComParent(5,6)->_value<<" ";
    TreeNode<int>* Prev = NULL;
    Prev=b.Tolist();
    TreeNode<int>* Prev1 = Prev;
    while (Prev1->_rchild != NULL)
    {
    cout << Prev1->_value << " ";
    Prev1 = Prev1->_rchild;
    }
    cout << endl;
    }


Python二叉树面试题有很多种,以下是其中几个常见的面试题: 1. 二叉树的最大深度:这个问题要求计算给定二叉树的最大深度。可以使用递归的方法来解决,递归函数的定义是返回当前节点的深度,递归终止条件是节点为空时返回0,递归过程中比较左右子树的深度并返回较大值加1。时间复杂度为O(n),空间复杂度为O(n)。 2. 二叉树的前序遍历:这个问题要求按照前序遍历的顺序输出二叉树的节点值。可以使用递归或迭代的方法来解决。递归方法的思路是先输出当前节点的值,然后递归遍历左子树,最后递归遍历右子树。迭代方法可以使用栈来辅助实现,把根节点压入栈中,然后循环弹出栈顶节点,输出其值,并将其右子节点和左子节点依次压入栈中。时间复杂度为O(n),空间复杂度为O(n)。 3. 二叉树的层序遍历:这个问题要求按照层序遍历的顺序输出二叉树的节点值。可以使用队列来辅助实现。首先将根节点入队,然后循环直到队列为空,每次从队列中取出一个节点,输出其值,并将其左右子节点依次入队。时间复杂度为O(n),空间复杂度为O(n)。 以上是几个常见的Python二叉树面试题的解法,根据具体的问题要求和输入条件选择合适的解法即可。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【编程之路】面试必刷TOP101:二叉树系列(23-30,Python实现)](https://blog.csdn.net/be_racle/article/details/125531755)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [【面试题8】二叉树的下一个节点](https://download.csdn.net/download/weixin_38589168/14035034)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值