/* * FIXME: When the RBTree contains thousands of elements it would take to long to iterate through the thousands * of elements put them into a stack and then give them to the caller. Instead we should do something like the * commented code below where we use assembly to pass a variable amount of arguments to a callback function. */ struct RBItrStack* RBDepthFirst(struct RBNode* const _Node, struct RBItrStack* _Stack) { if(_Node == NULL) return _Stack; (*_Stack).Prev = _Stack; (*_Stack).Node = _Node; ++_Stack; _Stack = RBDepthFirst(_Node->Left, _Stack); _Stack = RBDepthFirst(_Node->Right, _Stack); return _Stack; }
struct GenIterator* CreateRBItr(struct RBTree* _Tree, int _Size) { struct GenIterator* _Iterator = (struct GenIterator*) malloc(sizeof(struct GenIterator)); _Iterator->HasNext = GenIteratorArrayHasNext; _Iterator->NextObj = GenIteratorRBNextObj; _Iterator->StackSz = _Size; _Iterator->Stack = calloc(_Size, sizeof(struct RBItrStack)); _Iterator->Index = 0; RBDepthFirst(_Tree->Table, _Iterator->Stack); return _Iterator; }
void RBRemoveAll(struct RBTree* _Tree, void(*_Callback)(void*)) { struct RBItrStack _ItrStack[_Tree->Size]; int i = 0; memset(_ItrStack, 0, sizeof(struct RBItrStack*) * _Tree->Size); RBDepthFirst(_Tree->Table, _ItrStack); for(i = 0; i < _Tree->Size; ++i) _Callback(_ItrStack[i].Node->Data); while(_Tree->Size > 0) { RBDeleteNode(_Tree, _Tree->Table); } }
void RBIterate(struct RBTree* _Tree, int(*_Callback)(void*)) { int i = 0; int j = 0; struct RBItrStack _Stack[_Tree->Size]; struct RBItrStack _DeleteStack[_Tree->Size]; if(_Tree->Table == NULL) return; memset(_Stack, 0, sizeof(struct RBItrStack*) * _Tree->Size); memset(_DeleteStack, 0, sizeof(struct RBItrStack*) * _Tree->Size); RBDepthFirst(_Tree->Table, _Stack); for(i = 0; i < _Tree->Size; ++i) { if(_Callback(_Stack[i].Node->Data) != 0) _DeleteStack[j] = _Stack[i]; } for(i = 0; i < j; ++i) RBDeleteNode(_Tree, _DeleteStack[i].Node); }