⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dict.c

📁 一些常用的数据结构库
💻 C
📖 第 1 页 / 共 3 页
字号:
}/* * Look for the node corresponding to the greatest key that is equal to or * lower than the given key.  If there is no such node, return null. */dnode_t *dict_upper_bound(dict_t *dict, const void *key){    dnode_t *root = dict_root(dict);    dnode_t *nil = dict_nil(dict);    dnode_t *tentative = 0;    while (root != nil) {	int result = dict->compare(key, root->key);	if (result < 0) {	    root = root->left;	} else if (result > 0) {	    tentative = root;	    root = root->right;	} else {	    if (!dict->dupes) {	    	return root;	    } else {		tentative = root;		root = root->right;	    }	}     }        return tentative;}/* * Insert a node into the dictionary. The node should have been * initialized with a data field. All other fields are ignored. * The behavior is undefined if the user attempts to insert into * a dictionary that is already full (for which the dict_isfull() * function returns true). */void dict_insert(dict_t *dict, dnode_t *node, const void *key){    dnode_t *where = dict_root(dict), *nil = dict_nil(dict);    dnode_t *parent = nil, *uncle, *grandpa;    int result = -1;    node->key = key;    assert (!dict_isfull(dict));    assert (!dict_contains(dict, node));    assert (!dnode_is_in_a_dict(node));    /* basic binary tree insert */    while (where != nil) {	parent = where;	result = dict->compare(key, where->key);	/* trap attempts at duplicate key insertion unless it's explicitly allowed */	assert (dict->dupes || result != 0);	if (result < 0)	    where = where->left;	else	    where = where->right;    }    assert (where == nil);    if (result < 0)	parent->left = node;    else	parent->right = node;    node->parent = parent;    node->left = nil;    node->right = nil;    dict->nodecount++;    /* red black adjustments */    node->color = dnode_red;    while (parent->color == dnode_red) {	grandpa = parent->parent;	if (parent == grandpa->left) {	    uncle = grandpa->right;	    if (uncle->color == dnode_red) {	/* red parent, red uncle */		parent->color = dnode_black;		uncle->color = dnode_black;		grandpa->color = dnode_red;		node = grandpa;		parent = grandpa->parent;	    } else {				/* red parent, black uncle */	    	if (node == parent->right) {		    rotate_left(parent);		    parent = node;		    assert (grandpa == parent->parent);		    /* rotation between parent and child preserves grandpa */		}		parent->color = dnode_black;		grandpa->color = dnode_red;		rotate_right(grandpa);		break;	    }	} else { 	/* symmetric cases: parent == parent->parent->right */	    uncle = grandpa->left;	    if (uncle->color == dnode_red) {		parent->color = dnode_black;		uncle->color = dnode_black;		grandpa->color = dnode_red;		node = grandpa;		parent = grandpa->parent;	    } else {	    	if (node == parent->left) {		    rotate_right(parent);		    parent = node;		    assert (grandpa == parent->parent);		}		parent->color = dnode_black;		grandpa->color = dnode_red;		rotate_left(grandpa);		break;	    }	}    }    dict_root(dict)->color = dnode_black;    assert (dict_verify(dict));}/* * Delete the given node from the dictionary. If the given node does not belong * to the given dictionary, undefined behavior results.  A pointer to the * deleted node is returned. */dnode_t *dict_delete(dict_t *dict, dnode_t *delete){    dnode_t *nil = dict_nil(dict), *child, *delparent = delete->parent;    /* basic deletion */    assert (!dict_isempty(dict));    assert (dict_contains(dict, delete));    /*     * If the node being deleted has two children, then we replace it with its     * successor (i.e. the leftmost node in the right subtree.) By doing this,     * we avoid the traditional algorithm under which the successor's key and     * value *only* move to the deleted node and the successor is spliced out     * from the tree. We cannot use this approach because the user may hold     * pointers to the successor, or nodes may be inextricably tied to some     * other structures by way of embedding, etc. So we must splice out the     * node we are given, not some other node, and must not move contents from     * one node to another behind the user's back.     */    if (delete->left != nil && delete->right != nil) {	dnode_t *next = dict_next(dict, delete);	dnode_t *nextparent = next->parent;	dnode_color_t nextcolor = next->color;	assert (next != nil);	assert (next->parent != nil);	assert (next->left == nil);	/*	 * First, splice out the successor from the tree completely, by	 * moving up its right child into its place.	 */	child = next->right;	child->parent = nextparent;	if (nextparent->left == next) {	    nextparent->left = child;	} else {	    assert (nextparent->right == next);	    nextparent->right = child;	}	/*	 * Now that the successor has been extricated from the tree, install it	 * in place of the node that we want deleted.	 */	next->parent = delparent;	next->left = delete->left;	next->right = delete->right;	next->left->parent = next;	next->right->parent = next;	next->color = delete->color;	delete->color = nextcolor;	if (delparent->left == delete) {	    delparent->left = next;	} else {	    assert (delparent->right == delete);	    delparent->right = next;	}    } else {	assert (delete != nil);	assert (delete->left == nil || delete->right == nil);	child = (delete->left != nil) ? delete->left : delete->right;	child->parent = delparent = delete->parent;	    	if (delete == delparent->left) {	    delparent->left = child;    	} else {	    assert (delete == delparent->right);	    delparent->right = child;	}    }    delete->parent = NULL;    delete->right = NULL;    delete->left = NULL;    dict->nodecount--;    assert (verify_bintree(dict));    /* red-black adjustments */    if (delete->color == dnode_black) {	dnode_t *parent, *sister;	dict_root(dict)->color = dnode_red;	while (child->color == dnode_black) {	    parent = child->parent;	    if (child == parent->left) {		sister = parent->right;		assert (sister != nil);		if (sister->color == dnode_red) {		    sister->color = dnode_black;		    parent->color = dnode_red;		    rotate_left(parent);		    sister = parent->right;		    assert (sister != nil);		}		if (sister->left->color == dnode_black			&& sister->right->color == dnode_black) {		    sister->color = dnode_red;		    child = parent;		} else {		    if (sister->right->color == dnode_black) {			assert (sister->left->color == dnode_red);			sister->left->color = dnode_black;			sister->color = dnode_red;			rotate_right(sister);			sister = parent->right;			assert (sister != nil);		    }		    sister->color = parent->color;		    sister->right->color = dnode_black;		    parent->color = dnode_black;		    rotate_left(parent);		    break;		}	    } else {	/* symmetric case: child == child->parent->right */		assert (child == parent->right);		sister = parent->left;		assert (sister != nil);		if (sister->color == dnode_red) {		    sister->color = dnode_black;		    parent->color = dnode_red;		    rotate_right(parent);		    sister = parent->left;		    assert (sister != nil);		}		if (sister->right->color == dnode_black			&& sister->left->color == dnode_black) {		    sister->color = dnode_red;		    child = parent;		} else {		    if (sister->left->color == dnode_black) {			assert (sister->right->color == dnode_red);			sister->right->color = dnode_black;			sister->color = dnode_red;			rotate_left(sister);			sister = parent->left;			assert (sister != nil);		    }		    sister->color = parent->color;		    sister->left->color = dnode_black;		    parent->color = dnode_black;		    rotate_right(parent);		    break;		}	    }	}	child->color = dnode_black;	dict_root(dict)->color = dnode_black;    }    assert (dict_verify(dict));    return delete;}/* * Allocate a node using the dictionary's allocator routine, give it * the data item. */int dict_alloc_insert(dict_t *dict, const void *key, void *data){    dnode_t *node = dict->allocnode(dict->context);    if (node) {	dnode_init(node, data);	dict_insert(dict, node, key);	return 1;    }    return 0;}void dict_delete_free(dict_t *dict, dnode_t *node){    dict_delete(dict, node);    dict->freenode(node, dict->context);}/* * Return the node with the lowest (leftmost) key. If the dictionary is empty * (that is, dict_isempty(dict) returns 1) a null pointer is returned. */dnode_t *dict_first(dict_t *dict){    dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;    if (root != nil)	while ((left = root->left) != nil)	    root = left;    return (root == nil) ? NULL : root;}/* * Return the node with the highest (rightmost) key. If the dictionary is empty * (that is, dict_isempty(dict) returns 1) a null pointer is returned. */dnode_t *dict_last(dict_t *dict){    dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *right;    if (root != nil)	while ((right = root->right) != nil)	    root = right;    return (root == nil) ? NULL : root;}/* * Return the given node's successor node---the node which has the * next key in the the left to right ordering. If the node has * no successor, a null pointer is returned rather than a pointer to * the nil node. */dnode_t *dict_next(dict_t *dict, dnode_t *curr){    dnode_t *nil = dict_nil(dict), *parent, *left;    if (curr->right != nil) {	curr = curr->right;	while ((left = curr->left) != nil)	    curr = left;	return curr;    }    parent = curr->parent;    while (parent != nil && curr == parent->right) {	curr = parent;	parent = curr->parent;    }    return (parent == nil) ? NULL : parent;}/* * Return the given node's predecessor, in the key order. * The nil sentinel node is returned if there is no predecessor. */dnode_t *dict_prev(dict_t *dict, dnode_t *curr){    dnode_t *nil = dict_nil(dict), *parent, *right;    if (curr->left != nil) {	curr = curr->left;	while ((right = curr->right) != nil)	    curr = right;	return curr;    }    parent = curr->parent;    while (parent != nil && curr == parent->left) {	curr = parent;	parent = curr->parent;    }    return (parent == nil) ? NULL : parent;}void dict_allow_dupes(dict_t *dict){    dict->dupes = 1;}#undef dict_count#undef dict_isempty#undef dict_isfull#undef dnode_get#undef dnode_put#undef dnode_getkeydictcount_t dict_count(dict_t *dict){    return dict->nodecount;}int dict_isempty(dict_t *dict){    return dict->nodecount == 0;}int dict_isfull(dict_t *dict){    return dict->nodecount == dict->maxcount;}int dict_contains(dict_t *dict, dnode_t *node){    return verify_dict_has_node(dict_nil(dict), dict_root(dict), node);}static dnode_t *dnode_alloc(void *context){    return malloc(sizeof *dnode_alloc(NULL));}static void dnode_free(dnode_t *node, void *context){    free(node);}dnode_t *dnode_create(void *data){    dnode_t *new = malloc(sizeof *new);    if (new) {	new->data = data;	new->parent = NULL;	new->left = NULL;	new->right = NULL;    }    return new;}dnode_t *dnode_init(dnode_t *dnode, void *data){    dnode->data = data;    dnode->parent = NULL;    dnode->left = NULL;    dnode->right = NULL;    return dnode;}void dnode_destroy(dnode_t *dnode){    assert (!dnode_is_in_a_dict(dnode));    free(dnode);}void *dnode_get(dnode_t *dnode){    return dnode->data;}const void *dnode_getkey(dnode_t *dnode){    return dnode->key;}void dnode_put(dnode_t *dnode, void *data){    dnode->data = data;

⌨️ 快捷键说明

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