【东华大学oj】AVL树的判断

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Juneeeeeeeeeeeee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值