平衡二叉树

平衡二叉树的定义(AVL)

  1. 该二叉树为二叉搜索树,即每个节点的左孩子的值比该节点小,右孩子的值比该节点大。
  2. 该树每个节点的平衡因子的值的绝对值不超过1,节点的平衡因子定义为该节点左子树的高度减去该节点右子树的高度。

节点结构 

1 typedef struct Node
2 {
3     int data;
4     int height;
5     
6     struct Node *left;
7     struct Node *right;
8     struct Node *parent;
9 }NODE,*PNODE;

插入节点后的失衡和调整

最小失衡子树

    在新插入的结点向上查找,以第一个平衡因子的绝对值超过 1 的结点为根的子树称为最小不平衡子树。也就是说,一棵失衡的树,是有可能有多棵子树同时失衡的。而这个时候,我们只要调整最小的不平衡子树,就能够将不平衡的树调整为平衡的树。

获得每个节点高度的代码

 1 int update_height(PNODE node)
 2 {
 3     if(node == NULL)
 4     {
 5         return 0;
 6     }
 7     else
 8     {
 9         int height_left = update_height(node->left);
10         int height_right = update_height(node->right);
11         node->height = (height_left >= height_right ? height_left : height_right) + 1;
12         return node->height;
13     }
14 }

获得某节点平衡因子的代码

int get_factor(PNODE node)
{
    if(node->left != NULL&&node->right != NULL)
    return node->left->height - node->right->height;
    else if(node->left != NULL)
    return node->left->height;
    else if(node->right != NULL)
    return -node->right->height;
    else
    return 0;
}  

寻找最小失衡子树的根节点代码

1 PNODE get_first(PNODE node)
2 {
3     while(node != NULL&&get_factor(node) <= 1&&get_factor(node) >= -1)
4     {
5         node = node->parent;
6     }
7     return node;
8 }

调整策略1-左旋

    (1)节点的右孩子替代此节点位置 (2)右孩子的左子树变为该节点的右子树 (3)节点本身变为右孩子的左子树

void L_rotate(PNODE node)
{
    PNODE rson = NULL,parent = NULL;
    
    rson = node->right;
    parent = node->parent;
    
    node->right = rson->left;
    if(rson->left != NULL)
    {
        rson->left->parent = node;
    }
    
    rson->left = node;
    node->parent = rson;
    
    rson->parent = parent;
    if(parent != NULL)
    {
        if(parent->left == node)
        {
            parent->left = rson;
        }
        else
        {
            parent->right = rson;
        }
    } 
    
    update_height(node);
    update_height(rson);
}

调整策略2-右旋

    (1)节点的左孩子代表此节点 (2)节点的左孩子的右子树变为节点的左子树 (3)将此节点作为左孩子节点的右子树。

 1 void R_rotate(PNODE node)
 2 {
 3     PNODE lson = NULL,parent = NULL;
 4     
 5     lson = node->left;
 6     parent = node->parent;
 7     
 8     node->left = lson->right;
 9     if(lson->right != NULL)
10     {
11         lson->right->parent = node;
12     }
13     
14     lson->right = node;
15     node->parent = lson;
16     
17     lson->parent = parent;
18     if(parent != NULL)
19     {
20         if(parent->left == node)
21         {
22             parent->left = lson;
23         }
24         else
25         {
26             parent->right = lson;
27         }
28     } 
29     
30     update_height(node);
31     update_height(lson);
32 }

 

节点的几种插入情况

情况1

    插入某节点的左孩子的左子树导致该节点失衡

策略

    对该节点进行一次右旋即可

 

情况2

    插入某节点的右孩子的右子树导致该节点失衡

策略

    对该节点进行一次左旋即可

 

情况3

    插入某节点的左孩子的右子树导致该节点失衡

策略

    对该节点的左孩子进行一次左旋,然后对该节点经行一次右旋

 

情况4

    插入某节点的右孩子的左子树导致该节点失衡

策略

    对该节点的右孩子进行一次右旋,然后对该节点经行一次左旋

代码

 1 void balance(PNODE node)
 2 {
 3     PNODE p = get_first(node);
 4     
 5     if(p == NULL)
 6     {
 7         return;
 8     }
 9     else
10     {
11         int factor = get_factor(p);
12         if(factor > 0)
13         {
14             factor = get_factor(p->left);    
15             if(factor > 0)//在左孩子的左子树插入节点 
16             {
17                 R_rotate(p);
18             }
19             else//在左孩子的右子树插入节点 
20             {
21                 L_rotate(p->left);
22                 R_rotate(p); 
23             }
24         }
25         else
26         {
27             factor = get_factor(p->right);
28             if(factor < 0)//在右孩子的右子树插入节点
29             {
30                 L_rotate(p); 
31             }
32             else//在右孩子的左子树插入节点 
33             {
34                 R_rotate(p->right);
35                 L_rotate(p);
36             } 
37         }
38     }    
39 }

完整代码(C)

#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#include<queue> 

#define SIZE 3

using namespace std;

typedef struct Node
{
    int data;
    int height;
    
    struct Node *left;
    struct Node *right;
    struct Node *parent;
}NODE,*PNODE; 

//更新节点的高度
int update_height(PNODE node)
{
    if(node == NULL)
    {
        return 0;
    }
    else
    {
        int height_left = update_height(node->left);
        int height_right = update_height(node->right);
        node->height = (height_left >= height_right ? height_left : height_right) + 1;
        return node->height;
    }
}

//获得节点的平衡因子
int get_factor(PNODE node)
{
    if(node->left != NULL&&node->right != NULL)
    return node->left->height - node->right->height;
    else if(node->left != NULL)
    return node->left->height;
    else if(node->right != NULL)
    return -node->right->height;
    else
    return 0;
} 

//右旋
void R_rotate(PNODE node)
{
    PNODE lson = NULL,parent = NULL;
    
    lson = node->left;
    parent = node->parent;
    
    node->left = lson->right;
    if(lson->right != NULL)
    {
        lson->right->parent = node;
    }
    
    lson->right = node;
    node->parent = lson;
    
    lson->parent = parent;
    if(parent != NULL)
    {
        if(parent->left == node)
        {
            parent->left = lson;
        }
        else
        {
            parent->right = lson;
        }
    } 
    
    update_height(node);
    update_height(lson);
}

//左旋 
void L_rotate(PNODE node)
{
    PNODE rson = NULL,parent = NULL;
    
    rson = node->right;
    parent = node->parent;
    
    node->right = rson->left;
    if(rson->left != NULL)
    {
        rson->left->parent = node;
    }
    
    rson->left = node;
    node->parent = rson;
    
    rson->parent = parent;
    if(parent != NULL)
    {
        if(parent->left == node)
        {
            parent->left = rson;
        }
        else
        {
            parent->right = rson;
        }
    } 
    
    update_height(node);
    update_height(rson);
}

//获得距离插入节点最近的第一个非平衡节点
PNODE get_first(PNODE node)
{
    while(node != NULL&&get_factor(node) <= 1&&get_factor(node) >= -1)
    {
        node = node->parent;
    }
    return node;
}

//插入节点并维持树的平衡 
PNODE insert(PNODE *root,PNODE father,int key)
{
    if(*root == NULL)
    {
        *root = (PNODE)malloc(sizeof(NODE));
        (*root)->data = key;
        (*root)->left = NULL;
        (*root)->right = NULL;
        (*root)->parent = father;
        
        return *root;        
    }
    else
    {
        if(key > (*root)->data)
        {
            insert(&(*root)->right,*root,key);
        }
        else if(key < (*root)->data)
        {
            insert(&(*root)->left,*root,key);
        }
    }
    
} 

//插入节点后通过旋转调节二叉树

void balance(PNODE node)
{
    PNODE p = get_first(node);
    
    if(p == NULL)
    {
        return;
    }
    else
    {
        int factor = get_factor(p);
        if(factor > 0)
        {
            factor = get_factor(p->left);    
            if(factor > 0)//在左孩子的左子树插入节点 
            {
                R_rotate(p);
            }
            else//在左孩子的右子树插入节点 
            {
                L_rotate(p->left);
                R_rotate(p); 
            }
        }
        else
        {
            factor = get_factor(p->right);
            if(factor < 0)//在右孩子的右子树插入节点
            {
                L_rotate(p); 
            }
            else//在右孩子的左子树插入节点 
            {
                R_rotate(p->right);
                L_rotate(p);
            } 
        }
    }    
}

//创建平衡二叉树
void create(PNODE *root,int datas[])
{
    *root = NULL;
    
    for(int i = 0;i < SIZE;i++)
    {
        PNODE p = insert(root,NULL,datas[i]);
        update_height(*root);
        balance(p);
        
        //更新根节点 
        while((*root)->parent != NULL)
        {
            *root = (*root)->parent;
        }
    } 
} 

//层序遍历平衡二叉树
void levelTraverse(PNODE pT)
{
    queue<PNODE> que;
    que.push(pT);
    
    while(que.empty() == false)
    {
        printf("%d ",que.front()->data);
        
        if(que.front()->left != NULL)
        {
            que.push(que.front()->left);
        }
        
        if(que.front()->right != NULL)
        {
            que.push(que.front()->right);
        }
        
        que.pop();    
    }
}

int main()
{
    int datas[3] = {1,2,3};
    
    PNODE root;
    
    create(&root,datas);
    
    levelTraverse(root);
    
    return 0;
}

 

 

 

相关文章

这篇文章主要介绍“基于nodejs的ssh2怎么实现自动化部署”的...
本文小编为大家详细介绍“nodejs怎么实现目录不存在自动创建...
这篇“如何把nodejs数据传到前端”文章的知识点大部分人都不...
本文小编为大家详细介绍“nodejs如何实现定时删除文件”,内...
这篇文章主要讲解了“nodejs安装模块卡住不动怎么解决”,文...
今天小编给大家分享一下如何检测nodejs有没有安装成功的相关...