Part 3-- tree data structure of a balanced binary tree (AVL tree)

Introduced

Previous wrote a binary sort tree , build a binary sort tree, if the building is completely ordered sequence, such a situation occurs:

Obviously, this situation will make a binary search tree degenerate into a linked list. When this happens, look for binary sort tree it devolved into a linear search, so we need to rationalize the form of binary sort tree such that each node of the tree as much as possible has two child nodes, so that the entire the height of the binary tree will be approximately \ (log (n) \) , of which the \ (n-\) is the number of nodes.

Basic properties

AVL tree is also known as a balanced binary tree, is a self-balancing binary sort tree, is still essentially a binary sort tree, but adds requirements "balance", balance refers to any node on the AVL tree the absolute value of the difference in height between the two sub-trees (called balance factor) does not exceed \ (1 \) . This is to ensure the above, AVL height of the tree will be able to remain in the \ (O (logn) \) level.

Data structure definition

Since each node needs to have been balanced by the factor, so add a variable in the AVL tree structure heightis used to record the current node is the root of the subtree Height:

typedef struct Node
{
    char data;
    int height;
    struct Node* Left;
    struct Node* Right;
}*AVLTree;

Gets rootnode height:

int getHeight(Node *root){
    if(!root) return 0;//空节点高度为0
    return root->height;
}

Basic Operations

Seek

AVL tree is a binary search tree, so the search operation with the same binary search tree. Since the height of an AVL tree is \ (O (logn) \) level, so the search operation time complexity is \ (O (logn) \) .

You can get a binary search tree and the exact same code:

//找不到返回NULL,找到返回该节点。
//非递归
Node* Find(AVLTree t, int x) {
    if (!t)return NULL;
    if (t->data == x) return t;
    if (x < t->data) return BSTreeFind(t->Left, x);
    if (x > t->data) return BSTreeFind(t->Right, x);
}
//非递归
Node* Find(AVLTree T,int x) {
    BSTree p = T;
    while (p) {
        if (x == p->data)
            return p;
        p = x > p->data ? p->Right : p->Left;
    }
    return NULL;
}

insert

L

Put aside the problem of insertion AVL tree, watching binary sort tree below the left. We had peaceful coexistence, suddenly one day feel the weight B is greater than A, to rebel, but do root node B, must also ensure that the tree after the adjustment is still a binary sort tree.

☆ little value on ownership than A, Δ is greater than B on ownership, without change in the position of adjustment; because the children left after adjustment B into the A, then ▲ must be moved to other places, because A, value relationship right B, ▲ satisfies a <▲ <B, so let become ▲ a right subtree can be.

This adjustment process is referred to as L , the decomposition process is adjusted as follows:

code show as below:

void L(AVLTree *root){
    Node* temp = (*root)->Right; //root指向结点A,temp指向结点B
    (*root)->Right = temp->Left; //图示步骤2
    temp->Left = *root; //图示步骤3
    root->height = max(getHeight(root->Left), getHeight(root->Rihgt)) + 1;//更新结点A高度
    temp = max(getHeight(temp->Left), getHeight(temp->Rihgt)) + 1;//更新结点B高度
    *root = temp;//图示步骤4
}

Right-handed

Right-handed left-handed is the reverse process, as follows:

Adjusting the decomposition process is as follows:

code show as below:

void R(AVLTree *root) {
    Node* temp = (*root)->Left;//root指向结点B,temp指向结点A
    (*root)->Left = temp->Right;
    temp->Right = *root;
    root->height = max(getHeight(root->Left), getHeight(root->Rihgt)) + 1;
    temp = max(getHeight(temp->Left), getHeight(temp->Rihgt)) + 1;
    *root = temp;
}

AVL tree discussed next insertion operation, assuming now has a balanced binary tree, then a node is inserted thereto, there will be a junction point of the balance factor is changed, then there might be a node balance factor is greater than 1, such as the node to the root node of the subtree is unbalanced, where an imbalance will balanced binary tree can be divided into the following four:

LL、RR型

Zuozuo (LL), right right (RR), LL, RR only that tree (the tree lead to loss of balance of insertion position) is not left-handed, right-handed means.

img

For the LL-type, need to be the root node A right-handed;

For RR type A need to be left for the root node.

So the code is as follows:

void RR_Rotate(AVLTree *root){
    L(root);
}

void LL_Rotate(AVLTree *root) {
    R(root);
}

LR,RL型

Left and right (LR), right-left (RL).

img

For LR type B need to be a root node for the L, then A is the root node for a right-handed.

For RL type B need to be a root node for the right-handed, then A is the root node for a left-handed.

void LR_Rotate(AVLTree *root) {
    L(&(*root)->Left);
    R(root);
}
void RL_Rotate(AVLTree *root) {
    R(&(*root)->Right);
    L(root);
}

Insertion junction

When the insertion algorithm is imbalance state, which is determined such that the rotation requires the use of a binary tree to balance

AVLTree InsertAVLTree(AVLTree root, int x) {
    if (root == NULL) {
        root = new Node;
        root->Left = NULL;
        root->Right = NULL;
        root->data = x;
        return root;
    }
    if (x > root->data) { 
            //递归返回插入位置的父节点或者祖父……。
            root->Right = InsertAVLTree(root->Right, x); 
            //如果插入之后失去了平衡
            if (height(root->Left) - height(root->Right) == -2) {
                //如果插入的值大于,当前节点的左孩子节点,说明该节点是插在root的右子树上的
                if (x > root->Left->data) RR_Rotate(&root);
                else RL_Rotate(&root);
            }
    }

    else if (x < root->data) {
        root->Left = InsertAVLTree(root->Left, x);
        if (height(root->Left) - height(root->Right) == 2) {
            if (x < root->Left->data) LL_Rotate(&root);
            else LR_Rotate(&root);
        }
    }
    else { 
        cout << "the number is already included." << endl;
        return NULL; 
    }
    return root;
}

Delete Node

And removing nodes is a binary tree sort of almost, that is more out of a tall tree from which judgment delete nodes.

void AVLTreeDel(AVLTree *root, int data)
{
    if (!*root) {
        cout << "delete failed" << endl;
        return;
    }
    Node *p = *root;  
    if (data == p->data) {
        //左右子树都非空  
        if (p->Left && p->Right) {
            //在高度更大的那个子树上进行删除操作
            //进左子树,右转到底,进右子树,左转到底,转弯碰壁,杀孩子。
            if (height(p->Left) > height(p->Right)) {
                Node *pre=NULL,*q = p->Left;
                if (!q->Right)
                    q->Right = p->Right;
                else {
                    while (q->Right) {
                        pre = q;
                        q = q->Right;
                    }
                    pre->Right = q->Left;
                    q->Left = p->Left;
                    q->Right = p->Right;
                }
                *root = q;
            }
            else {
                Node *pre = NULL, *q = p->Right;
                if (!q->Left)
                    q->Left = p->Left;
                else {
                    while (q->Left) {
                        pre = q;
                        q = q->Left;
                    }
                    pre->Left = q->Right;
                    q->Left = p->Left;
                    q->Right = p->Right;
                }
                *root=q;
            }
        }
        else 
            (*root) = (*root)->Left ? (*root)->Left : (*root)->Right;
        delete p;
    }
    else if (data < p->data){//要删除的节点在左子树中  
        //在左子树中进行递归删除  
        AVLTreeDel(&(*root)->Left, data);
        //判断是否仍然满足平衡条件  
        if (height(p->Right) - height(p->Left) == 2){
            //如果当前节点右孩子的左子树更高
            if (height(p->Right->Left) > height(p->Right->Right))
                RL_Rotate(root);
            else  
                RR_Rotate(root);
        }
    }
    else{
        AVLTreeDel(&(*root)->Right, data);
        if (height(p->Left) - height(p->Right) == 2) {
            if (height((*root)->Left->Left) > height((*root)->Left->Right))
                LL_Rotate(root);
            else
                LR_Rotate(root);
        }
    }
}

Complete test code:

#pragma once
#include "top.h"

typedef BTreeNode Node, *AVLTree;

void RR_Rotate(AVLTree *root){
    Node* Right = (*root)->Right;
    (*root)->Right = Right->Left;
    Right->Left = *root;
    *root = Right;
}

void LL_Rotate(AVLTree *root) {
    Node* Left = (*root)->Left;
    (*root)->Left = Left->Right;
    Left->Right = *root;
    *root = Left;
}
void LR_Rotate(AVLTree *root) {
    RR_Rotate(&(*root)->Left);
    return LL_Rotate(root);
}
void RL_Rotate(AVLTree *root) {
    LL_Rotate(&(*root)->Right);
    RR_Rotate(root);
}
AVLTree AVLTreeInsert(AVLTree root, int x) {
    if (root == NULL) {
        root = new Node;
        root->Left = NULL;
        root->Right = NULL;
        root->data = x;
        return root;
    }
    if (x > root->data) { 
            root->Right = AVLTreeInsert(root->Right, x); 
            //递归返回插入位置的父节点或者祖父……,如果失去了平衡
            if (height(root->Left) - height(root->Right) == -2) {
            //如果插入的值大于,当前节点的右孩子节点,说明该节点是插在root的右子树上的
                //if (x > root->Left->data) RR_Rotate(&root);不能保证该节点一定有左子树
                if (x > root->Right->data)RR_Rotate(&root);
                else RL_Rotate(&root);
            }
    }
    else if (x < root->data) {
        root->Left = AVLTreeInsert(root->Left, x);
        if (height(root->Left) - height(root->Right) == 2) {
            if (x < root->Left->data) LL_Rotate(&root);
            else LR_Rotate(&root);
        }
    }
    else { 
        cout << "the number is already included." << endl;
        return NULL; 
    }
    return root;
}

AVLTree AVLTreeCreat(int *a, int length) {
    AVLTree T = NULL;
    for (int i = 0; i < length; i++) {
        T = AVLTreeInsert(T, a[i]);
    }
    return T;
}
Node* AVLFind(AVLTree T, int x) {
    Node *p = T;
    while (p) {
        if (x == p->data) break;
        p = x > p->data ? p->Right : p->Left;
    }
    return p;
}

AVLTree AVLMax(AVLTree p)
{
    if (!p) return NULL;
    if (p->Right == NULL)
        return p;
    return AVLMax(p->Right);
}

AVLTree AVLMin(AVLTree p)
{
    if (!p)
        return NULL;
    if (p->Left == NULL)
        return p;
    return AVLMin(p->Left);
}

void AVLTreeDel(AVLTree *root, int data)
{
    if (!*root) {
        cout << "delete failed" << endl;
        return;
    }
    Node *p = *root;  
    if (data == p->data) {
        //左右子树都非空  
        if (p->Left && p->Right) {
            //在高度更大的那个子树上进行删除操作
            //进左子树,右转到底,进右子树,左转到底,转弯碰壁,杀孩子。
            if (height(p->Left) > height(p->Right)) {
                Node *pre=NULL,*q = p->Left;
                if (!q->Right)
                    q->Right = p->Right;
                else {
                    while (q->Right) {
                        pre = q;
                        q = q->Right;
                    }
                    pre->Right = q->Left;
                    q->Left = p->Left;
                    q->Right = p->Right;
                }
                *root = q;
            }
            else {
                Node *pre = NULL, *q = p->Right;
                if (!q->Left)
                    q->Left = p->Left;
                else {
                    while (q->Left) {
                        pre = q;
                        q = q->Left;
                    }
                    pre->Left = q->Right;
                    q->Left = p->Left;
                    q->Right = p->Right;
                }
                *root=q;
            }
        }
        else 
            (*root) = (*root)->Left ? (*root)->Left : (*root)->Right;
        delete p;
    }
    else if (data < p->data){//要删除的节点在左子树中  
        //在左子树中进行递归删除  
        AVLTreeDel(&(*root)->Left, data);
        //判断是否仍然满足平衡条件  
        if (height(p->Right) - height(p->Left) == 2){
            //如果当前节点右孩子的左子树更高
            if (height(p->Right->Left) > height(p->Right->Right))
                RL_Rotate(root);
            else  
                RR_Rotate(root);
        }
    }
    else{
        AVLTreeDel(&(*root)->Right, data);
        if (height(p->Left) - height(p->Right) == 2) {
            if (height((*root)->Left->Left) > height((*root)->Left->Right))
                LL_Rotate(root);
            else
                LR_Rotate(root);
        }
    }
}

int height(BTree L) {
    if (L == NULL)
        return 0;
    int left = height(L->Left);
    int right = height(L->Right);
    return left >= right ? left + 1 : right + 1;
}

void checkCreat() {
    int length = 10;
    int *a = getNoRepateRandomArray(length, 10);

    for (int i = 0; i < length; i++) {
        cout << a[i] << ",";
    }
        
    cout << endl;
    AVLTree T = AVLTreeCreat(a, length);
    int t = rand() % length;
    AVLTreeDel(&T, a[t]);
    for (int i = t; i < length - 1; i++) {
        a[i] = a[i + 1];
    }
    
    Preorder(T);
    cout << endl;
    Inorder(T);
    cout << endl;
    Postorder(T);
    cout << endl;
    free(a);
}

Guess you like

Origin www.cnblogs.com/czc1999/p/11794808.html