1.求二叉树节点个数
可以使用递归解决。将问题分解为求根节点+左子树的节点数+右节点的节点数。
实现 :
public:
size_t _Size() { //封装调用
return Size(_root);
}
private:
size_t Size(Node *root){ //二叉树中节点个数
if (root == NULL)
return 0;
return 1 + Size(root->leftChild) + Size(root->rightChild);
}
2.求页节点个数
页节点:左右子树都为空的节点被称为页节点,使用递归遍历,当碰到一个左右子树为空的节点时,返回 1,累加起来。
实现:
public:
size_t _LeafSize() { //封装
return LeafSize(_root);
}
private:
size_t LeafSize(Node *root) { //页节点数
if (root == NULL)
return 0;
if (root->leftChild == NULL && root->rightChild == NULL) //如果左右都为空
return 1;
return LeafSize(root->leftChild)+LeafSize(root->rightChild);
}
3.求第K层节点个数
在求第 K 层节点个数时,可能会出现所求的第 K 层大于实际二叉树的层数。
实现
public:
size_t _LevelSize(size_t k) //封装
{
return LevelSize(_root, k, 1);
}
private:
size_t LevelSize(Node *root, size_t k, size_t n)//求第K层节点数
{
if (root == NULL) { //节点为空 返回0
return 0;
}
if (n < k - 1) {
return LevelSize(root->leftChild, k, n + 1) + LevelSize(root->rightChild, k, n + 1);
}
if (n == k - 1) {
return (root->leftChild != NULL) + (root->rightChild != NULL);
}
return 0;
}
4.求二叉树深度/高度
在求二叉树深度的时候,可以将问题分解为求根节点的左子树和右子树的深度的最大值 + 1。所以需要对左子树和右子树的深度进行判断,返回较大的。
实现
public:
size_t Depth() { //封装
return _Depth(_root);
}
private:
size_t _Depth(Node *root) { //求深度
if (root == NULL) {
return 0;
}
if (_Depth(root->leftChild) > _Depth(root->rightChild))
return 1+_Depth(root->leftChild);
else
return 1+_Depth(root->rightChild);
}
5.查找节点
可以使用递归对整个二叉树进行遍历,如果碰到则返回该节点位置。
实现:
public:
Node *Find(const T& x) { //查找并返回节点
return _Find(_root, x);
}
private:
Node* _Find(Node *root , const T&x) {
if (root == NULL)
return NULL;
if (root->_data == x)
return root;
Node * ret = _Find(root->leftChild, x);
if (ret != NULL)
return ret;
return _Find(root->rightChild, x);
}
6.将二叉树镜像
将二叉树镜像也就是将二叉树进行翻转。
可以使用队列,从上向下将每个元素的左右子树进行交换。
也可以使用递归,从下向上就行翻转。
循环思想
实现
public:
void MirrorTree() //非递归求镜像
{
_MirrorTree(_root);
}
private:
void _MirrorTree(Node *root) //封装调用
{
queue<Node*> q; //利用队列
Node *cur = root;
q.push(cur);
while (!q.empty())
{
Node* top = q.front();
if (top->leftChild)
q.push(top->leftChild);
if (top->rightChild)
q.push(top->rightChild);
swap(top->leftChild, top->rightChild);
q.pop();
}
}
递归思想
实现
public:
void MirrorTreeR() //递归二叉树镜像
{
_MirrorTree(_root);
}
private:
void _MirrorTreeR(Node *root) //封装调用
{
if (root == NULL)
return;
_MirrorTree(root->leftChild); //左树
_MirrorTree(root->rightChild); //右树
swap(root->leftChild, root->rightChild);
}
7.判断一颗二叉树是不是完全二叉树
完全二叉树:前N个节点与该树的满二叉树相同。
可以使用队列对二叉树进行遍历。
如果二叉树存在左右子树,则对左右子树进行压栈。
此时会出现4中情况
(1) 左右子树都存在
此时应该将根节点的左右子树入队,并将根结点的出队。
(2) 左子树存在,右子树不存在
此时应该将左节点入队并退出循环进行判断,队列中剩余元素是否存在子节点,如果存在则不是完全二叉树。
(3) 右子树存在,左子树不存在
此时,此颗二叉树肯定不是完全二叉树。
(4) 左右子树都不存在
此时应该直接退出循环,对队列中剩余的所有子树进行判断。
实现
bool IsComplateTree()
{
queue<Node *> q;
if (_root)
q.push(_root);
while (!q.empty())
{
Node *front = q.front();
q.pop();
if (front->leftChild&&front->rightChild) //如果左右子树都不为空则压入
{
q.push(front->leftChild);
q.push(front->rightChild);
}
else if (front->leftChild) { //左不为空,右为空
q.push(front->leftChild);
break; //放入左树后进行判断
}
else if (front->rightChild) //左空右不空,肯定不是完全二叉树
return false;
else //左右都为空
break; //对队列中剩下的元素进行判断
}
while (!q.empty())
{
Node *front = q.front();
if (front->leftChild == NULL&&front->rightChild == NULL)
q.pop();
else
return false;
}
return true;
}