Что не так с этим кодом балансировки AVL? - PullRequest
0 голосов
/ 13 октября 2010

Каждый раз, когда я использую эту функцию avlRotate, она удаляет некоторые элементы из дерева.z - узел, в котором был обнаружен дисбаланс, y - узел его поддерева, имеющий большую высоту, x - вновь вставленный узел.Эта функция вызывается сразу после одиночной вставки.

#define RESTRUCTURE  a->left = t0; a->right = t1; c->left = t2; c->right = t3; b->left = a; b->right = c;

avlTree avlRotate(avlTree z,avlTree y,avlTree x)
{
    avlTree a,b,c;  
    avlTree t0,t1,t2,t3;

    if(y==z->left && x==y->left)  //single rotation
    {
        a=x;b=y;c=z;
        t0=a->left;
        t1=a->right;
        t2=b->right;
        t3=c->right;
        RESTRUCTURE
        c->height[0] = y->height[1];

    }
    else if(y==z->right && x==y->right) //single rotation
    {
        a=z;b=y;c=x;
        t0=a->left;
        t1=b->left;
        t2=c->left;
        t3=c->right;
        RESTRUCTURE
        a->height[1] = y->height[0];

    }
    else if(y==z->right && x==y->left)  //double rotation
    {
        a=z;b=x;c=y;
        t0=a->left;
        t1=b->left;
        t2=b->right;
        t3=c->right;
        RESTRUCTURE
        a->height[1] = x->height[0];
        c->height[0] = x->height[1];
    }
    else if(y==z->left && x==y->right)  //double rotation
    {
        a=y;b=x;c=z;
        t0=a->left;
        t1=b->left;
        t2=b->right;
        t3=c->right;
        RESTRUCTURE
        a->height[1] = x->height[0];
        c->height[0] = x->height[1];    
    }

    printf("\nRem parts:\n");
    printf("{%d %d} {%d %d} {%d %d}\n",a->part->range[0],a->part->range[1],b->part->range[0],b->part->range[1],c->part->range[0],c->part->range[1]);
    printf("\n\n");

    b->height[0] = ( (a->height[0] > a->height[1]) ? (a->height[0])+1 : (a->height[1])+1 ); 
    b->height[1] = ( (c->height[0] > c->height[1]) ? (c->height[0])+1 : (c->height[1])+1 ); 
    a->balFactor = a->height[0] - a->height[1];
    b->balFactor = b->height[0] - b->height[1];
    c->balFactor = c->height[0] - c->height[1]; 
    return(b);
}

Функция вызывается с помощью:

if(a->balFactor > 1 || a->balFactor < -1)
    {
        printf("imbalance fside=%d pside=%d\n",*finalSide,*prevSide);

        if(*finalSide == 0)
        {yLike = a->left;}
        else
        {yLike = a->right;}
        if(*prevSide == 0)
        {xLike = yLike->left;}
        else
        {xLike = yLike->right;}
        printf("passing to rotate %u %u %u\n",a,yLike,xLike);
        printf("{%d %d} {%d %d} {%d %d}\n",a->part->range[0],a->part->range[1],yLike->part->range[0],yLike->part->range[1],xLike->part->range[0],xLike->part->range[1]);
        a = avlRotate(a,yLike,xLike);
        avlInOrderTraversal(a,0);           
        printf("{%d %d} {%d %d} {%d %d}\n",a->left->part->range[0],a->left->part->range[1],a->part->range[0],a->part->range[1],a->right->part->range[0],a->right->part->range[1]);
    }

в функции вставки.

Выход:

a->height[0]=1 a->height[1]=0
BALANCE FACTOR = 1



    16 to 18
51 to 53



a->height[0]=0 a->height[1]=1
BALANCE FACTOR = -1
a->height[0]=2 a->height[1]=0
BALANCE FACTOR = 2
imbalance fside=0 pside=1
passing to rotate 147992552 147992584 147992616
{51 53} {16 18} {41 41}

Rem parts:
{16 18} {41 41} {51 53}





51 to 53



a->height[0]=0 a->height[1]=1
BALANCE FACTOR = -1



51 to 53
    60 to 61



a->height[0]=1 a->height[1]=1
BALANCE FACTOR = 0



    4 to 6
51 to 53
    60 to 61

Что-то явно не так с этой функцией?

Примечание: Каждый узел хранит диапазон, например.3 to 5.

Ответы [ 2 ]

1 голос
/ 13 октября 2010

В Интернете существует множество ресурсов по дереву AVL, среди которых есть несколько:

  1. http://en.wikipedia.org/wiki/AVL_tree
  2. C реализация: http://www.stanford.edu/~blp/avl/libavl.html
  3. Анимация : http://www.cs.jhu.edu/~goodrich/dsa/trees/avltree.html
  4. Анимация : http://www.strille.net/works/media_technology_projects/avl-tree_2001/

Продолжая Пустой ответ Ксавьера , далее , я бы предложил сравнить вывод дампа вашей программы с результатами анимации .

1 голос
/ 13 октября 2010

Напишите функцию для дампа вашего дерева.Для каждого узла покажите, что он думает: его глубина левого, правого, верхнего и левого / правого поддеревьев.

Дамп дерева перед поворотом, а затем после.написал мой.

У вас - в дереве будут тонкие ошибки - обращение к SO по каждой проблеме не даст вам быстрых результатов.Вам также понадобится функция дампа для отладки перебалансировки при подъеме по дереву - существует ряд уникальных случаев перебалансировки для добавления и удаления, которые вы должны проверить.Все это требует дампа дерева.

...