AVL树的判断
作者: 冯向阳
时间限制: 1s
章节: 课程设计
问题描述
目的:设计并实现一个算法Judge_AVL,用来判断1棵给定的二叉排序树是否是平衡二叉树。
提示:
(1)若一棵二叉排序树中每个结点的左、右子树的深度之差(平衡因子)的绝对值不超过1,则称这样的二叉树为平衡二叉树(AVL树)。
(2)首先判断该二叉树是否是一棵二叉排序树。如不是,则可直接给出false(不是AVL树);如是,进入(3)
(3)使用任意的遍历方式对该二叉树进行遍历(测试数据使用非递归的后序遍历得到,参考个人任务12),在visit函数中计算访问的结点的平衡因子。参照个人任务13,但要稍作修改(不要通过数据元素的值,而是直接通过遍历到的结点地址来定位)。
(4)如有结点的平衡因子的绝对值超过1,则可给出false;如所有结点的平衡因子的绝对值都不超过1,则可给出true。
注意:结点的数据域的类型为string
参考函数原型:
(1)判断是否是AVL树
template<class ElemType>
bool Judge_AVL(BinaryTree<ElemType> &T);
(2)visit函数
template<class ElemType>
bool visit(BinaryTreeNode<ElemType> * root){
int lheight, rheight, flag;
if(!root) return false;
else{
cout<<root->data<<" ";
lheight = GetBinaryTreeHeight_Cursive(root->LChild);
rheight = GetBinaryTreeHeight_Cursive(root->RChild);
flag = lheight - rheight;
cout<<flag<<endl;
if( flag < -1 || flag > 1) return false;
}
return true;
}
输入说明
第一行:表示无孩子或指针为空的特殊分隔符
第二行:二叉树的先序序列(结点元素之间以空格分隔)
输出说明
如不是二叉排序树,直接输出false
否则,按照后序遍历
结点1的数据域的值 平衡因子(以空格分隔)
....
(如遇到结点的平衡因子不在范围内,在下一行显示false,终止)
(如所有结点的平衡因子都在范围内,在下一行显示true,终止)
#include <iostream>
#include <stack>
#include <sstream>
#include <vector>
#include <string>
using namespace std;
template<class ElemType>
struct BinaryTreeNode
{
ElemType data;
BinaryTreeNode<ElemType>* LChild;
BinaryTreeNode<ElemType>* RChild;
BinaryTreeNode(ElemType item = ElemType(), BinaryTreeNode<ElemType>* L = nullptr, BinaryTreeNode<ElemType>* R = nullptr)
: data(item), LChild(L), RChild(R) {}
};
template<class ElemType>
class BinaryTree
{
private:
BinaryTreeNode<ElemType>* root;
void destroy(BinaryTreeNode<ElemType>*& node)
{
if (node != nullptr)
{
destroy(node->LChild);
destroy(node->RChild);
delete node;
node = nullptr;
}
}
void preorder(BinaryTreeNode<ElemType>* node, vector<ElemType>& result)
{
if (node != nullptr)
{
result.push_back(node->data);
preorder(node->LChild, result);
preorder(node->RChild, result);
}
}
void inorder(BinaryTreeNode<ElemType>* node, vector<ElemType>& result)
{
if (node != nullptr)
{
inorder(node->LChild, result);
result.push_back(node->data);
inorder(node->RChild, result);
}
}
void postorder(BinaryTreeNode<ElemType>* node, vector<ElemType>& result)
{
if (node != nullptr)
{
postorder(node->LChild, result);
postorder(node->RChild, result);
result.push_back(node->data);
}
}
public:
BinaryTree() : root(nullptr) {}
~BinaryTree()
{
destroy(root);
}
void createFromPreorder(vector<ElemType> elements, ElemType empty)
{
auto it = elements.begin();
root = create(it, elements.end(), empty);
}
//层次遍历创建二叉树
void createFromLayer(vector<ElemType> elements, ElemType empty)
{
if (elements.empty())
{
root = nullptr;
return;
}
root = new BinaryTreeNode<ElemType>(elements[0]);
vector<BinaryTreeNode<ElemType>*> nodes;
nodes.push_back(root);
size_t i = 1;
while (i < elements.size())
{
BinaryTreeNode<ElemType>* node = nodes.front();
nodes.erase(nodes.begin());
if (elements[i] != empty)
{
node->LChild = new BinaryTreeNode<ElemType>(elements[i]);
nodes.push_back(node->LChild);
}
++i;
if (i < elements.size() && elements[i] != empty)
{
node->RChild = new BinaryTreeNode<ElemType>(elements[i]);
nodes.push_back(node->RChild);
}
++i;
}
}
BinaryTreeNode<ElemType>* create(typename vector<ElemType>::iterator& it, typename vector<ElemType>::iterator end, ElemType empty)
{
if (it == end || *it == empty)
{
return nullptr;
}
BinaryTreeNode<ElemType>* node = new BinaryTreeNode<ElemType>(*it);
++it;
node->LChild = create(it, end, empty);
++it;
node->RChild = create(it, end, empty);
return node;
}
// 非递归后序遍历算法
void PostOrderTraversal()
{
stack<BinaryTreeNode<ElemType>*> S;
BinaryTreeNode<ElemType>* p = root;
BinaryTreeNode<ElemType>* lastVisited = nullptr;
bool isAVL = true;
while (p != nullptr || !S.empty())
{
if (p != nullptr)
{
S.push(p);
p = p->LChild;
}
else
{
BinaryTreeNode<ElemType>* topNode = S.top();
if (topNode->RChild != nullptr && topNode->RChild != lastVisited)
{
p = topNode->RChild;
}
else
{
S.pop();
if (!visit(topNode)) // 使用visit函数来访问节点,并检查是否平衡
{
isAVL = false;
break; // 如果发现不平衡的节点,立即退出遍历
}
lastVisited = topNode;
}
}
}
if (isAVL)
{
// 如果遍历完成后没有发现不平衡的节点,输出true
cout << "true" << endl;
}
}
//中序遍历算法
void InOrderTraversal()
{
stack<BinaryTreeNode<ElemType>*> S;
BinaryTreeNode<ElemType>* p = root;
vector<ElemType> result;
while (p != nullptr || !S.empty())
{
if (p != nullptr)
{
S.push(p);
p = p->LChild;
}
else
{
p = S.top();
S.pop();
result.push_back(p->data);
p = p->RChild;
}
}
// 输出结果
for (size_t i = 0; i < result.size(); ++i)
{
cout << result[i];
if (i != result.size() - 1)
cout << ",";
}
}
//判断是否为BST
bool isBST()
{
stack<BinaryTreeNode<ElemType>*> S;
BinaryTreeNode<ElemType>* p = root;
ElemType lastData = ElemType();
while (p != nullptr || !S.empty())
{
if (p != nullptr)
{
S.push(p);
p = p->LChild;
}
else
{
p = S.top();
S.pop();
if (p->data < lastData)
return false;
lastData = p->data;
p = p->RChild;
}
}
return true;
}
//判断是否为平衡二叉树
bool visit(BinaryTreeNode<ElemType>* node)
{
if (!node) return true; // 如果节点为空,直接返回true
int lheight = GetBinaryTreeHeight_Cursive(node->LChild);
int rheight = GetBinaryTreeHeight_Cursive(node->RChild);
int flag = lheight - rheight;
// 输出节点的数据和平衡因子
cout << node->data << " " << flag << endl;
if (flag < -1 || flag > 1)
{
// 如果平衡因子不在[-1, 1]范围内,输出false并返回false
cout << "false" << endl;
return false; // 节点不平衡
}
return true; // 节点平衡
}
//获取二叉树高度
int GetBinaryTreeHeight_Cursive(BinaryTreeNode<ElemType>* root)
{
int lheight, rheight;
if (!root) return 0;
else {
lheight = GetBinaryTreeHeight_Cursive(root->LChild);
rheight = GetBinaryTreeHeight_Cursive(root->RChild);
}
return lheight > rheight ? lheight + 1 : rheight + 1;
}
//判断是否为AVL
bool Judge_AVL(BinaryTree<ElemType>& T)
{
return visit(T.root);
}
};
int main()
{
string nullSymbol;
string preorderInput;
getline(cin, nullSymbol);
getline(cin, preorderInput);
stringstream ss(preorderInput);
string item;
vector<string> elements;
while (ss >> item)
{
elements.push_back(item);
}
BinaryTree<string> tree;
tree.createFromPreorder(elements, nullSymbol);
if (!tree.isBST())
{
cout << "false";
return 0;
}
tree.PostOrderTraversal();
cout << endl;
return 0;
}