顺序表实现一颗avl树

课本上讲的是用指针建立avl树,但是这种方法速度慢而且指针容易出现各种错误,实在是不是竞赛中的上上选。
现在po上顺序表建立avl树的代码。

#include<iostream>
#include<cstdio>
using namespace std;
struct node
{
    //该节点的储存的值,左子树地址,右子树地址
    int k, l, r, size;//size为该树的重量(包含该节点)
    node()
    {
        k = l = r = 0;
        size = 0;//未被填入数据时,空节点重量为1
    }
}tree[20];
int maxnode=2, root=1;//当前可分配空间的最小节点的下标,maxnode为空,
//root为二叉树的根
void left_x(int &a)//左旋操作
{
    int op = tree[a].r;
    if (a == root) root = op;//若正在旋转的树为整颗子树,需要修改根节点地址
    tree[a].r = tree[op].l;//该节点的右节点=右节点的左节点
    tree[op].l = a;//右节点的左节点=该节点
    //重点***
    //为什么可以这样修改size值
    //此时该子树的层次关系已经修改好,但是树的父节点与该子树的层次关系还未修改
    //在子树中,op代替了原先a的位置,所以op的size是a的size
    tree[op].size = tree[a].size;
    //此时tree[a]节点的左右子节点已经改好,其size值就是他两个子树的size+自己的size
    tree[a].size = tree[tree[a].r].size + tree[tree[a].l].size + 1;
    a = op;//由于使用了引用,参数为某颗树的子树的根节点地址,修改a=op,就是修改子树根节点的地址为op
}
void right_x(int &a)
{
    int op = tree[a].l;
    if (a == root) root = op;
    tree[a].l = tree[op].r;
    tree[op].r = a;
    tree[op].size = tree[a].size;
    tree[a].size = tree[tree[a].r].size + tree[tree[a].l].size + 1;
    a = op;
}
void balance(int &a, bool flag)//平衡子树tree[a],flag为平衡a的左子树(0)还是右子树(1)
{
    if (flag)//平衡右子树,说明插入了a的右子树
    {
        if (tree[tree[tree[a].r].r].size > tree[tree[a].l].size)
            //a的右子树的右子树的重量>a的左子树时,左旋
            left_x(a);
        else if (tree[tree[tree[a].r].l].size > tree[tree[a].l].size)
            //a的右子树的左子树重量>a的左子树时,先对a的右子树右旋,再对a左旋
        {
            right_x(tree[a].r);
            left_x(a);
        }
        else return;
    }
    else
    {
        if (tree[tree[tree[a].l].l].size > tree[tree[a].r].size)
            right_x(a);
        else if (tree[tree[tree[a].l].r].size > tree[tree[a].r].size)
        {
            left_x(tree[a].l);
            right_x(a);
        }
        else return;
    }
}
void insert(int &a,int k)//插入元素,a为插入tree中哪个元素,k为插入的值
//main函数中调用时,将root赋值给另外的变量,再用引用传递进insert
 {
    if ( tree[a].k==0)//tree[a]为新节点时
    {
        tree[a].k = k;
        tree[a].size = 1;//初始化重量
        tree[a].l = maxnode;//为左节点分配空间
        maxnode++;
        tree[a].r = maxnode;
        maxnode++;//将max指针移动到未被连入avl树的空节点处
    }
    else
    {
        tree[a].size++;//要在该树的任意子树中插入,该树的重量+1
        if (k < tree[a].k)
        {
            insert(tree[a].l, k);//插入
            balance(a, 0);//调整该树
        }
        if (k > tree[a].k)
        {
            insert(tree[a].r , k);
            balance(a, 1);
        }
    }

}
int main()
{
    int b[9] = { 1,2,3,4,5,6,7,8,9 };
    for (int i = 0; i < 9; i++)
    {
        int k = root;
        //注意不能直接将root的引用传入insret,否则root的引用可能被传到其他子函数
        //insert->balance->左右旋函数,在左右旋函数中最后会修改引用的值,如果直接将root的引用传入,会改变root的值
        insert(k, b[i]);
    }
    return 0;
}
    原文作者:AVL树
    原文地址: https://blog.csdn.net/qq_39464106/article/details/79174750
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞