二叉树面试题总结

二叉树是除了链表外最重要的数据结构之一,它的面试题也是很常见的,今天可以来总结一下。
1. 前/中/后遍历二叉树(递归&非递归)
2. 层序遍历二叉树
3. 按行层序打印二叉树
4、求二叉树的高度
5、求二叉树中结点的个数
6、求叶子结点的个数
7、求二叉树中第k层结点的个数
8、判断一个节点是否在一棵二叉树中
9、求二叉树中两个结点的最近公共祖先结点
10、判断一棵二叉树是否是平衡二叉树
11、求二叉树中最远的两个结点之间的距离
12、有前序遍历和中序遍历重建二叉树(前序遍历结果:1,2,3,4,5,6 中序遍历结果:4,2,5,1,6,3)
13、判断一棵二叉树是否是完全二叉树
14、求二叉树的镜像
15、将二叉搜索树转换成一个排序的双向链表。要求:不能创建任何新的结点,只能调整树种结点指针的指向
遍历
(1)前序非递归&&递归

 void PreOrder(BinTreeNode* root)
  {
    if(root)
     {
        cout<<"root"<<root->data;

        PreOrder(root->pLeft);

        PreOrder(root->pRight);
     }
 }
void PreOrderNon(BinTreeNode* root)
 {
      if(root==NULL)
        return;
     stack<BinTreeNode*> s;
     s.push(root);
     while(!s.empty())
     {
          BinTreeNode* pcur=q.top();
         cout<<pcur->data;
         q.pop();

        if(pcur->pRight!=NULL)
            q.push(pcur->pRight);
         if(pcur->pLeft!=NULL)
             q.push(pcur->pLeft);
     }

 }
 void PreOrderNon2(BinTreeNode* root)
 {
     stack<BinTreeNode*> s;
     while(root!=NULL||!s.empty())
      {
         while(root)
         {
             cout<<root->data<<"->";
             s.push(root);
              root=root->pLeft;
          }
          BinTreeNode* top=s.top();
          s.pop();
         root=top->pRight;
      }
 }

(2)中序遍历递归&非递归

void InOrder(BinTreeNode* root)
  {
      if(root)
     {
         InOrder(root->pLeft);

          cout<<"root"<<root->data;

          InOrder(root->pRight);
      }
  }
 void InOrderNon(BinTreeNode* root)
 {
    if(root==NULL)
         return;
     stack<BinTreeNode*> s;
    while(root!=NULL||!s.empty())
    {
        while(root)
         {
             s.push(root);
             root=root->pLeft;
        }
        BinTreeNode* top=s.top();
        cout<<top->data<<"->";
        s.pop();
        root=root->pRight;

    }
}

(3)后序遍历递归&非递归

void PostOrder(BinTreeNode* root)
 {
     if(root)
     {
         PostOrder(root->pLeft);

         PostOrder(root->pRight);

         cout<<"root"<<root->data;
     }
  }
void PostOrderNon(BinTreeNode* root)
 {
    BinTreeNode* pcur=root;
     BinTreeNode* pPre=NULL;
     stack<BinTreeNode* > s;
    while(pcur!=NULL||s.empty())
     {
        while(pcur)
         {
            s.push(pcur);
            pcur=pcur->pLeft;
         }

         BinTreeNode* ptop=s.top();
       if(ptop->pRight==NULL||ptop->pRight==pPre)
        {
             cout<<ptop->data<<"->";
             s.pop();
             pPre=ptop;
         }
       else
            {
            pcur=ptop->pRight;
         }

    }

 }

层序遍历

void LeverOrder(BinTreeNode* root)                                          
 {
     if(root==NULL)
         return;
     queue<BinTreeNode*> q;
     q.push(root);

      while(!q.empty())
     {
         BinTreeNode* pcur=q.front();
         cout<<pcur->data<<endl;
        q.pop();

         if(pcur->pLeft!=NULL)
             q.push(pcur->pLeft);

         if(pcur->pRight!=NULL)
             q.push(pcur->pRight);
    }
 }

按行层序遍历

 void LeverOrderLine(BinTreeNode* root)
 {
     if(root==NULL)
        return;
     queue<BinTreeNode*> q;
     q.push(root);
     int nextlever=0;
     int printNode=1;

     while(!q.empty())
     {
         BinTreeNode* pcur=q.front();
         cout<<pcur->data;
         q.pop();

         if(pcur->pLeft!=NULL)
         {
             q.push(pcur->pLeft);
             ++nextlever;
         }
         if(Pcur->pRight!=NULL)  
            {
            q.push(pcur->pRight);
             ++nextlever;
         }

         --printNode;
         if(printNode==0)
         {
            cout<<endl;

            printNode=nextlever;

            nextlever=0;

         }
   }
 }

二叉树高度(递归)

int Height(BinTreeNode* root)
 {
     if(root==NULL)
        return 0;
     if(root->pLeft==NULL||root->pRight==NULL)
         return 1;

     int leftHeight=Height(root->pLeft);
     int rightHeight=Height(root->pRight);

     return leftHeight>rightHeight?leftHeight+1:rightHeight+1;
194 }

二叉树结点个数(递归)

 int NodesOfTree(BinTreeNode* root)
 {
     if(root==NULL)
        return 0;
     if(root->pLeft==NULL&&root->pRight==NULL)
         return 1;
    return NodesOfTree(root->pLeft)+NodesOfTree(root->pRight)+1;
 }

叶子结点数

int LeefNodes(BinTreeNode* root)
 {
    if(root==NULL)
        return 0;
     if(root->pLeft==NULL&&root->pRight==NULL)
         return 1;

     return LeefNodes(root->pLeft)+LeefNodes(root->pRight);
 }

第K层结点数目

 int GetKthNodes(BinTreeNode* root, int k)
 {
     if(root==NULL||k<0)
         return 0;
     if(k==1)
         return 1;
     return GetKthNodes(root->pLeft,k-1)+GetKthNodes(root->pRight,k-1);
 }

判断结点是否在二叉树中(递归)

 bool IsNodeInTree(BinTreeNode* root,BinTreeNode* pcur)
{
     if(root==NULL||pcur==NULL)
         return false;
     if(root->data==pcur->data)
         return true;

     if( IsNodeInTree(root->pLeft,pcur)||IsNodeInTree(root->pRight,pcur))
         return true;
     else
         return false;
 }

求两个结点最近公共祖先(分三种情况)
树中两个结点的最低公共祖先
判断是不是平衡二叉树

 bool IsAvlue(int bf)
 {
     return abs(bf)<2;
 }
 bool IsAVLTree(BinTreeNode* root,int &depth)
 {
     if(root==NULL)
     {
         return false;
     }
    int left=0;
      int right=0;

     if(IsAVLTree(root->pLeft,left)&&IsAVLTree(root->pRight,right))
     {
         int bf=right-left;
         if(IsAvlue(bf))
        {
             depth=left>right?left+1:right+1;
  return true;
         }
        return false;
     }
 }

求二叉树最远结点的距离
树中最远结点的距离
利用前序遍历和中序遍历重建二叉树

BinTreeNode* ConstructCore(DataType* prestart,DataType* preend,\
                           DataType* Instart,DataType* Inend)
 {
     int rootValue=prestart[0];
     BinTreeNode* root=new BinTreeNode;
     root->data=rootValue;
     root->pLeft=root->pRight=NULL;

     if(prestart==preend)
     {
         if(Instart==Inend&&*prestart==*Instart)
             return root;
         else
             return NULL;
     }
     int *rootInorder=Instart;
     while(rootInorder<=Inend&&*rootInorder!=rootValue)
    {
        ++rootInorder;
     }
if(rootInorder==Inend&&*rootInorder!=rootValue)
         return NULL;

     int leftLength=rootInorder-Instart;
     int* leftPreEnd=prestart+leftLength;
     if(leftLength>0)
     {
         root->pLeft=ConstructCore(prestart+1,leftPreEnd,\
                                  Instart,rootInorder-1);
     }
     if(leftLength<preend-prestart)
     {
         root->pRight=ConstructCore(leftPreEnd+1,preend,\
                                   rootInorder+1,Inend);
     }
     return root;
 }

 BinTreeNode* Construct(DataType* preOrder,DataType*inOrder,int length)
 {
     if(preOrder==NULL||inOrder==NULL||length<=0)
        return NULL;
    return ConstructCore(preOrder,preOrder+length-1,\
             inOrder,inOrder+length-1);
 }

判断是不是完全二叉树

bool _IsComplete(PNode PRoot)
    {
        if (PRoot == NULL)
            return true;

        queue<PNode> q;
        bool flag = false;//标志是否是叶子结点,将叶子结点作为临界点
        bool result = true;
        q.push(PRoot);

        while (!q.empty())
        {
            PNode cur = q.front();
            q.pop();
            if (flag)  //如果是叶子结点的话,判断当前结点(上一个的兄弟结点)的左右子树
            {
                if (cur->_PLeft != NULL || cur->_PRight != NULL)
                {
                    result = false;
                    break;
                }
            }

           else
           {

               if (cur->_PLeft && cur->_PRight)
             {
                q.push(cur->_PLeft);
                q.push(cur->_PRight);
             }  
               //左子树不存在,右子树存在,一定不是
               else if (cur->_PLeft == NULL&&cur->_PRight != NULL)
            {
                result = false;
            }
              //左子树存在,右子树不存在,判断其兄弟结点的左右子树
               else if (cur->_PLeft != NULL&&cur->_PRight == NULL)
            {
                q.push(cur->_PLeft);
                flag = true;
            }
            //当前结点为叶子结点,判断其兄弟结点的左右子树
               else
             {
                flag = true;
             }
          }

        }
        return result;
}

求镜像

void _Mirror(PNode& PRoot)
    {
        if (PRoot)
        {
            //访问根结点
            swap(PRoot->_PLeft, PRoot->_PRight);
                        //左子树
            _Mirror(PRoot->_PLeft);
            //右子树
            _Mirror(PRoot->_PRight);
        }
}

链表转化
将二叉搜索树转换为双向链表

猜你喜欢

转载自blog.csdn.net/qq_37954088/article/details/81486758