二叉树是除了链表外最重要的数据结构之一,它的面试题也是很常见的,今天可以来总结一下。
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);
}
}
链表转化
将二叉搜索树转换为双向链表