涉及易考题目如下:
1. 求二叉树中的节点个数
2. 求二叉树的深度
3. 求二叉树第K层的节点个数
4. 求二叉树中叶子节点的个数
5. 判断两棵二叉树是否结构相同
6. 判断二叉树是不是平衡二叉树
7. 求二叉树的镜像
8. 判断二叉树是不是完全二叉树
二叉树节点定义:
struct BinaryTreeNode { int _Value; BinaryTreeNode* _pLeft; BinaryTreeNode* _pRight; };
1、求二叉树中的节点个数
递归解法:
(1)如果二叉树为空,节点个数为0
(2)如果二叉树不为空,二叉树节点个数 = 左子树节点个数 + 右子树节点个数 + 1
参考代码如下:
int GetNodeNum(BinaryTreeNode * pRoot) { if(pRoot == NULL) // 递归出口 return 0; return GetNodeNum(pRoot->_pLeft) + GetNodeNum(pRoot->_pRight) + 1; }
2、求二叉树的深度
递归解法:
(1)如果二叉树为空,二叉树的深度为0
(2)如果二叉树不为空,二叉树的深度 = max(左子树深度, 右子树深度) + 1
参考代码如下:
int GetDepth(BinaryTreeNode * pRoot) { if(pRoot == NULL) // 递归出口 return 0; int depthLeft = GetDepth(pRoot->_pLeft); int depthRight = GetDepth(pRoot->_pRight); return depthLeft > depthRight ? (depthLeft + 1) : (depthRight + 1); }
3、求二叉树第K层的节点个数
递归解法:
(1)如果二叉树为空或者k<1返回0
(2)如果二叉树不为空并且k==1,返回1
(3)如果二叉树不为空且k>1,返回左子树中k-1层的节点个数与右子树k-1层节点个数之和
参考代码如下:
int GetNodeNumKthLevel(BinaryTreeNode * pRoot, int k) { if(pRoot == NULL || k < 1) return 0; if(k == 1) return 1; int numLeft = GetNodeNumKthLevel(pRoot->_pLeft, k-1); // 左子树中k-1层的节点个数 int numRight = GetNodeNumKthLevel(pRoot->_pRight, k-1); // 右子树中k-1层的节点个数 return (numLeft + numRight); }
4、求二叉树中叶子节点的个数
递归解法:
(1)如果二叉树为空,返回0
(2)如果二叉树不为空且左右子树为空,返回1
(3)如果二叉树不为空,且左右子树不同时为空,返回左子树中叶子节点个数加上右子树中叶子节点个数
参考代码如下:
int GetLeafNodeNum(BinaryTreeNode * pRoot) { if(pRoot == NULL) return 0; if(pRoot->_pLeft == NULL && pRoot->_pRight == NULL) return 1; int numLeft = GetLeafNodeNum(pRoot->_pLeft); // 左子树中叶节点的个数 int numRight = GetLeafNodeNum(pRoot->_pRight); // 右子树中叶节点的个数 return (numLeft + numRight); }
5、判断两棵二叉树是否结构相同
不考虑数据内容。结构相同意味着对应的左子树和对应的右子树都结构相同。
递归解法:
(1)如果两棵二叉树都为空,返回真
(2)如果两棵二叉树一棵为空,另一棵不为空,返回假
(3)如果两棵二叉树都不为空,如果对应的左子树和右子树都同构返回真,其他返回假
参考代码如下:
bool StructureCmp(BinaryTreeNode * pRoot1, BinaryTreeNode * pRoot2) { if(pRoot1 == NULL && pRoot2 == NULL) // 都为空,返回真 return true; else if(pRoot1 == NULL || pRoot2 == NULL) // 有一个为空,一个不为空,返回假 return false; bool resultLeft = StructureCmp(pRoot1->_pLeft, pRoot2->_pLeft); // 比较对应左子树 bool resultRight = StructureCmp(pRoot1->_pRight, pRoot2->_pRight); // 比较对应右子树 return (resultLeft && resultRight); }
6、 判断二叉树是不是平衡二叉树
递归解法:
(1)如果二叉树为空,返回真
(2)如果二叉树不为空,如果左子树和右子树都是AVL树并且左子树和右子树高度相差不大于1,返回真,其他返回假
参考代码:
bool IsAVL(BinaryTreeNode * pRoot, int & height) { if(pRoot == NULL) // 空树,返回真 { height = 0; return true; } int heightLeft; bool resultLeft = IsAVL(pRoot->_pLeft, heightLeft); int heightRight; bool resultRight = IsAVL(pRoot->_pRight, heightRight); if(resultLeft && resultRight && abs(heightLeft - heightRight) <= 1) // 左子树和右子树都是AVL,并且高度相差不大于1,返回真 { height = max(heightLeft, heightRight) + 1; return true; } else { height = max(heightLeft, heightRight) + 1; return false; } }
7、求二叉树的镜像
递归解法:
(1)如果二叉树为空,返回空
(2)如果二叉树不为空,求左子树和右子树的镜像,然后交换左子树和右子树
参考代码如下:
BinaryTreeNode * Mirror(BinaryTreeNode * pRoot) { if(pRoot == NULL) // 返回NULL return NULL; BinaryTreeNode * pLeft = Mirror(pRoot->_pLeft); // 求左子树镜像 BinaryTreeNode * pRight = Mirror(pRoot->_pRight); // 求右子树镜像 // 交换左子树和右子树 pRoot->_pLeft = pRight; pRoot->_pRight = pLeft; return pRoot; }
8、判断二叉树是不是完全二叉树
若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数,第 h 层所有的结点都连续集中在最左边,这就是完全
二叉树。
有如下算法,按层次(从上到下,从左到右)遍历二叉树,当遇到一个节点的左子树为空时,则该节点右子树必须为空,且后面遍历的节点左
右子树都必须为空,否则不是完全二叉树。
bool IsCompleteBinaryTree(BinaryTreeNode * pRoot) { if(pRoot == NULL) return false; queue<BinaryTreeNode *> q; q.push(pRoot); bool mustHaveNoChild = false; bool result = true; while(!q.empty()) { BinaryTreeNode * pNode = q.front(); q.pop(); if(mustHaveNoChild) // 已经出现了有空子树的节点了,后面出现的必须为叶节点(左右子树都为空) { if(pNode->_pLeft != NULL || pNode->_pRight != NULL) { result = false; break; } } else { if(pNode->_pLeft != NULL && pNode->_pRight != NULL) { q.push(pNode->_pLeft); q.push(pNode->_pRight); } else if(pNode->_pLeft != NULL && pNode->_pRight == NULL) { mustHaveNoChild = true; q.push(pNode->_pLeft); } else if(pNode->_pLeft == NULL && pNode->_pRight != NULL) { result = false; break; } else { mustHaveNoChild = true; } } } return result; }