二叉树的基本操作
二叉树的遍历(前/中/后/层,递归&非递归)
代码中用到的栈
代码中用到的队列
面试题
- 拷贝二叉树
- 判断一棵二叉树是否是完全二叉树
- 二叉树的镜像递归
- 二叉树的镜像非递归
- 求二叉树中结点的个数
- 获取二叉树中叶子结点的个数
- 求二叉树中K层结点的个数
- 求二叉树的高度
- 查找值为data的结点
- 判断一个结点是否在二叉树里
1、拷贝二叉树
- 利用递归,依次拷贝根结点,左子树,右子树
- 代码如下
PBTNode CopyBinTree(PBTNode pRoot)
{
PBTNode pNewRoot = NULL;
if (NULL == pRoot)
return NULL;
else
{
//拷贝根结点
pNewRoot = BuyBinTreeNode(pRoot->_data);
//拷贝左子树
pNewRoot->pLeft = CopyBinTree(pRoot->pLeft);
//拷贝右子树
pNewRoot->pRight = CopyBinTree(pRoot->pRight);
}
return pNewRoot;
}
2、判断一棵二叉树是否是完全二叉树
- 如果二叉树为空,则返回1(空二叉树也是完全二叉树)
- 如果二叉树没有左右子树,则返回1
- 二叉树为完全二叉树时有以下几种情况:
- 代码如下
int IsCompleteBinTreeNode(PBTNode pRoot)
{
Queue q;
PBTNode pCur = NULL;
int flag = 0;
if (NULL == pRoot)
return 1;
if (NULL == pRoot->pLeft && NULL == pRoot->pRight)
return 1;
QueueInit(&q);
QueuePush(&q, pRoot);
while (!QueueEmpty(&q))
{
pCur = QueueFrontData(&q);
if (flag)
{
if (pCur->pLeft != NULL || pCur->pRight != NULL)
return 0;
}
else
{
if (pCur->pLeft && pCur->pRight)
{
QueuePush(&q, pCur->pLeft);
QueuePush(&q, pCur->pRight);
flag = 0;
}
else if (pCur->pLeft)
{
QueuePush(&q, pCur->pLeft);
flag = 1;
}
else if (pCur->pRight)
{
return 0;
}
else
{
flag = 1;
}
}
QueuePop(&q);
}
QueueDestory(&q);
return 0;
}
3、二叉树的镜像递归
- 如果二叉树为空,返回空
- 如果二叉树不为空,求左子树和右子树的镜像,然后交换左子树和右子树
-代码如下
void MirrorBinTree(PBTNode pRoot)
{
if (NULL == pRoot)
return;
else
{
PBTNode pTemp = pRoot->pLeft;
pRoot->pLeft = pRoot->pRight;
pRoot->pRight = pTemp;
MirrorBinTree(pRoot->pLeft);
MirrorBinTree(pRoot->pRight);
}
}
4、二叉树的镜像非递归
利用队列,先将根结点入队,进入循环后,保存根结点,交换根结点的左右子树,如果左右子树存在,则入队 。最后再将根结点出队,依次类推,队列空时,镜像完成。
别忘记销毁队列
- 代码如下
void MirrorBinTreeNor(PBTNode pRoot)
{
Queue q;
if (NULL == pRoot)
return;
QueueInit(&q);
QueuePush(&q, pRoot);
while (!QueueEmpty(&q))
{
PBTNode pCur = QueueFrontData(&q);
PBTNode pTemp = pCur->pLeft;
pCur->pLeft = pCur->pRight;
pCur->pRight = pTemp;
if (pCur->pLeft)
QueuePush(&q, pCur->pLeft);
if (pCur->pRight)
QueuePush(&q, pCur->pRight);
QueuePop(&q);
}
QueueDestory(&q);
}
5、求二叉树中结点的个数
- 如果二叉树为空,节点个数为0
- 如果二叉树不为空,二叉树节点个数 = 左子树节点个数 + 右子树节点个数 + 1
- 代码如下
int BinTreeSize(PBTNode pRoot)
{
if (NULL == pRoot)
return 0;
return BinTreeSize(pRoot->pLeft) + BinTreeSize(pRoot->pLeft) + 1;
}
6、获取二叉树中叶子结点的个数
- 如果二叉树为空,返回0
- 如果二叉树不为空且左右子树为空,返回1
- 代码如下
int GetLeafCount(PBTNode pRoot)
{
if (NULL == pRoot)
return 0;
if (NULL == pRoot->pLeft&& NULL == pRoot->pRight)
return 1;
return GetLeafCount(pRoot->pLeft) + GetLeafCount(pRoot->pRight);
}
7、求二叉树中K层结点的个数
- 求第K层结点个数时,就相当于求第K-1层的左子树结点和右子树结点的和
- 代码如下
int GetKLevelNode(PBTNode pRoot, int K)
{
if (K < 1 || NULL == pRoot)
return 0;
if (1 == K)
return 1;
return GetKLevelNode(pRoot->pLeft, K - 1) +
GetKLevelNode(pRoot->pRight, K - 1);
}
8、求二叉树的高度
- 求出左右子树的高度,然后比较左右子树那个高,那个高那个就是二叉树的高度
- 代码如下
int Height(PBTNode pRoot)
{
if (NULL == pRoot)
return 0;
int LeftHeight = Height(pRoot->pLeft);
int RightHeight = Height(pRoot->pRight);
return LeftHeight > RightHeight ? LeftHeight + 1 : RightHeight + 1;
}
9 、查找值为data的结点
- 如果为空而二叉树,则返回NULL
- 如果根节点的值等于要找到值,直接返回根节点
- 依次遍历左子树和右子树,找到则返回
PBTNode FindNode(PBTNode pRoot, BTDataType data)
{
PBTNode pNode = NULL;
if (NULL == pRoot)
return NULL;
if (pRoot->_data == data)
return pRoot;
if (pNode == FindNode(pRoot->pLeft, data))
return pNode;
return FindNode(pRoot->pRight, data);
}
- 最后在遍历左子树,用了if语句,遍历右子树没有用,原因如下
用if语句判断左子树找到了,则保存,并返回,如果没有if语句,要返回时只能在用return FindNode(pRoot->pLeft data)语句遍历一次返回节点; ,它不能向右子树那样直接返回,因为我遍历完左子树,如果没有找到,我还需要遍历右子树
10. 判断一个结点是否在二叉树里
- 如果为空而二叉树,则返回0
- 如果根节点的值等于要找到值,直接返回1
- 依次遍历左子树和右子树,找到则返回1,否则返回0
int IsBinTreeNode(PBTNode pRoot, PBTNode pNode)
{
int flag = 0;
if (NULL == pRoot||NULL == pNode)
return 0;
if (pNode == pRoot)
return 1;
if (flag = IsBinTreeNode(pRoot->pLeft, pNode))
return flag;
return IsBinTreeNode(pRoot->pRight, pNode);
}