AVL树的实现(C++)

首先定义节点:

#include<stdio.h>
#include<stdlib.h>
#include<cstring>

class Node
{
public:
    Node(int d);
    Node(Node* other);
    int data;
    int height;
    int distance;
    Node* leftChild;
    Node* rightChild;
    Node* father;
    int calculateDistance();
    int calculateheight();
};

Node::Node(int d)
{
    this->data = d;
    father = NULL;
    leftChild = NULL;
    rightChild = NULL;
    height = 1;
    distance = 0;
}

Node::Node(Node* other)
{
    this->data = other->data;
    this->distance = other->distance;
    this->father = other->father;
    this->height = other->height;
    this->leftChild = other->leftChild;
    this->rightChild = other->rightChild;
}

int Node::calculateDistance()
{
    int leftHeight;
    int rightHeight;

    leftHeight = leftChild == NULL? 0 : leftChild->height;
    rightHeight = rightChild == NULL? 0 : rightChild->height;

    return leftHeight-rightHeight;
}

int Node::calculateheight()
{
    int leftHeight;
    int rightHeight;

    leftHeight = leftChild == NULL? 0 : leftChild->height;
    rightHeight = rightChild == NULL? 0 : rightChild->height;

    if(leftHeight > rightHeight)
        return leftHeight+1;
    else
        return rightHeight+1;
}

这里有计算左右子树高度差的函数,左子树高度-右子树的高度。

还有计算该节点在树中的高度,在左右子树的更高者的基础上加1。

然后定义二叉平衡树:

#include"Node.h"

class Tree
{
public:
    Tree();
    void insert(int data);
    bool delete_node(int data);
    int size();
    void display();
private:
    void right_rotate(Node* target);
    void left_rotate(Node* target);
    void pre_order(Node* cur);
    Node* root;
    int count;
};

Tree::Tree()
{
    root = NULL;
    count = 0;
}

void Tree::insert(int data)
{
    if(root == NULL)
        root = new Node(data);
    else
    {
        Node* current = root;
        Node* pre = NULL;
        while(current != NULL)
        {
            pre = current;
            if(data <= current->data)
                current = current->leftChild;
            else
                current = current->rightChild;
        }
        Node* newNode = new Node(data);
        if(data <= pre->data)
            pre->leftChild = newNode;
        else
            pre->rightChild = newNode;  
        newNode->father = pre;
        Node* fatherNode = pre;
        current = newNode;
        while(pre != NULL)
        {
            pre->height = pre->calculateheight();
            pre->distance = pre->calculateDistance();
            if(pre->distance == 2)
            {
                if(pre->leftChild->distance == 1)
                {
                    right_rotate(pre);
                    pre = pre->father;
                }
                if(pre->leftChild->distance == -1)
                {
                    left_rotate(pre->leftChild);
                    right_rotate(pre);
                    pre = pre->father;
                }
            //	pre = pre->father;
            }
            if(pre->distance == -2)
            {
                if(pre->rightChild->distance == -1)
                {
                    left_rotate(pre);
                    pre = pre->father;
                }
                if(pre->rightChild->distance == 1)
                {
                    right_rotate(pre->rightChild);
                    left_rotate(pre);
                    pre = pre->father;
                }
                
            }
            current = pre;
            pre = pre->father;
        }
        
    }

    count++;
}

void Tree::left_rotate(Node* target)
{
    Node* tempUp = target->rightChild;
    Node* tempLeft2Right = tempUp->leftChild;

    Node* top = target->father;
    Node* up = new Node(tempUp);
    if(tempUp->leftChild != NULL)
        tempUp->leftChild->father = up;
    if(tempUp->rightChild != NULL)
        tempUp->rightChild->father = up;

    Node* left2right;
    if(tempLeft2Right != NULL)
    {
        left2right = new Node(tempLeft2Right);
        if(tempLeft2Right->leftChild != NULL)
            tempLeft2Right->leftChild->father = left2right;
        if(tempLeft2Right->rightChild != NULL)
            tempLeft2Right->rightChild->father = left2right;
    }
    else
        left2right = NULL;

    if(top != NULL)
    {
        if(top->leftChild == target)
            top->leftChild = up;
        else
            top->rightChild = up;
    }
    up->father = top;
    up->leftChild = target;
    target->father = up;
    target->rightChild = left2right;
    if(left2right != NULL)
        left2right->father = target;

    target->height = target->calculateheight();
    target->distance = target->calculateDistance();
    up->height = up->calculateheight();
    up->distance = up->calculateDistance();
    top->height = top->calculateheight();
    top->distance = top->calculateDistance();

    delete(tempUp);
    delete(tempLeft2Right);

//	target = target->father;

}

void Tree::right_rotate(Node* target)
{
    Node* tempUp = target->leftChild;
    Node* tempRight2Left = tempUp->rightChild;

    Node* top = target->father;
    Node* up = new Node(tempUp);

    if(tempUp->leftChild != NULL)
        tempUp->leftChild->father = up;
    if(tempUp->rightChild != NULL)
        tempUp->rightChild->father = up;
    Node* right2left;

    if(tempRight2Left != NULL)
    {
        right2left = new Node(tempRight2Left);
        if(tempRight2Left->leftChild != NULL)
            tempRight2Left->leftChild->father = right2left;
        if(tempRight2Left->rightChild != NULL)
            tempRight2Left->rightChild->father = right2left;
    }
    else
        right2left = NULL;

    if(top != NULL)
    {
        if(top->leftChild == target)
            top->leftChild = up;
        else
            top->rightChild = up;
    }
    up->father = top;
    up->rightChild = target;
    target->father = up;
    target->leftChild = right2left;
    if(right2left != NULL)
        right2left->father = target;

    target->height = target->calculateheight();
    target->distance = target->calculateDistance();
    up->height = up->calculateheight();
    up->distance = up->calculateDistance();
    top->height = top->calculateheight();
    top->distance = top->calculateDistance();

    delete(tempUp);
    delete(tempRight2Left);

}

int Tree::size()
{
    return count;
}

void Tree::display()
{
    pre_order(root);
}

void Tree::pre_order(Node* cur)
{
    if(cur != NULL)
    {
        pre_order(cur->leftChild);
        printf("%d\n", cur->data);
        pre_order(cur->rightChild);
    }
}

二叉平衡树的关键是,它能够在插入所有元素之后保持平衡,左右子树的高度差不会超过1。所以在每次插入完元素后,检查二叉平衡树是否平衡。只要从插入点开始检查,一直往树的根端检查即可。(其实只需检查一个点)然后确定需要哪种旋转,是单旋转还是双旋转。这里,我用了新的指针来代表旋转所得的新位置。注意指针的指向的改变。

    原文作者:AVL树
    原文地址: https://blog.csdn.net/kuangwanjing626/article/details/8025732
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞