1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2025-01-08 13:22:53 +02:00

Support removing elements.

Originally committed as revision 11400 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Michael Niedermayer 2008-01-04 18:20:03 +00:00
parent 6e8b982bcc
commit f05dda3b7a

View File

@ -51,39 +51,55 @@ void *av_tree_insert(AVTreeNode **tp, void *key, int (*cmp)(void *key, const voi
AVTreeNode *t= *tp; AVTreeNode *t= *tp;
if(t){ if(t){
unsigned int v= cmp(t->elem, key); unsigned int v= cmp(t->elem, key);
if(v){ void *ret;
int i= v>>31; if(!v){
AVTreeNode **child= &t->child[i]; if(*next)
void *ret= av_tree_insert(child, key, cmp, next); return t->elem;
else if(t->child[0]||t->child[1]){
int i= !t->child[0];
AVTreeNode **child= &t->child[i];
void *next_elem[2];
av_tree_find(*child, key, cmp, next_elem);
key= t->elem= next_elem[i];
v= -i;
}else{
*next= t;
*tp=NULL;
return NULL;
}
}
ret= av_tree_insert(&t->child[v>>31], key, cmp, next);
if(!ret){ if(!ret){
t->state -= ((int)v>>31)|1; int i= (v>>31) ^ !!*next;
AVTreeNode **child= &t->child[i];
t->state += 2*i - 1;
if(!(t->state&1)){ if(!(t->state&1)){
if(t->state){ if(t->state){
if((*child)->state*2 == t->state){ if((*child)->state*2 == -t->state){
*tp= *child;
*child= (*child)->child[i^1];
(*tp)->child[i^1]= t;
t->state= 0;
}else{
*tp= (*child)->child[i^1]; *tp= (*child)->child[i^1];
(*child)->child[i^1]= (*tp)->child[i]; (*child)->child[i^1]= (*tp)->child[i];
(*tp)->child[i]= *child; (*tp)->child[i]= *child;
*child= (*tp)->child[i^1]; *child= (*tp)->child[i^1];
(*tp)->child[i^1]= t; (*tp)->child[i^1]= t;
i= (*tp)->state > 0; (*tp)->child[0]->state= -((*tp)->state>0);
(*tp)->child[i ]->state= 0; (*tp)->child[1]->state= (*tp)->state<0 ;
(*tp)->child[i^1]->state= -(*tp)->state; (*tp)->state=0;
}else{
*tp= *child;
*child= (*child)->child[i^1];
(*tp)->child[i^1]= t;
if((*tp)->state) t->state = 0;
else t->state>>= 1;
(*tp)->state= -t->state;
} }
(*tp)->state=0;
} }
return key;
} }
if(!(*tp)->state ^ !!*next)
return key;
} }
return ret; return ret;
}else{
return t->elem;
}
}else{ }else{
*tp= *next; *next= NULL; *tp= *next; *next= NULL;
(*tp)->elem= key; (*tp)->elem= key;
@ -140,17 +156,29 @@ int cmp(const void *a, const void *b){
int main(void){ int main(void){
int i,j,k; int i,j,k;
AVTreeNode *root= NULL; AVTreeNode *root= NULL, *node=NULL;
for(i=0; i<10000; i++){ for(i=0; i<10000; i++){
int j= (random()%863294); int j= (random()%86294);
if(check(root) > 999){ if(check(root) > 999){
av_log(NULL, AV_LOG_ERROR, "FATAL error %d\n", i); av_log(NULL, AV_LOG_ERROR, "FATAL error %d\n", i);
print(root, 0); print(root, 0);
return -1; return -1;
} }
av_log(NULL, AV_LOG_ERROR, "inserting %4d\n", j); av_log(NULL, AV_LOG_ERROR, "inserting %4d\n", j);
av_tree_insert(&root, (void*)(j+1), cmp); if(!node)
node= av_mallocz(av_tree_node_size);
av_tree_insert(&root, (void*)(j+1), cmp, &node);
j= (random()%86294);
k= av_tree_find(root, (void*)(j+1), cmp, NULL);
if(k){
AVTreeNode *node2=NULL;
av_tree_insert(&root, (void*)(j+1), cmp, &node2);
k= av_tree_find(root, (void*)(j+1), cmp, NULL);
if(k)
av_log(NULL, AV_LOG_ERROR, "removial failure %d\n", i);
}
} }
return 0; return 0;
} }