views:

59

answers:

0

Hello all,

I am doing an STL-like AA-tree as a personal project and am running into some trouble. Chopping out the loop containing the skew and split functions gives a working and correct unbalanced binary search tree. However, once the loop is included it goes into an infinite loop. I am trying to insert the numbers 0 to 49 and the skew() and split() loop becomes when 6 is being inserted (The numbers are being inserted in order).

Aside from the infinite loop problem, I have checked the skew() and split() functions repeatedly and, while it looks correct, I suspect there is a problem when the nodes' parents are being set in both functions. I've been pulling my hair out over this. I certainly give my respect to the authors and maintainers of the various STL implementations. Any corrections or help would be much appreciated.

Some notes:

The comparison function being used is essentially the same as std::less. Uses the idiom comp(value1, value2) returning a 0 or 1 to branchlessly calculate the direction that should be taken when traversing the tree, like so: p_node->p_child[comp(value1, value2)];

    //Inserts value into a tree regardless of whether there are duplicates
template <typename Key, typename Value, typename Compare, class Allocator>
typename aa_tree<Key, Value, Compare, Allocator>::iterator 
aa_tree<Key, Value, Compare, Allocator>::insert_duplicate(const value_type &value)
{
    if(anchor.p_parent != &null_node) {
        node_type *p_trv = static_cast<node_type *>(anchor.p_parent);
        node_type *p_parent = static_cast<node_type *>(&null_node);

        while(p_trv != &null_node) {
            p_parent = p_trv;
            p_trv = static_cast<node_type *>(p_trv->p_child[comp(p_trv->value, value)]); //>= move to the right
        }

        node_type *p_node = create_node();
        powerstd_helper::construct(&(p_node->value), value);
        p_node->p_parent = p_parent;
        p_parent->p_child[comp(p_parent->value, value)] = p_node; // >= goes to the right

//The problem is here with the skew and split functions. Chopping this out gives a correct unbalanced BST.

        base_type *p_trv2 = static_cast<base_type *>(p_parent);
        while(p_trv2 != &null_node) {
            skew(p_trv2, &anchor);
            split(p_trv2, &anchor);
            p_trv2 = p_trv2->p_parent;
        }

        return iterator(p_node);
    }

    node_type *p_node = create_node();
    powerstd_helper::construct(&(p_node->value), value);
    p_node->p_parent = &null_node;

    ++tree_size;

    //set root (p_parent), leftmost (p_child[0]), rightmost (p_child[1])
    anchor.p_child[0] = anchor.p_child[1] = anchor.p_parent = static_cast<base_type *>(p_node);

    return iterator(p_node);
}
    #include "aa_tree.hpp"

//maintaining the leftmost and rightmost not done yet
void powerstd_aa_tree::skew(aa_node_base *&p_tree, aa_node_base *p_anchor) //modifies p_root
{
    if(p_tree->p_child[0] != &null_node && p_tree->p_child[0]->level == p_tree->level) {
        aa_node_base *p_left = p_tree->p_child[0];

        //Set the parents of each node
        p_left->p_child[1]->p_parent = p_tree;
        p_left->p_parent = p_tree->p_parent;
        p_tree->p_parent = p_left;

        if(p_tree == p_anchor->p_parent)
            p_anchor->p_parent = p_left;

        //set the nodes
        p_tree->p_child[0] = p_left->p_child[1];
        p_left->p_child[1] = p_tree;
        p_tree = p_left;
    }
}

void powerstd_aa_tree::split(aa_node_base *&p_tree, aa_node_base *p_anchor) //modifies p_root
{
    if(p_tree != &null_node && p_tree->p_child[1]->p_child[1]->level == p_tree->level) {
        aa_node_base *p_right = p_tree->p_child[1];

        //Set the parents of each node
        p_right->p_child[0]->p_parent = p_tree;
        p_right->p_parent = p_tree->p_parent;
        p_tree->p_parent = p_right;

        if(p_tree == p_anchor->p_parent)
            p_anchor->p_parent = p_right;

        //set the nodes
        p_right->p_child[1] = p_right->p_child[0];
        p_right->p_child[0] = p_tree;
        p_tree = p_right;
        ++(p_right->level);
    }
}