二叉树的常见面试题(1)

来源:互联网 发布:在线c语言教学系统 编辑:程序博客网 时间:2024/05/06 17:45

二叉树作为树的一种,是一种重要的数据结构,也是面试官经常考的东西。最近也一直在看这些,所以就记录下来方便以后的学习 和 分享给一起学习的朋友。

二叉树的常见面试题:二叉树的前序、中序后序遍历  , 二叉树的线索化和线索二叉树的遍历(其中后序最难) , 求二叉树的高度 , 二叉树的叶子节点的个数  , 查询某个元素是否在二叉树中 , 判断某个节点是否在二叉树中 ,找两个节点的最近的祖先节点,二叉树的镜像 , 判断二叉树是不是完全二叉树   等等。

首先,前面对二叉树的遍历和二叉树的线索化及遍历做了详细的解读 ,本篇就不在多说 。 


节点的构造

template<class T>struct BinaryTreeNode{typedef BinaryTreeNode<T>*  Treepoint ;BinaryTreeNode(const T& data):_data(data), pLeft(NULL), pRight(NULL){}T _data;Treepoint pLeft;Treepoint pRight;};


下面看讲述的都声明在这个类里面

template<class T>
class BinaryTree

{

private:
BinaryTreeNode<T>* _pRoot;

    //下面的代码程序

}


开始

 1、求二叉树的高按照 根节点的高度是 1

树的高度就是左子树高度和右子树高度的最大值  , 基于这个思想,我们先分别求得左子树高度 和右子树高度,然后比较两者,返回两者的最大值即可(注意:得加上根节点的高度

size_t _Height(BinaryTreeNode<T>* Root)//高度    {if (Root == NULL  ){return 0 ;}if (Root->pLeft == NULL && Root->pRight == NULL){return 1;}size_t LeftHeight = _Height(Root->pLeft); //左子树的高度size_t RightHeight = _Height(Root->pRight);  <span style="font-family: Arial, Helvetica, sans-serif;">//右子树的高度</span>return LeftHeight > RightHeight ? LeftHeight + 1 : RightHeight + 1; }

 2、求叶节点的个数

叶节点:树中度为0的节点 。当树只存在一个节点的时候,叶节点的的个数就是1(即 叶节点就是根节点),像上面的面试题一样,我们这就相当于找到了一个最终的结束条件(不管是循环还是递归) , 其实对于 二叉树的遍历 ,我们就很容易把这个结束条件往 递归上面靠 。

size_t _LeefCount(BinaryTreeNode<T>* Root)//叶节点个数{if (NULL == Root){return 0;}if (NULL == Root->pLeft && NULL == Root->pRight){return 1;}size_t Left_number = _LeefCount(Root->pLeft);//左边的叶节点size_t Right_number = _LeefCount(Root->pRight);//右边的叶节点return  Left_number + Right_number;}
3、 查询某个元素是否在二叉树中
可定要遍历二叉树直到找到该元素,然返回该元素的位置即可。

BinaryTreeNode<T>* _Find_data(BinaryTreeNode<T>* Root,const T& data) //找数{if (Root == NULL || Root->_data == data){return Root;}BinaryTreeNode<T>* Ret = NULL;if ((Ret = _Find_data(Root->pLeft, data)) != NULL)   //在左边找{return Ret;}if ((Ret = _Find_data(Root->pRight, data)) != NULL)  //在右边找{return Ret ;}return NULL;}

4、 判断某个节点是否在二叉树中 

那我们也是和找元素的方法类似

bool _Finde_Node(BinaryTreeNode<T>* Root, BinaryTreeNode<T>* Node){assert(Node != NULL);if (Root == NULL ){return false ;}if (Root == Node){return true;}bool Ret = false;if ( Ret = _Finde_Node(Root->pLeft, Node) )//左边找{return Ret;}if ( Ret = _Finde_Node(Root->pRight , Node) ) //右边找{return Ret;}return false;}

5、 找两个节点的最近的祖先节点 

首先得知道这两个节点是不是在一个树中 , (Yes) 然后把找寻节点的路径保存在栈中,然后依次出栈比较,直到找到该位置,然后返回(栈为空 就找不到 , 返回NULL就可以了)

<span style="font-size:18px;">BinaryTreeNode<T>*  <span style="color:#ff0000;">GetAncestorNode</span>(BinaryTreeNode<T>* pNode1 , BinaryTreeNode<T>* pNode2) {vector<BinaryTreeNode<T>* > v1;vector<BinaryTreeNode<T>* > v2;if (_GetPath(this->_pRoot, pNode1, v1)&& _GetPath(this->_pRoot, pNode2, v2))   {while (!v1.empty() && !v2.empty()) {if (v1.back() == v2.back()){return v1.back();}if (v1.size() > v2.size()){v1.pop_back();}else if (v1.size() < v2.size()){v2.pop_back();}else{v1.pop_back();v2.pop_back();}}}return NULL;}bool<span style="color:#ff0000;"> _GetPath</span>(BinaryTreeNode<T>* Root, BinaryTreeNode<T>* pNode, vector<BinaryTreeNode<T>* >& v)//找路径{if (Root == NULL || pNode == NULL){return false;}v.push_back(Root);if (Root == pNode){return true;}if ((Root->pLeft !=NULL) && _GetPath(Root->pLeft, pNode, v)) //左边{return true ;}if (Root->pLeft != NULL){v.pop_back();}if ((Root->pRight != NULL) && _GetPath(Root->pRight, pNode, v)) //右边{return true;}if (Root->pLeft != NULL){v.pop_back();}return false; }</span>

6、 二叉树的镜像

就像照镜子一样 ,二叉树也是同样如此。左右互换即可

BinaryTreeNode<T>*  _BiTree_Mirror(BinaryTreeNode<T>* Root){if ( Root == NULL || (Root->pLeft == NULL && Root->pRight == NULL)){return Root;}std::swap(Root->pLeft, Root->pRight);_BiTree_Mirror(Root->pLeft);_BiTree_Mirror(Root->pRight);return Root;}

又想出了一个非递归的做法,大家看看

void _BiTree_Mirror_Nor(BinaryTreeNode<T>* Root){if (Root == NULL || (Root->pLeft == NULL && Root->pRight == NULL)){return ;}queue<BinaryTreeNode<T>* > q;q.push(Root);while (!q.empty()){BinaryTreeNode<T>* pCur = q.front();std::swap(pCur->pLeft, pCur->pRight);q.pop();if (pCur->pLeft != NULL){q.push(pCur->pLeft);}if (pCur->pRight != NULL){q.push(pCur->pRight);}}}

7、判断二叉树是不是完全二叉树

完全二叉树:具有n个结点的二叉树按层序编号,如果编号为i(1≤i≤n)的结点与同样深度的满二叉树中的编号为i的结点在二叉树中的位置完全相同。 定义这样难免不好理解,我们可以用这棵树和的它的满二叉树形式对比就可以知道是不是完全二叉树了。

我测了感觉没有什么问题,大家看的时候多测测,或许能找出漏洞

  思路 :设置标志位,当像第一次遇到只存在单个子树的时候,就标记一下,如果下一次还能再遇到,那么它就不是完全二叉树

bool _IsComplete_BiTree_First(BinaryTreeNode<T >* Root){if (Root == NULL){return false ;}bool flag = false; queue<BinaryTreeNode<T>* > q;q.push(Root);while (!q.empty()){BinaryTreeNode<T>* pCur = q.front();q.pop();if (flag)//找到第二个  只有单个子树的节点 {if (pCur->pLeft != NULL || pCur->pRight != NULL){return false;}}//两个子树都存在if (pCur->pLeft != NULL && pCur->pRight != NULL){q.push(pCur->pLeft);q.push(pCur->pRight);}//只有左子树else if (pCur->pLeft != NULL){q.push(pCur->pLeft) ;flag = true;}//只有右子树else if (pCur->pRight != NULL){q.push(pCur->pRight) ;flag = true; }else   //没有子树{flag = false;}}return true;}

               Thx.


0 0
原创粉丝点击