yc_bbstree.c

来自「一个类STL的多平台可移植的算法容器库,主要用于嵌入式系统编程时的内存管理等方面」· C语言 代码 · 共 1,490 行 · 第 1/4 页

C
1,490 行
字号
            if( !(uninit_self->m_header.parent) )
                return 0;
            else
            {
                uninit_self->m_header.left
                    = bbstree_min_element( uninit_self->m_header.parent );
                uninit_self->m_header.right
                    = bbstree_max_element( uninit_self->m_header.parent );
            }
        }

        uninit_self->m_node_count = src->m_node_count;
    }

    return 1;
}

/******************************************************************************/

int bbstree_assign_copy( bbstree* self, const bbstree* src )
{
    if( self == src || self->m_element_size != src->m_element_size
        || self->m_elmt_init_copy != src->m_elmt_init_copy )
        return -1;
    else
    {
        bbstree_destroy( self );

        if( src->m_node_count > 0 )
        {
            self->m_header.parent
                = bbstree_copy_tree( self, &(self->m_header), ROOT(src) );

            if( !(self->m_header.parent) )
                return 0;
            else
            {
                self->m_header.left
                    = bbstree_min_element( self->m_header.parent );
                self->m_header.right
                    = bbstree_max_element( self->m_header.parent );
            }
        }

        self->m_node_count = src->m_node_count;
    }

    return 1;
}

/******************************************************************************/

void bbstree_init_move( bbstree* uninit_self, bbstree* src )
{
    if( uninit_self != src )
    {
        *uninit_self = *src;
        bbstree_init_header( uninit_self );
        uninit_self->m_node_count = 0;
        bbstree_swap( uninit_self, src );
    }
}

/******************************************************************************/

void bbstree_assign_move( bbstree* self, bbstree* src )
{
    if( self != src )
        bbstree_swap( self, src );
}

/******************************************************************************/

void bbstree_swap( bbstree* self, bbstree* other )
{
    if( self != other )
    {
        bbstree temp;
        bool xempty = ( self->m_node_count == 0 ? true : false );
        bool yempty = ( other->m_node_count == 0 ? true : false );

        if( true == xempty )
        {
       	    if( true == yempty )
       	        return;

            temp = *self;
            *self = *other;
            *other = temp;
            bbstree_init_header( other );  /* empty other */

            /* other->root pointer to self->m_header */
            self->m_header.parent->parent = &(self->m_header);
        }
    	else
    	{
            temp = *self;
            *self = *other;
            *other = temp;

            /* self->root pointer to other->m_header */
            other->m_header.parent->parent = &(other->m_header);

            if( true == yempty )
                bbstree_init_header( self );  /* empty self */
            else
                self->m_header.parent->parent = &(self->m_header);
        }
    }
}

/******************************************************************************/

bbstree_node* bbstree_find( bbstree* self, const void* key )
{
    bbstree_node* result = &(self->m_header);
    bbstree_node* current = ROOT( self );

    if( self->m_get_key )
    {
        while( current )
        {
            /* current < key */
            if( self->m_cmp_key( NODE_KEY(self, current), key ) < 0 )
                current = current->right;
            else
            {
                result = current;
                current = current->left;
            }
        }
    }
    else
    {
        while( current )
        {
            if( self->m_cmp_key( NODE_DATA(current), key ) < 0 )
                current = current->right;
            else
            {
                result = current;
                current = current->left;
            }
        }
    }

    return ( result == &(self->m_header) )
           || ( self->m_cmp_key(key, GET_NODE_KEY(self, result)) < 0 )
           ? &(self->m_header) : result;
}

/******************************************************************************/

bbstree_node* bbstree_lower_bound( bbstree* self, const void* key )
{
    bbstree_node* result = &(self->m_header);
    bbstree_node* current = ROOT( self );

    if( self->m_get_key )
    {
        while( current )
        {
            /* current < key */
            if( self->m_cmp_key( NODE_KEY(self, current), key ) < 0 )
                current = current->right;
            else
            {
                result = current;
                current = current->left;
            }
        }
    }
    else
    {
        while( current )
        {
            if( self->m_cmp_key( NODE_DATA(current), key ) < 0 )
                current = current->right;
            else
            {
                result = current;
                current = current->left;
            }
        }
    }

    return result;
}

/******************************************************************************/

bbstree_node* bbstree_upper_bound( bbstree* self, const void* key )
{
    bbstree_node* result = &(self->m_header);
    bbstree_node* current = ROOT( self );

    if( self->m_get_key )
    {
        while( current )
        {
            /* key < current */
            if( self->m_cmp_key( key, NODE_KEY(self, current) ) < 0 )
            {
                result = current;
                current = current->left;
            }
            else
                current = current->right;
        }
    }
    else
    {
        while( current )
        {
            if( self->m_cmp_key( key, NODE_DATA(current) ) < 0 )
            {
                result = current;
                current = current->left;
            }
            else
                current = current->right;
        }
    }

    return result;
}

/******************************************************************************/

bbstree_pair_iterator bbstree_equal_range( bbstree* self, const void* key )
{
    bbstree_pair_iterator result;
    result.first = bbstree_lower_bound( self, key );
    result.second = bbstree_upper_bound( self, key );
    return result;
}

/******************************************************************************/

size_t bbstree_count( bbstree* self, const void* key )
{
    size_t count = 0;
    bbstree_node* first = bbstree_lower_bound( self, key );
    bbstree_node* last = bbstree_upper_bound( self, key );

    while( first != last )
    {
        ++count;
        bbstree_itr_inc( &first );
    }

    return count;
}

/******************************************************************************/

void bbstree_erase_pos( bbstree* self, bbstree_node* pos )
{
    if( pos && pos != &(self->m_header) )
    {
        bbstree_erase_fixup( pos, &(self->m_header) );
        if( self->m_elmt_destroy )
            self->m_elmt_destroy( NODE_DATA(pos) );
        self->m_dealloc( pos, sizeof(bbstree_node) + self->m_element_size );
        --( self->m_node_count );
    }
}

/******************************************************************************/

void bbstree_erase_range( bbstree* self,
                          bbstree_node* first,
                          bbstree_node* last )
{
    if( first && last && first != &(self->m_header) )
    {
        if( first == self->m_header.left && last == &(self->m_header) )
            bbstree_destroy( self );
        else
        {
            bbstree_node* erase_node;

            while( first != last )
            {
                erase_node = first;
                bbstree_itr_inc( &first );
                bbstree_erase_pos( self, erase_node );
            }
        }
    }
}

/******************************************************************************/

size_t bbstree_erase_key( bbstree* self, const void* key )
{
    size_t count = 0;
    bbstree_node* erase_node = NULL;
    bbstree_node* first = bbstree_lower_bound( self, key );
    bbstree_node* last = bbstree_upper_bound( self, key );

    while( first != last )
    {
        ++count;
        erase_node = first;
        bbstree_itr_inc( &first );
        bbstree_erase_pos( self, erase_node );
    }

    return count;
}

/******************************************************************************/

bbstree_node* bbstree_insert_unique_value( bbstree* self, const void* value )
{
    int less_val = -1;
    bbstree_node* result;
    bbstree_node* parent = &(self->m_header);
    bbstree_node* current = ROOT( self );

    if( self->m_get_key )
    {
        const void* key = self->m_get_key( value );
        while( current )
        {
            parent = current;
            less_val = self->m_cmp_key( key, NODE_KEY(self, current) );
            current = ( less_val < 0 ? current->left : current->right );
        }
    }
    else
    {
        while( current )
        {
            parent = current;
            less_val = self->m_cmp_key( value, NODE_DATA(current) );
            current = ( less_val < 0 ? current->left : current->right );
        }
    }

    result = parent;
    if( less_val < 0 )  /* last result is value < current */
    {
        if( result == LEFTMOST(self) )
            return bbstree_insert_node( self, current, parent, value );
        else
            bbstree_itr_dec( &result );
    }

    /* result < value */
    if( self->m_cmp_key(GET_NODE_KEY(self, result), DATA_KEY(self, value)) < 0 )
        return bbstree_insert_node( self, current, parent, value );

    return result;
}

/******************************************************************************/

bbstree_node* bbstree_insert_unique_pos( bbstree* self,
                                         bbstree_node* pos,
                                         const void* value )
{
    bbstree_node* result = NULL;

    if( pos == LEFTMOST(self) )  /* pos == begin */
    {
        if( self->m_node_count > 0
            && self->m_cmp_key( DATA_KEY(self, value),
                                GET_NODE_KEY(self, pos) ) < 0 )
            result = bbstree_insert_node( self, pos, pos, value );
        else
            result = bbstree_insert_unique_value( self, value );

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?