点:二叉树
题意:判断一个二叉树是否是AVL树,即二叉树任意一个节点的左右子树深度之差不得大于1
剑指offer面试题39引申
思路:和算二叉树的深度一样,依然按后序,然后依次求深度,同时传入一个bool变量入函数栈,每个节点只要发现左右子树深度超过1,就可以说明已经不是avl树了。
在剑指offer中还有一种更高效的解法,它虽然也依赖树的深度,但不是以算深度为主导,而是在每次发现深度差超过1时,即发现已经不是avl树时,便给上级递归返回这个结果,上级发现下层左或右节点已经非avl时,就不会再继续去算另一个节点的情况了,而是直接返回这个非avl的结果到它的递归上一级。相比上面的算法,这个算法在某些情况下确实节省了很多不必要的二叉树深度计算。
两个解法的代码:
#include <random>
#include <iostream>
template<class T> struct Node {
T val;
Node<T> *lchild;
Node<T> *rchild;
Node(T _val):val(_val), lchild(nullptr), rchild(nullptr) {}
};
template<class T> class Btree {
Node<T> *root;
public:
Btree():root(nullptr){}
void Free (Node<T> *cur) {
if (cur) {
Free(cur->lchild);
Free(cur->rchild);
delete cur;
cur = nullptr;
}
}
~Btree () {
Free(root);
}
void Add (int val) {
if (!root) {
root = new Node<T>(val);
} else {
Node<T> *cur = root;
while (cur) {
if (cur->val > val) {
if (cur->lchild) {
cur = cur->lchild;
} else {
Node<T> *newnode = new Node<T>(val);
cur->lchild = newnode;
}
} else if (cur->val < val) {
if (cur->rchild) {
cur = cur->rchild;
} else {
Node<T> *newnode = new Node<T>(val);
cur->rchild = newnode;
}
} else {
break;
}
}
}
}
void Pre (Node<T> *cur) {
if (cur) {
std::cout << cur->val << "\t";
Pre(cur->lchild);
Pre(cur->rchild);
}
}
void pre () {
Pre(root);
std::cout << std::endl;
}
bool Judge2 (Node<T> *cur, int *depth) {
if (cur) {
int left, right;
if (Judge2(cur->lchild, &left) && Judge2(cur->rchild, &right)) {
*depth = 1 + ((left > right)?left:right);
if (left - right > 1 || right - left > 1) {
return false;
} else {
return true;
}
} else {
return false;
}
} else {
*depth = 0;
return true;
}
}
bool judge_if_avl2 () {
int depth = 1;
return Judge2(root, &depth);
}
int Judge (Node<T> *cur, int dp, bool &res) {
if (cur) {
int ld = Judge(cur->lchild, dp + 1, res);
int rd = Judge(cur->rchild, dp + 1, res);
if (ld - rd > 1 || rd - ld > 1) {
res = false;
}
return (ld > rd)?ld:rd;
} else {
return dp - 1;
}
}
bool judge_if_avl () {
bool res = true;
Judge(root, 1, res);
return res;
}
};
int main () {
Btree<int> bt;
std::random_device rd;
for (int i = 0; i < 7; i++) {
bt.Add(rd() % 100);
}
bt.pre();
std::cout << bt.judge_if_avl() << std::endl;
std::cout << bt.judge_if_avl2() << std::endl;
return 0;
}