/**
 * Links two trees.  The parent node is assumed to have lesser key than the
 * child.  The child is made the leftmost node of the parent.
 *
 * @param queue     Queue in which to operate
 * @param parent    Parent node
 * @param child     New child node
 */
static void link( strict_fibonacci_heap *queue, strict_fibonacci_node *parent,
                  strict_fibonacci_node *child )
{
    if( parent == child->parent )
        return;

    if( child == queue->root )
        remove_from_siblings( queue, parent );
    else
        remove_from_siblings( queue, child );

    strict_fibonacci_node *next = parent->left_child;
    strict_fibonacci_node *prev;

    if( parent->left_child == NULL )
        parent->left_child = child;
    else
    {
        prev = next->left;
        child->right = next;
        child->left = prev;
        prev->right = child;
        next->left = child;

        if( is_active( queue, child ) )
            parent->left_child = child;
    }

    child->parent = parent;
}
key_type pq_delete_min( strict_fibonacci_heap *queue )
{
    if( pq_empty( queue ) )
        return 0;

    key_type key = queue->root->key;
    strict_fibonacci_node *current, *new_root, *old_root;
    int i, j;

    old_root = queue->root;

    if( old_root->left_child == NULL )
    {
        old_root = queue->root;
        if( is_active( queue, old_root ) )
            convert_to_passive( queue, old_root );
        queue->root = NULL;
    }
    else
    {
        new_root = select_new_root( queue );
        remove_from_siblings( queue, new_root );
        dequeue_node( queue, new_root );
        queue->root = new_root;

        if( is_active( queue, new_root ) )
            convert_to_passive( queue, new_root );
        if( is_active( queue, old_root ) )
            convert_to_passive( queue, old_root );

        while( old_root->left_child != NULL )
            link( queue, new_root, old_root->left_child );

        for( i = 0; i < 2; i++ )
        {
            current = consume_node( queue );
            if( current != NULL )
            {
                for( j = 0; j < 2; j++ )
                {
                    if( current->left_child != NULL &&
                            !is_active( queue, current->left_child->left ) )
                        link( queue, new_root, current->left_child->left );
                    else
                        break;
                }
            }
        }
    }

    pq_free_node( queue->map, STRICT_NODE_FIB, old_root );

    post_delete_min_reduction( queue );
    garbage_collection( queue );

    queue->size--;

    return key;
}
示例#3
0
void Patricia::Node::remove_self(allocator<Node*> &a) {
	if (root()) {
		//rootノードは除去できない.
		return;
	}
	//兄弟ノード
	NodeList &siblings = parent_->children_;
	//マージするケース:
	size_t sz = children_.size();
	//std::printf("node: remove: %lu %s ", sz, terminal() ? "t" : "-"); dump();
	if (sz == 0) {
		remove_from_siblings();
		//terminal() == trueであるはず.
		//- このノードが子供を持たない場合は単純に除去される。結果兄弟ノードの数が1になってしまった場合には,
		//そのノードと親とのマージを試みる(親がrootないし終端ノードの場合マージされない)
		/* eg) +ab +ac +abc +abd -ac => 
			__root__
				ab
					c
					d
		*/
		if (siblings.size() == 1) {
			//merge this child node with parent.
			//parent_とsiblings[0]はこの中で解放される.
			parent_->merge(a, siblings[0]);
		}
		destroy(a);
	} else if (terminal()) {
		//子供を持つ場合で終端ノードの場合.
		param_ = nullptr; //終端ノードではなくなるだけ.(子供があるため削除できない).
		if (sz == 1) {
			//- このノードが1つの子供を持つ場合で、終端ノードだった => このノードと子供をマージしてparent_に追加する.
			// eg) +ab +abc +abcd -ab => abc
			// thisとchildren_[0]はこのmergeの中で解放される.従ってthisにはこれ以降触らないこと.
			merge(a, children_[0]);
		}
	} else {
		//実用上、このケースは発生しない(remove_sliceで終端ノードが見つかり、かつ対象スライスを被覆していることをチェックしているため).
		//エラーにしても良いが、ライブラリ内部での利用で便利な可能性があるため残す。このノード以下のすべてのノードを削除する.
		remove_from_siblings();
		destroy(a);
	}
}
示例#4
0
//Patricia::Node
void Patricia::Node::merge(allocator<Node*> &a, Node *n) {
	if (terminal() || root()) {
		return;
	}
	//create merged node (マージされる時、必ず終端ノードとなる)
	Node *merged = Node::new_node(a, parent_, bytes_, len_ + n->len_, n->param_);
	std::memcpy(merged->bytes_ + len_, n->bytes_, n->len_);
	//nに子供があればmergedに付け直す.
	if (n->children_.size() > 0) {
		for (Node *c : n->children_) {
			c->parent_ = merged;
		}
		merged->children_ = std::move(n->children_); //moveしてくれるのでcopy発生しないはず.
	}
	//replace self with merged node in siblings
	remove_from_siblings();
	parent_->children_.push_back(merged);
	parent_->sort_children();
	//マージ元になったオブジェクトは破棄される
	n->free(a); //nのchildはすでにmergedに引き渡されている
	free(a); //thisはchildをn以外に持たないはず.
}