code
This commit is contained in:
709
Plugins/MqttClient/Source/DTMqtt/MqttC/MQTTTree.c
Normal file
709
Plugins/MqttClient/Source/DTMqtt/MqttC/MQTTTree.c
Normal file
@ -0,0 +1,709 @@
|
||||
// Copyright 2023 Dexter.Wan. All Rights Reserved.
|
||||
// EMail: 45141961@qq.com
|
||||
|
||||
#define TREE_C /* so that malloc/free/realloc aren't redefined by Heap.h */
|
||||
|
||||
#include "MQTTTree.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Heap.h"
|
||||
|
||||
|
||||
int isRed(Node* aNode);
|
||||
int isBlack(Node* aNode);
|
||||
/*int TreeWalk(Node* curnode, int depth);*/
|
||||
/*int TreeMaxDepth(MQTT_Tree *aTree);*/
|
||||
void TreeRotate(MQTT_Tree* aTree, Node* curnode, int direction, int index);
|
||||
Node* TreeBAASub(MQTT_Tree* aTree, Node* curnode, int which, int index);
|
||||
void TreeBalanceAfterAdd(MQTT_Tree* aTree, Node* curnode, int index);
|
||||
void* TreeAddByIndex(MQTT_Tree* aTree, void* content, size_t size, int index);
|
||||
Node* TreeFindIndex1(MQTT_Tree* aTree, void* key, int index, int value);
|
||||
Node* TreeFindContentIndex(MQTT_Tree* aTree, void* key, int index);
|
||||
Node* TreeMinimum(Node* curnode);
|
||||
Node* TreeSuccessor(Node* curnode);
|
||||
Node* TreeNextElementIndex(MQTT_Tree* aTree, Node* curnode, int index);
|
||||
Node* TreeBARSub(MQTT_Tree* aTree, Node* curnode, int which, int index);
|
||||
void TreeBalanceAfterRemove(MQTT_Tree* aTree, Node* curnode, int index);
|
||||
void* TreeRemoveIndex(MQTT_Tree* aTree, void* content, int index);
|
||||
|
||||
|
||||
void MQTTTreeInitializeNoMalloc(MQTT_Tree* aTree, int(*compare)(void*, void*, int))
|
||||
{
|
||||
memset(aTree, '\0', sizeof(MQTT_Tree));
|
||||
aTree->heap_tracking = 1;
|
||||
aTree->index[0].compare = compare;
|
||||
aTree->indexes = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates and initializes a new tree structure.
|
||||
* @return a pointer to the new tree structure
|
||||
*/
|
||||
MQTT_Tree* MQTTTreeInitialize(int(*compare)(void*, void*, int))
|
||||
{
|
||||
#if defined(UNIT_TESTS) || defined(NO_HEAP_TRACKING)
|
||||
MQTT_Tree* newt = malloc(sizeof(MQTT_Tree));
|
||||
#else
|
||||
MQTT_Tree* newt = mymalloc(__FILE__, __LINE__, sizeof(MQTT_Tree));
|
||||
#endif
|
||||
if (newt)
|
||||
MQTTTreeInitializeNoMalloc(newt, compare);
|
||||
return newt;
|
||||
}
|
||||
|
||||
|
||||
void MQTTTreeAddIndex(MQTT_Tree* aTree, int(*compare)(void*, void*, int))
|
||||
{
|
||||
aTree->index[aTree->indexes].compare = compare;
|
||||
++(aTree->indexes);
|
||||
}
|
||||
|
||||
|
||||
void MQTTTreeFree(MQTT_Tree* aTree)
|
||||
{
|
||||
#if defined(UNIT_TESTS) || defined(NO_HEAP_TRACKING)
|
||||
free(aTree);
|
||||
#else
|
||||
(aTree->heap_tracking) ? myfree(__FILE__, __LINE__, aTree) : free(aTree);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#define LEFT 0
|
||||
#define RIGHT 1
|
||||
#if !defined(max)
|
||||
#define max(a, b) (a > b) ? a : b;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int isRed(Node* aNode)
|
||||
{
|
||||
return (aNode != NULL) && (aNode->red);
|
||||
}
|
||||
|
||||
|
||||
int isBlack(Node* aNode)
|
||||
{
|
||||
return (aNode == NULL) || (aNode->red == 0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
int TreeWalk(Node* curnode, int depth)
|
||||
{
|
||||
if (curnode)
|
||||
{
|
||||
int left = TreeWalk(curnode->child[LEFT], depth+1);
|
||||
int right = TreeWalk(curnode->child[RIGHT], depth+1);
|
||||
depth = max(left, right);
|
||||
if (curnode->red)
|
||||
{
|
||||
/*if (isRed(curnode->child[LEFT]) || isRed(curnode->child[RIGHT]))
|
||||
{
|
||||
printf("red/black tree violation %p\n", curnode->content);
|
||||
exit(-99);
|
||||
}*/;
|
||||
}
|
||||
}
|
||||
return depth;
|
||||
}
|
||||
|
||||
|
||||
int TreeMaxDepth(MQTT_Tree *aTree)
|
||||
{
|
||||
int rc = TreeWalk(aTree->index[0].root, 0);
|
||||
/*if (aTree->root->red)
|
||||
{
|
||||
printf("root node should not be red %p\n", aTree->root->content);
|
||||
exit(-99);
|
||||
}*/
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
void TreeRotate(MQTT_Tree* aTree, Node* curnode, int direction, int index)
|
||||
{
|
||||
Node* other = curnode->child[!direction];
|
||||
|
||||
curnode->child[!direction] = other->child[direction];
|
||||
if (other->child[direction] != NULL)
|
||||
other->child[direction]->parent = curnode;
|
||||
other->parent = curnode->parent;
|
||||
if (curnode->parent == NULL)
|
||||
aTree->index[index].root = other;
|
||||
else if (curnode == curnode->parent->child[direction])
|
||||
curnode->parent->child[direction] = other;
|
||||
else
|
||||
curnode->parent->child[!direction] = other;
|
||||
other->child[direction] = curnode;
|
||||
curnode->parent = other;
|
||||
}
|
||||
|
||||
|
||||
Node* TreeBAASub(MQTT_Tree* aTree, Node* curnode, int which, int index)
|
||||
{
|
||||
Node* uncle = curnode->parent->parent->child[which];
|
||||
|
||||
if (isRed(uncle))
|
||||
{
|
||||
curnode->parent->red = uncle->red = 0;
|
||||
curnode = curnode->parent->parent;
|
||||
curnode->red = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (curnode == curnode->parent->child[which])
|
||||
{
|
||||
curnode = curnode->parent;
|
||||
TreeRotate(aTree, curnode, !which, index);
|
||||
}
|
||||
curnode->parent->red = 0;
|
||||
curnode->parent->parent->red = 1;
|
||||
TreeRotate(aTree, curnode->parent->parent, which, index);
|
||||
}
|
||||
return curnode;
|
||||
}
|
||||
|
||||
|
||||
void TreeBalanceAfterAdd(MQTT_Tree* aTree, Node* curnode, int index)
|
||||
{
|
||||
while (curnode && isRed(curnode->parent) && curnode->parent->parent)
|
||||
{
|
||||
if (curnode->parent == curnode->parent->parent->child[LEFT])
|
||||
curnode = TreeBAASub(aTree, curnode, RIGHT, index);
|
||||
else
|
||||
curnode = TreeBAASub(aTree, curnode, LEFT, index);
|
||||
}
|
||||
aTree->index[index].root->red = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add an item to a tree
|
||||
* @param aTree the list to which the item is to be added
|
||||
* @param content the list item content itself
|
||||
* @param size the size of the element
|
||||
*/
|
||||
void* TreeAddByIndex(MQTT_Tree* aTree, void* content, size_t size, int index)
|
||||
{
|
||||
Node* curparent = NULL;
|
||||
Node* curnode = aTree->index[index].root;
|
||||
Node* newel = NULL;
|
||||
int left = 0;
|
||||
int result = 1;
|
||||
void* rc = NULL;
|
||||
|
||||
while (curnode)
|
||||
{
|
||||
result = aTree->index[index].compare(curnode->content, content, 1);
|
||||
left = (result > 0);
|
||||
if (result == 0)
|
||||
break;
|
||||
else
|
||||
{
|
||||
curparent = curnode;
|
||||
curnode = curnode->child[left];
|
||||
}
|
||||
}
|
||||
|
||||
if (result == 0)
|
||||
{
|
||||
if (aTree->allow_duplicates)
|
||||
goto exit; /* exit(-99); */
|
||||
else
|
||||
{
|
||||
newel = curnode;
|
||||
if (index == 0)
|
||||
aTree->size += (size - curnode->size);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(UNIT_TESTS) || defined(NO_HEAP_TRACKING)
|
||||
newel = malloc(sizeof(Node));
|
||||
#else
|
||||
newel = (aTree->heap_tracking) ? mymalloc(__FILE__, __LINE__, sizeof(Node)) : malloc(sizeof(Node));
|
||||
#endif
|
||||
if (newel == NULL)
|
||||
goto exit;
|
||||
memset(newel, '\0', sizeof(Node));
|
||||
if (curparent)
|
||||
curparent->child[left] = newel;
|
||||
else
|
||||
aTree->index[index].root = newel;
|
||||
newel->parent = curparent;
|
||||
newel->red = 1;
|
||||
if (index == 0)
|
||||
{
|
||||
++(aTree->count);
|
||||
aTree->size += size;
|
||||
}
|
||||
}
|
||||
newel->content = content;
|
||||
newel->size = size;
|
||||
rc = newel->content;
|
||||
TreeBalanceAfterAdd(aTree, newel, index);
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
void* MQTTTreeAdd(MQTT_Tree* aTree, void* content, size_t size)
|
||||
{
|
||||
void* rc = NULL;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < aTree->indexes; ++i)
|
||||
rc = TreeAddByIndex(aTree, content, size, i);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
Node* TreeFindIndex1(MQTT_Tree* aTree, void* key, int index, int value)
|
||||
{
|
||||
int result = 0;
|
||||
Node* curnode = aTree->index[index].root;
|
||||
|
||||
while (curnode)
|
||||
{
|
||||
result = aTree->index[index].compare(curnode->content, key, value);
|
||||
if (result == 0)
|
||||
break;
|
||||
else
|
||||
curnode = curnode->child[result > 0];
|
||||
}
|
||||
return curnode;
|
||||
}
|
||||
|
||||
|
||||
Node* MQTTTreeFindIndex(MQTT_Tree* aTree, void* key, int index)
|
||||
{
|
||||
return TreeFindIndex1(aTree, key, index, 0);
|
||||
}
|
||||
|
||||
|
||||
Node* TreeFindContentIndex(MQTT_Tree* aTree, void* key, int index)
|
||||
{
|
||||
return TreeFindIndex1(aTree, key, index, 1);
|
||||
}
|
||||
|
||||
|
||||
Node* MQTTTreeFind(MQTT_Tree* aTree, void* key)
|
||||
{
|
||||
return MQTTTreeFindIndex(aTree, key, 0);
|
||||
}
|
||||
|
||||
|
||||
Node* TreeMinimum(Node* curnode)
|
||||
{
|
||||
if (curnode)
|
||||
while (curnode->child[LEFT])
|
||||
curnode = curnode->child[LEFT];
|
||||
return curnode;
|
||||
}
|
||||
|
||||
|
||||
Node* TreeSuccessor(Node* curnode)
|
||||
{
|
||||
if (curnode->child[RIGHT])
|
||||
curnode = TreeMinimum(curnode->child[RIGHT]);
|
||||
else
|
||||
{
|
||||
Node* curparent = curnode->parent;
|
||||
while (curparent && curnode == curparent->child[RIGHT])
|
||||
{
|
||||
curnode = curparent;
|
||||
curparent = curparent->parent;
|
||||
}
|
||||
curnode = curparent;
|
||||
}
|
||||
return curnode;
|
||||
}
|
||||
|
||||
|
||||
Node* TreeNextElementIndex(MQTT_Tree* aTree, Node* curnode, int index)
|
||||
{
|
||||
if (curnode == NULL)
|
||||
curnode = TreeMinimum(aTree->index[index].root);
|
||||
else
|
||||
curnode = TreeSuccessor(curnode);
|
||||
return curnode;
|
||||
}
|
||||
|
||||
|
||||
Node* MQTTTreeNextElement(MQTT_Tree* aTree, Node* curnode)
|
||||
{
|
||||
return TreeNextElementIndex(aTree, curnode, 0);
|
||||
}
|
||||
|
||||
|
||||
Node* TreeBARSub(MQTT_Tree* aTree, Node* curnode, int which, int index)
|
||||
{
|
||||
Node* sibling = curnode->parent->child[which];
|
||||
|
||||
if (isRed(sibling))
|
||||
{
|
||||
sibling->red = 0;
|
||||
curnode->parent->red = 1;
|
||||
TreeRotate(aTree, curnode->parent, !which, index);
|
||||
sibling = curnode->parent->child[which];
|
||||
}
|
||||
if (!sibling)
|
||||
curnode = curnode->parent;
|
||||
else if (isBlack(sibling->child[!which]) && isBlack(sibling->child[which]))
|
||||
{
|
||||
sibling->red = 1;
|
||||
curnode = curnode->parent;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isBlack(sibling->child[which]))
|
||||
{
|
||||
sibling->child[!which]->red = 0;
|
||||
sibling->red = 1;
|
||||
TreeRotate(aTree, sibling, which, index);
|
||||
sibling = curnode->parent->child[which];
|
||||
}
|
||||
sibling->red = curnode->parent->red;
|
||||
curnode->parent->red = 0;
|
||||
sibling->child[which]->red = 0;
|
||||
TreeRotate(aTree, curnode->parent, !which, index);
|
||||
curnode = aTree->index[index].root;
|
||||
}
|
||||
return curnode;
|
||||
}
|
||||
|
||||
|
||||
void TreeBalanceAfterRemove(MQTT_Tree* aTree, Node* curnode, int index)
|
||||
{
|
||||
while (curnode != aTree->index[index].root && isBlack(curnode))
|
||||
{
|
||||
/* curnode->content == NULL must equal curnode == NULL */
|
||||
if (((curnode->content) ? curnode : NULL) == curnode->parent->child[LEFT])
|
||||
curnode = TreeBARSub(aTree, curnode, RIGHT, index);
|
||||
else
|
||||
curnode = TreeBARSub(aTree, curnode, LEFT, index);
|
||||
}
|
||||
curnode->red = 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove an item from a tree
|
||||
* @param aTree the list to which the item is to be added
|
||||
* @param curnode the list item content itself
|
||||
*/
|
||||
void* MQTTTreeRemoveNodeIndex(MQTT_Tree* aTree, Node* curnode, int index)
|
||||
{
|
||||
Node* redundant = curnode;
|
||||
Node* curchild = NULL;
|
||||
size_t size = curnode->size;
|
||||
void* content = curnode->content;
|
||||
|
||||
/* if the node to remove has 0 or 1 children, it can be removed without involving another node */
|
||||
if (curnode->child[LEFT] && curnode->child[RIGHT]) /* 2 children */
|
||||
redundant = TreeSuccessor(curnode); /* now redundant must have at most one child */
|
||||
|
||||
curchild = redundant->child[(redundant->child[LEFT] != NULL) ? LEFT : RIGHT];
|
||||
if (curchild) /* we could have no children at all */
|
||||
curchild->parent = redundant->parent;
|
||||
|
||||
if (redundant->parent == NULL)
|
||||
aTree->index[index].root = curchild;
|
||||
else
|
||||
{
|
||||
if (redundant == redundant->parent->child[LEFT])
|
||||
redundant->parent->child[LEFT] = curchild;
|
||||
else
|
||||
redundant->parent->child[RIGHT] = curchild;
|
||||
}
|
||||
|
||||
if (redundant != curnode)
|
||||
{
|
||||
curnode->content = redundant->content;
|
||||
curnode->size = redundant->size;
|
||||
}
|
||||
|
||||
if (isBlack(redundant))
|
||||
{
|
||||
if (curchild == NULL)
|
||||
{
|
||||
if (redundant->parent)
|
||||
{
|
||||
Node temp;
|
||||
memset(&temp, '\0', sizeof(Node));
|
||||
temp.parent = redundant->parent;
|
||||
temp.red = 0;
|
||||
TreeBalanceAfterRemove(aTree, &temp, index);
|
||||
}
|
||||
}
|
||||
else
|
||||
TreeBalanceAfterRemove(aTree, curchild, index);
|
||||
}
|
||||
|
||||
#if defined(UNIT_TESTS) || defined(NO_HEAP_TRACKING)
|
||||
free(redundant);
|
||||
#else
|
||||
(aTree->heap_tracking) ? myfree(__FILE__, __LINE__, redundant) : free(redundant);
|
||||
#endif
|
||||
if (index == 0)
|
||||
{
|
||||
aTree->size -= size;
|
||||
--(aTree->count);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove an item from a tree
|
||||
* @param aTree the list to which the item is to be added
|
||||
* @param curnode the list item content itself
|
||||
*/
|
||||
void* TreeRemoveIndex(MQTT_Tree* aTree, void* content, int index)
|
||||
{
|
||||
Node* curnode = TreeFindContentIndex(aTree, content, index);
|
||||
|
||||
if (curnode == NULL)
|
||||
return NULL;
|
||||
|
||||
return MQTTTreeRemoveNodeIndex(aTree, curnode, index);
|
||||
}
|
||||
|
||||
|
||||
void* MQTTTreeRemove(MQTT_Tree* aTree, void* content)
|
||||
{
|
||||
int i;
|
||||
void* rc = NULL;
|
||||
|
||||
for (i = 0; i < aTree->indexes; ++i)
|
||||
rc = TreeRemoveIndex(aTree, content, i);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
void* MQTTTreeRemoveKeyIndex(MQTT_Tree* aTree, void* key, int index)
|
||||
{
|
||||
Node* curnode = MQTTTreeFindIndex(aTree, key, index);
|
||||
void* content = NULL;
|
||||
int i;
|
||||
|
||||
if (curnode == NULL)
|
||||
return NULL;
|
||||
|
||||
content = MQTTTreeRemoveNodeIndex(aTree, curnode, index);
|
||||
for (i = 0; i < aTree->indexes; ++i)
|
||||
{
|
||||
if (i != index)
|
||||
content = TreeRemoveIndex(aTree, content, i);
|
||||
}
|
||||
return content;
|
||||
}
|
||||
|
||||
|
||||
void* MQTTTreeRemoveKey(MQTT_Tree* aTree, void* key)
|
||||
{
|
||||
return MQTTTreeRemoveKeyIndex(aTree, key, 0);
|
||||
}
|
||||
|
||||
|
||||
int MQTTTreeIntCompare(void* a, void* b, int content)
|
||||
{
|
||||
int i = *((int*)a);
|
||||
int j = *((int*)b);
|
||||
|
||||
/* printf("comparing %d %d\n", *((int*)a), *((int*)b)); */
|
||||
return (i > j) ? -1 : (i == j) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
int MQTTTreePtrCompare(void* a, void* b, int content)
|
||||
{
|
||||
return (a > b) ? -1 : (a == b) ? 0 : 1;
|
||||
}
|
||||
|
||||
|
||||
int MQTTTreeStringCompare(void* a, void* b, int content)
|
||||
{
|
||||
return strcmp((char*)a, (char*)b);
|
||||
}
|
||||
|
||||
|
||||
#if defined(UNIT_TESTS)
|
||||
|
||||
int check(MQTT_Tree *t)
|
||||
{
|
||||
Node* curnode = NULL;
|
||||
int rc = 0;
|
||||
|
||||
curnode = MQTTTreeNextElement(t, curnode);
|
||||
while (curnode)
|
||||
{
|
||||
Node* prevnode = curnode;
|
||||
|
||||
curnode = MQTTTreeNextElement(t, curnode);
|
||||
|
||||
if (prevnode && curnode && (*(int*)(curnode->content) < *(int*)(prevnode->content)))
|
||||
{
|
||||
printf("out of order %d < %d\n", *(int*)(curnode->content), *(int*)(prevnode->content));
|
||||
rc = 99;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int traverse(MQTT_Tree *t, int lookfor)
|
||||
{
|
||||
Node* curnode = NULL;
|
||||
int rc = 0;
|
||||
|
||||
printf("Traversing\n");
|
||||
curnode = MQTTTreeNextElement(t, curnode);
|
||||
/* printf("content int %d\n", *(int*)(curnode->content)); */
|
||||
while (curnode)
|
||||
{
|
||||
Node* prevnode = curnode;
|
||||
|
||||
curnode = MQTTTreeNextElement(t, curnode);
|
||||
/* if (curnode)
|
||||
printf("content int %d\n", *(int*)(curnode->content)); */
|
||||
if (prevnode && curnode && (*(int*)(curnode->content) < *(int*)(prevnode->content)))
|
||||
{
|
||||
printf("out of order %d < %d\n", *(int*)(curnode->content), *(int*)(prevnode->content));
|
||||
}
|
||||
if (curnode && (lookfor == *(int*)(curnode->content)))
|
||||
printf("missing item %d actually found\n", lookfor);
|
||||
}
|
||||
printf("End traverse %d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
int test(int limit)
|
||||
{
|
||||
int i, *ip, *todelete;
|
||||
Node* current = NULL;
|
||||
MQTT_Tree* t = MQTTTreeInitialize(MQTTTreeIntCompare);
|
||||
int rc = 0;
|
||||
|
||||
printf("MQTT_Tree initialized\n");
|
||||
|
||||
srand(time(NULL));
|
||||
|
||||
ip = malloc(sizeof(int));
|
||||
*ip = 2;
|
||||
MQTTTreeAdd(t, (void*)ip, sizeof(int));
|
||||
|
||||
check(t);
|
||||
|
||||
i = 2;
|
||||
void* result = MQTTTreeRemove(t, (void*)&i);
|
||||
if (result)
|
||||
free(result);
|
||||
|
||||
int actual[limit];
|
||||
for (i = 0; i < limit; i++)
|
||||
{
|
||||
void* replaced = NULL;
|
||||
|
||||
ip = malloc(sizeof(int));
|
||||
*ip = rand();
|
||||
replaced = MQTTTreeAdd(t, (void*)ip, sizeof(int));
|
||||
if (replaced) /* duplicate */
|
||||
{
|
||||
free(replaced);
|
||||
actual[i] = -1;
|
||||
}
|
||||
else
|
||||
actual[i] = *ip;
|
||||
if (i==5)
|
||||
todelete = ip;
|
||||
printf("MQTT_Tree element added %d\n", *ip);
|
||||
if (1 % 1000 == 0)
|
||||
{
|
||||
rc = check(t);
|
||||
printf("%d elements, check result %d\n", i+1, rc);
|
||||
if (rc != 0)
|
||||
return 88;
|
||||
}
|
||||
}
|
||||
|
||||
check(t);
|
||||
|
||||
for (i = 0; i < limit; i++)
|
||||
{
|
||||
int parm = actual[i];
|
||||
|
||||
if (parm == -1)
|
||||
continue;
|
||||
|
||||
Node* found = MQTTTreeFind(t, (void*)&parm);
|
||||
if (found)
|
||||
printf("MQTT_Tree find %d %d\n", parm, *(int*)(found->content));
|
||||
else
|
||||
{
|
||||
printf("%d not found\n", parm);
|
||||
traverse(t, parm);
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
check(t);
|
||||
|
||||
for (i = limit -1; i >= 0; i--)
|
||||
{
|
||||
int parm = actual[i];
|
||||
void *found;
|
||||
|
||||
if (parm == -1) /* skip duplicate */
|
||||
continue;
|
||||
|
||||
found = MQTTTreeRemove(t, (void*)&parm);
|
||||
if (found)
|
||||
{
|
||||
printf("%d MQTT_Tree remove %d %d\n", i, parm, *(int*)(found));
|
||||
free(found);
|
||||
}
|
||||
else
|
||||
{
|
||||
int count = 0;
|
||||
printf("%d %d not found\n", i, parm);
|
||||
traverse(t, parm);
|
||||
for (i = 0; i < limit; i++)
|
||||
if (actual[i] == parm)
|
||||
++count;
|
||||
printf("%d occurs %d times\n", parm, count);
|
||||
return -2;
|
||||
}
|
||||
if (i % 1000 == 0)
|
||||
{
|
||||
rc = check(t);
|
||||
printf("%d elements, check result %d\n", i+1, rc);
|
||||
if (rc != 0)
|
||||
return 88;
|
||||
}
|
||||
}
|
||||
printf("finished\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
while (rc == 0)
|
||||
rc = test(999999);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user