コード例 #1
0
ファイル: avl.c プロジェクト: hacatu/Praser2
avl_node *avl_remove_retrace(avl_node *n){
	avl_node *p = n->parent;
	if(!p){
		return n;
	}
	if(n == p->left){//+2 cases
		switch(p->balance){
			case -1:
			p->balance = 0;
			return avl_remove_retrace(p);
			case 0://change in height absorbed
			p->balance = 1;
			return avl_root(p);
		}//default: p->balance == 1
		return avl_remove_rebalance_l(p);
	}//otherwise n == p->right
	switch(p->balance){//-2 cases
		case 1:
		p->balance = 0;
		return avl_remove_retrace(p);
		case 0://change in height absorbed
		p->balance = -1;
		return avl_root(p);
	}//default: p->balance == -1
	return avl_remove_rebalance_r(p);
}
コード例 #2
0
ファイル: avl.c プロジェクト: hacatu/Praser2
avl_node *avl_insert_retrace(avl_node *n){
	avl_node *p = n->parent;
	if(!p){
		return n;
	}
	if(n == p->right){//+2 cases
		switch(p->balance){
			case -1://height change absorbed
			p->balance = 0;
			return avl_root(p);
			case 0:
			p->balance = 1;
			return avl_insert_retrace(p);
		}//default: p->balance == 1
		return avl_insert_rebalance_r(p, n);//height change will be absorbed
	}//otherwise n == p->left
	switch(p->balance){//-2 cases
		case 1://height change absorbed
		p->balance = 0;
		return avl_root(p);
		case 0:
		p->balance = -1;
		return avl_insert_retrace(p);
	}//default: p->balance == -1
	return avl_insert_rebalance_l(p, n);//height change will be absorbed
}
コード例 #3
0
ファイル: avl.c プロジェクト: hacatu/Praser2
avl_node *avl_insert_rebalance_l(avl_node *p, avl_node *n){//mirror image of avl_insert_rebalance_r
	if(n->balance == -1){
		avl_rotate_l(p);
		p->balance = n->balance = 0;
		return avl_root(n);
	}
	avl_rotate_r(n);
	avl_rotate_l(p);
	n->balance = -(n->parent->balance == 1);
	p->balance = +(n->parent->balance == -1);//unary + for symmetry
	n->parent->balance = 0;
	return avl_root(n->parent);
}
コード例 #4
0
ファイル: avl.c プロジェクト: hacatu/Praser2
avl_node *avl_insert_rebalance_r(avl_node *p, avl_node *n){
	if(n->balance == 1){//right-right case: only one rotation needed
		avl_rotate_r(p);//note n becomes the parent of p
		p->balance = n->balance = 0;
		return avl_root(n);
	}//otherwise right-left case: two rotations are required and the balance factors have 3 cases
	avl_rotate_l(n);
	avl_rotate_r(p);//note p, n->left, n change roles from parent, right child, right-left grandchild to left child, parent, right child
	n->balance = +(n->parent->balance == -1);//n, now the right child of n->parent, its old left child, has a balance factor of 1 if the child was -1, else 0
	p->balance = -(n->parent->balance == 1);//p, now the right child of n->parent, has a balance factor of -1 if n->parent was 1, else 0
	n->parent->balance = 0;//if this is still confusing, try drawing out all of the possible trees with root +2 and right child +/-1 with irrelevant subtrees only marked as heights.
	return avl_root(n->parent);//there are 4 cases and I will try to put them in a pdf somewhere if I can figure out how to draw it on a computer.
}
コード例 #5
0
ファイル: sb_avl.c プロジェクト: sbradfo5/C_Libraries
// erase an entry
void avl_erase(sb_avl * instance, void * key)
{
	avl_node * v = avl_finder(key, avl_root(instance), instance->cmp_keys);
	if ( v == NULL ) {
		return;
	}
	avl_delete(instance, v);
}
コード例 #6
0
ファイル: sb_avl.c プロジェクト: sbradfo5/C_Libraries
avl_node * avl_find_max(sb_avl * instance)
{
	avl_node * x = avl_root(instance);
	while (x->right != NULL) {
		x = x->right;
	}
	return x;
}
コード例 #7
0
ファイル: sb_avl.c プロジェクト: sbradfo5/C_Libraries
avl_node * avl_find_min(sb_avl * instance)
{
	avl_node * x = avl_root(instance);
	while (x->left != NULL) {
		x = x->left;
	}
	return x;
}
コード例 #8
0
ファイル: sb_avl.c プロジェクト: sbradfo5/C_Libraries
void avl_insert(sb_avl * instance, void * key, void * data)
{
	avl_node * curr_node, * prev_node, * q, * x, * y, * z;

	// insert into empty AVL tree
	if (avl_root(instance) == NULL) {
		instance->root = avl_new_node(key, data);
		instance->root->height = 1;
		return;
	}

	curr_node = instance->root;  
	prev_node = instance->root;

	// traverse until NULL, keeping track of the parent
	while ( curr_node != NULL )
	{
		if ( instance->cmp_keys(key, curr_node->key ) < 0 )
		{
			prev_node = curr_node;       // Remember prev. node
			curr_node = curr_node->left;  // Continue search in left subtree
		}
		else if ( instance->cmp_keys(key, curr_node->key ) >= 0 )
		{
			prev_node = curr_node;       // Remember prev. node
			curr_node = curr_node->right; // Continue search in right subtree
		}
	}

	q = avl_new_node(key, data);
	q->height = 1;
	q->parent = prev_node;

	if ( instance->cmp_keys(key, prev_node->key) < 0 ) {
		prev_node->left = q;
	}
	else {
		prev_node->right = q;
	}

	x = y = z = q;

	while ( x != NULL ) {
		if ( avl_diff_height(x->left, x->right) <= 1) {
			z = y;
			y = x;
			x = x->parent;
		}
		else {
			break;
		}
	}

	if ( x != NULL ) {
		avl_trinode_restructure(instance, x, y, z);
	}
	return;
}
コード例 #9
0
ファイル: sb_avl.c プロジェクト: sbradfo5/C_Libraries
avl_node * avl_find_node(sb_avl * instance, void * key)
{
	avl_node * tmp;
	tmp = avl_finder(key, avl_root(instance), instance->cmp_keys);
	if (tmp == NULL) {
		return NULL;
	}
	else {
		return tmp;
	}
}
コード例 #10
0
ファイル: avl.c プロジェクト: hacatu/Praser2
avl_node *avl_remove_rebalance_r(avl_node *p){//mirror image of avl_remove_rebalance_l
	avl_node *n = p->left;
	if(n->balance != 1){
		avl_rotate_l(p);
		p->balance -= n->balance++;//if n is -1, n and p become 0, otherwise n is 0 and they become +1 and -1.  Note the -= needn't be flipped since -- was
		return n->balance ? avl_root(n) : avl_remove_retrace(n);
	}
	avl_rotate_r(n);
	avl_rotate_l(p);
	p->balance = +(n->parent->balance == -1);
	n->balance = -(n->parent->balance == 1);
	n->parent->balance = 0;
	return avl_remove_retrace(n->parent);
}
コード例 #11
0
ファイル: avl.c プロジェクト: hacatu/Praser2
avl_node *avl_remove_rebalance_l(avl_node *p){//do not try to understand this until you understand avl_insert_rebalance_r
	avl_node *n = p->right;//If we've become off balance by a left REMOVAL there must be a right child
	if(n->balance != -1){//not the right-left case
		avl_rotate_r(p);//nb. the pointers n and p point to the same nodes but now n is the parent
		p->balance -= n->balance--;//if n is +1, n and p become 0, otherwise n is 0 and they become -1 and +1
		return n->balance ? avl_root(n) : avl_remove_retrace(n);//if n->balance becomes 0 by removal we still have height decrease to propagate
	}//right-left case.  This is exactly the same as insertion whereas the previous part included a right-even case not present in insertion
	avl_rotate_l(n);
	avl_rotate_r(p);
	p->balance = -(n->parent->balance == 1);
	n->balance = +(n->parent->balance == -1);
	n->parent->balance = 0;
	return avl_remove_retrace(n->parent);
}
コード例 #12
0
ファイル: sb_avl.c プロジェクト: sbradfo5/C_Libraries
void avl_delete(sb_avl * instance, avl_node * p)
{
	/** Case 1: p has no children **/
	if (p->left == NULL && p->right == NULL) {
		/** Case 1a: p is the root **/
		if (p == avl_root(instance)) {
			free(avl_root(instance));
			return;
		}
		
		avl_node * parent = p->parent;

		if (parent->left == p) {
			parent->left = NULL;
		}
		else {
			parent->right = NULL;
		}

		avl_recomp_height(parent);

		avl_rebalance(instance, parent);

		free(p);

		return;
	}

	/** Case 2: p has 1 child **/
	if (p->right == NULL) {

		/** Case 2a: p is the root **/
		if (p == avl_root(instance)) {

			// update the new root's parent
			instance->root->left->parent = NULL;

			// change the root to the new root
			instance->root = instance->root->left;

			// free the old root
			free(p);

			// re-compute heights
			avl_recomp_height(instance->root);

			// and re-balance
			avl_rebalance(instance, instance->root);
			return;
		}

		avl_node * parent = p->parent;

		if (parent->left == p) {
			parent->left = p->left;
			p->left->parent = parent;
		}
		else {
			parent->right = p->left;
			p->left->parent = parent;
		}

		free(p);

		avl_recomp_height(parent);

		avl_rebalance(instance, parent);

		return;
	}

	if (p->left == NULL) {
		if ( p == avl_root(instance) ) {
			// update the new root's parent
			instance->root->right->parent = NULL;

			// change the root
			instance->root = instance->root->right;

			// free the old root
			free(p);

			// re-compute heights
			avl_recomp_height(instance->root);

			// and re-balance
			avl_rebalance(instance, instance->root);

			return;
		}

		avl_node * parent = p->parent;

		if (parent->left == p) {
			parent->left = p->right;
			p->right->parent = parent;
		}
		else {
			parent->right = p->right;
			p->right->parent = parent;
		}

		free(p);

		avl_recomp_height(parent);

		avl_rebalance(instance, parent);

		return;
	}

	/** Case 3: p has 2 children **/
	if ( p->right->left == NULL ) {

		// overwrite p with p->right.
		// This leaves p->right with no way to
		// get to it. So remove p->right.
		avl_node * tmp = p->right;
		p->key = p->right->key;
		p->value = p->right->value;
		p->right = p->right->right;

		free(tmp);

		avl_recomp_height(p->parent);

		avl_rebalance(instance, p->parent);

		return;
	}

	avl_node * succ = p->right;
	avl_node * succParent;

	while ( succ->left != NULL ) {
		succ = succ->left;
	}

	p->key = succ->key;
	p->value = succ->value;

	succParent = succ->parent;
	succParent->left = succ->right;

	free(succ);

	avl_recomp_height(succParent);
	
	avl_rebalance(instance, succParent);

	return;
}