平衡二叉树AVL的c++实现

本文详细介绍了如何使用C++实现平衡二叉树AVL,包括节点类的创建、AVL树的插入和删除操作,以及四种旋转操作(左旋、右旋、右左旋、左右旋)的代码实现,以保持树的平衡。文章还探讨了AVL树的平衡性质及其重要性。
摘要由CSDN通过智能技术生成

1 先创建节点类,就是一个普通的节点类的创建,用结构体也可以,唯一值的注意的是要有一个表示当前节点高度的成员,因为节点高度是判断平衡二叉树是否平衡的标志。

#include <iostream>
 using namespace std;
template<class T>
class TreeNode
{
public:
    T val;
    TreeNode<T>* lc;
    TreeNode<T>* rc;
    int height;
public:
    TreeNode(T _val=0,TreeNode<T> *_lc=NULL,TreeNode<T>* _rc=NULL,int _height=0):val(_val),     lc(_lc),rc(_rc),height(_height)
    {

    }
    ~TreeNode()
    {}
    TreeNode<T>*Getlc()const{
        return lc;
    }
    // void CreateNode(TreeNode)
    void Setlc(TreeNode<T>* _lc);
    TreeNode<T>* Getrc() const;
    void Setrc(TreeNode<T>* _rc);
    void SetVal(T _val);
    T GetVal() const
    {
        return val;
    }
    bool IsLeaf();
    static TreeNode<T>*CreateNode();
};
template<class T>
TreeNode<T>* TreeNode<T>::CreateNode()
{
    cout<<"请输入当前节点的值:";
    T n;
    cin>>n;
    if(n<0)
    {
        return;
    }
    TreeNode<T> *Node_ptr=new TreeNode<T>(n);
    Node_ptr->lc=TreeNode<T>::CreateNode();
    Node_ptr->rc=TreeNode<T>::CreateNode();
    return Node_ptr;

}
template<class T>
void TreeNode<T>::SetVal(T _val)
{
    val=_val;
}
template<class T>
void TreeNode<T>::Setlc(TreeNode<T>* _lc)
{
    lc=_lc;
}
template<class T>
void TreeNode<T>::Setrc(TreeNode<T>* _rc)
{
    rc=_rc;
}
template<class T>
TreeNode<T>* TreeNode<T>::Getrc() const
{
    return rc;

}

接下来是AVL树的创建

1 AVL树的介绍

AVL树是最先发明的自平衡二叉查找树。在AVL树中任何节点的两个子树的高度最大差别为一,所以它也被称为高度平衡树。查找、插入和删除在平均和最坏情况下都是O(log n)。增加和删除可能需要通过一次或多次树旋转来重新平衡这个树。AVL树得名于它的发明者 G.M. Adelson-Velsky 和 E.M. Landis,他们在 1962 年的论文 "An algorithm for the organization of information" 中发表了它。

        其实说白了 AVL树还是一棵二叉查找树(如果不理解什么是二叉查找树一定要先弄懂这个),只不过相对于二叉查找树它多了一个自平衡的特性,就是左右子树的高度差不能大于1,如果大于1了,就要通过旋转来是二叉树重新到达平衡。

下面先看我们实现平衡二叉树类的各种功能,然后我们在一边讲解一边逐一实现。

平衡二叉树的类:

class BalancedBinaryTree
{
private:
    TreeNode<T>*subroot;
    TreeNode<T>* InsertNode(TreeNode<T>* &_root,T _val);//插入节点
    TreeNode<T>* RightHand(TreeNode<T>* &_root);          //右旋
    TreeNode<T>* LeftHand(TreeNode<T>* &_root);            //左旋
    TreeNode<T>* RightLeftHand(TreeNode<T>* &_root);     //右左
    TreeNode<T>* LeftRightHand(TreeNode<T>* &_root);     //右左
    TreeNode<T>* RemoveNode(TreeNode<T>* _root,T _val);//删除值为_val的节点,返回值是删除后的根节点
    TreeNode<T>* MinNode(TreeNode<T>* _root) const;//获取树中的最小值,一直返回左子树的值,直到左子树为空
    TreeNode<T>* MaxNode(TreeNode<T>* _root) const;//获取树中的最大值
    TreeNode<T>* FindNode(TreeNode<T>*_root,T key) const;//查找值为Key的节点
    void DestroyNode(TreeNode<T>* &_root);                       //销毁树

    void TravelPreorderNode(TreeNode<T>* _root) const;           //前序遍历-》深度优先遍历

inline int getheight(TreeNode<T> *_Node) const      //获取当前节点的高度
    {
        if(NULL==_Node)
        {
            return 0;
        }
        return _Node->height;
    }

public:
    BalancedBinaryTree(TreeNode<T>* _subroot=NULL):subroot(_subroot)
    {}
    BalancedBinaryTree(BalancedBinaryTree<T> *Tree)
    {
        subroot=Tree->GetRoot();
    }
    ~BalancedBinaryTree()
    {}
    TreeNode<T>* GetRoot() const
    {
        return subroot;
    }
  
    void InsertKey(T _val);
    void RemoveKey(T _val);
    void DestroyTree();      //销毁树
    void TravelPreorderTree() const;
    TreeNode<T> * FindKey(T _key);
    int TreeHeight() const;                                                //获取树的高度

    void TravelInfixorder(TreeNode<T>* _root) const;          //中序遍历-》深度优先遍历
    void ExtentTravel(TreeNode<T>* _root) const;              //广度优先遍历
};

    通过上面的代码我们可以看到AVL树的成员函数,在这里要说一下,为什么把所有的函数分为private:和public:这两类,是因为这样符合封装性。再说一下写获取树高度的内联函数的原因,因为在插入或者删除后都要根据左右子树高度差来判断当前AVL树有没有失去平衡。写这个函数最重要的原因是对传入的Node进行了是否为NULL的判断是NULL则返回0,如果写程序的时候直接用Node->lc->height来获取左子树的高度,如果左子树为NULL的话就会报段错误,这种错误编译过程是检查不出来的。

平衡二叉树最重要的就是插入和删除函数,而精髓就是对于四中不平衡情况的旋转&#

平衡二叉树AVL树)是一种自平衡的二叉搜索树,它的左右子树的高度差不超过1。下面是一个非递归实现平衡二叉树C++代码示例: ```cpp #include <iostream> #include <stack> using namespace std; struct TreeNode { int val; int height; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), height(1), left(NULL), right(NULL) {} }; int getHeight(TreeNode* node) { if (node == NULL) { return 0; } return node->height; } int getBalanceFactor(TreeNode* node) { if (node == NULL) { return 0; } return getHeight(node->left) - getHeight(node->right); } TreeNode* rotateLeft(TreeNode* node) { TreeNode* newRoot = node->right; node->right = newRoot->left; newRoot->left = node; node->height = max(getHeight(node->left), getHeight(node->right)) + 1; newRoot->height = max(getHeight(newRoot->left), getHeight(newRoot->right)) + 1; return newRoot; } TreeNode* rotateRight(TreeNode* node) { TreeNode* newRoot = node->left; node->left = newRoot->right; newRoot->right = node; node->height = max(getHeight(node->left), getHeight(node->right)) + 1; newRoot->height = max(getHeight(newRoot->left), getHeight(newRoot->right)) + 1; return newRoot; } TreeNode* insert(TreeNode* root, int val) { if (root == NULL) { return new TreeNode(val); } if (val < root->val) { root->left = insert(root->left, val); } else if (val > root->val) { root->right = insert(root->right, val); } else { return root; // 不允许插入重复的节点 } root->height = max(getHeight(root->left), getHeight(root->right)) + 1; int balanceFactor = getBalanceFactor(root); if (balanceFactor > 1 && val < root->left->val) { return rotateRight(root); } if (balanceFactor < -1 && val > root->right->val) { return rotateLeft(root); } if (balanceFactor > 1 && val > root->left->val) { root->left = rotateLeft(root->left); return rotateRight(root); } if (balanceFactor < -1 && val < root->right->val) { root->right = rotateRight(root->right); return rotateLeft(root); } return root; } void inorderTraversal(TreeNode* root) { if (root == NULL) { return; } stack<TreeNode*> s; TreeNode* curr = root; while (curr != NULL || !s.empty()) { while (curr != NULL) { s.push(curr); curr = curr->left; } curr = s.top(); s.pop(); cout << curr->val << " "; curr = curr->right; } } int main() { TreeNode* root = NULL; int arr[] = {3, 2, 4, 5, 6, 1}; int n = sizeof(arr) / sizeof(arr[0]); for (int i = 0; i < n; i++) { root = insert(root, arr[i]); } cout << "Inorder traversal of the AVL tree: "; inorderTraversal(root); return 0; } ``` 这段代码实现平衡二叉树的插入操作,并通过中序遍历打印出了平衡后的树节点值。你可以根据需要进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值