Commit 71fe8719 authored by Warren Dukes's avatar Warren Dukes

tree updates:

*) when CHILDREN_PER_NODE is large, use binary search *) add a iterator implementation *) some code cleanup git-svn-id: https://svn.musicpd.org/mpd/trunk@4492 09075e82-0dd4-0310-85a5-a0d7c8717e4f
parent 263a9d58
...@@ -5,6 +5,36 @@ ...@@ -5,6 +5,36 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#ifndef CHILDREN_PER_NODE
#define CHILDREN_PER_NODE 3
#endif
#define DATA_PER_NODE (CHILDREN_PER_NODE-1)
#if CHILDREN_PER_NODE > 11
#define USE_BINARY_SEARCH 1
#endif
/************************* DATA STRUCTURES **********************************/
struct _TreeNode
{
void * data[DATA_PER_NODE];
struct _TreeNode * parent;
struct _TreeNode * children[CHILDREN_PER_NODE];
int dataCount;
};
struct _Tree
{
TreeCompareDataFunction compareData;
TreeFreeDataFunction freeData;
TreeNode * rootNode;
};
/************************* STATIC METHODS ***********************************/
static static
TreeNode * TreeNode *
_MakeNode() _MakeNode()
...@@ -16,31 +46,63 @@ _MakeNode() ...@@ -16,31 +46,63 @@ _MakeNode()
static static
int int
_FindPositionInNode(Tree * tree, TreeNode * node, void * data, int * pos)
{
#ifdef USE_BINARY_SEARCH
int low = 0;
int high = node->dataCount;
int cmp = -1;
while (high > low)
{
int cur = (high + low) >> 1;
cmp = tree->compareData(data, node->data[cur]);
if (cmp > 0)
{
low = cur+1;
}
else if (cmp < 0)
{
high = cur;
}
else
{
low = cur;
break;
}
}
*pos = low;
return (cmp == 0);
#else
int i = 0;
int cmp = -1;
for (;
i < node->dataCount &&
(cmp = tree->compareData(data, node->data[i])) > 0;
i++);
*pos = i;
return (cmp == 0);
#endif
}
static
int
_Find(TreeIterator * iter, void * data) _Find(TreeIterator * iter, void * data)
{ {
while (1) while (1)
{ {
for (; iter->which < iter->node->dataCount; iter->which++) if (_FindPositionInNode(iter->tree,
iter->node,
data,
&iter->which))
{ {
int comp = iter->tree-> return 1;
compareData(data,iter->node->data[iter->which]);
if (comp == 0)
{
return 1;
}
else if (comp < 0)
{
break;
}
} }
assert(iter->which < CHILDREN_PER_NODE);
if (iter->node->children[iter->which]) if (iter->node->children[iter->which])
{ {
iter->node = iter->node->children[iter->which]; iter->node = iter->node->children[iter->which];
iter->which = 0;
} }
else else
{ {
...@@ -49,16 +111,6 @@ _Find(TreeIterator * iter, void * data) ...@@ -49,16 +111,6 @@ _Find(TreeIterator * iter, void * data)
} }
} }
Tree *
MakeTree(TreeCompareDataFunction compareData, TreeFreeDataFunction freeData)
{
Tree * ret = malloc(sizeof(Tree));
ret->compareData = compareData;
ret->freeData = freeData;
ret->rootNode = _MakeNode();
return ret;
}
static static
TreeNode * TreeNode *
_SplitNode(TreeNode * node) _SplitNode(TreeNode * node)
...@@ -67,21 +119,38 @@ _SplitNode(TreeNode * node) ...@@ -67,21 +119,38 @@ _SplitNode(TreeNode * node)
TreeNode * newNode = _MakeNode(); TreeNode * newNode = _MakeNode();
unsigned i = DATA_PER_NODE/2; #ifdef USE_MEM_FUNC
unsigned j = 0; memcpy(&(newNode->data[0]),
&(node->data[DATA_PER_NODE/2]),
(DATA_PER_NODE-DATA_PER_NODE/2)*sizeof(void *));
memset(&(node->data[DATA_PER_NODE/2]),
0,
(DATA_PER_NODE-DATA_PER_NODE/2)*sizeof(void *));
memcpy(&(newNode->children[1]),
&(node->children[DATA_PER_NODE/2+1]),
(DATA_PER_NODE-DATA_PER_NODE/2)*sizeof(TreeNode *));
memset(&(node->children[DATA_PER_NODE/2+1]),
0,
(DATA_PER_NODE-DATA_PER_NODE/2)*sizeof(TreeNode *));
#endif
int i = DATA_PER_NODE/2;
int j = 0;
for (; i < DATA_PER_NODE; i++, j++) for (; i < DATA_PER_NODE; i++, j++)
{ {
#ifndef USE_MEM_FUNC
newNode->data[j] = node->data[i]; newNode->data[j] = node->data[i];
newNode->children[j+1] = node->children[i+1]; newNode->children[j+1] = node->children[i+1];
node->data[i] = NULL;
node->children[i+1] = NULL;
#endif
if (newNode->children[j+1]) if (newNode->children[j+1])
{ {
newNode->children[j+1]->parent = newNode; newNode->children[j+1]->parent = newNode;
} }
node->data[i] = NULL;
node->children[i+1] = NULL;
} }
newNode->dataCount = j; newNode->dataCount = (DATA_PER_NODE-DATA_PER_NODE/2);
node->dataCount -= j; node->dataCount -= (DATA_PER_NODE-DATA_PER_NODE/2);
return newNode; return newNode;
} }
...@@ -102,23 +171,29 @@ _InsertNodeAndData(Tree * tree, ...@@ -102,23 +171,29 @@ _InsertNodeAndData(Tree * tree,
} }
int i = 0; int i = 0;
for (; _FindPositionInNode(tree, node, data, &i);
i < node->dataCount &&
tree->compareData(data, node->data[i]) > 0; #ifdef USE_MEM_FUNC
i++); memmove(&(node->data[i+1]),
&(node->data[i]),
(node->dataCount-i)*sizeof(void *));
memmove(&(node->children[i+2]),
&(node->children[i+1]),
(node->dataCount-i)*sizeof(TreeNode *));
#else
int j = node->dataCount; int j = node->dataCount;
for (; j > i; j--) for (; j > i; j--)
{ {
node->data[j] = node->data[j-1]; node->data[j] = node->data[j-1];
node->children[j+1] = node->children[j]; node->children[j+1] = node->children[j];
} }
#endif
assert(!node->children[j] || assert(!node->children[i] ||
tree->compareData(data, node->children[j]->data[0]) > 0); tree->compareData(data, node->children[i]->data[0]) > 0);
node->data[j] = data; node->data[i] = data;
node->children[j+1] = newNode; node->children[i+1] = newNode;
node->dataCount++; node->dataCount++;
} }
...@@ -150,10 +225,7 @@ _AddDataToSplitNodes(Tree * tree, ...@@ -150,10 +225,7 @@ _AddDataToSplitNodes(Tree * tree,
} }
int i = 0; int i = 0;
for (; _FindPositionInNode(tree, moreNode, data, &i);
i < moreNode->dataCount &&
tree->compareData(data, moreNode->data[i]) > 0;
i++);
if (i == 0) if (i == 0)
{ {
...@@ -165,19 +237,28 @@ _AddDataToSplitNodes(Tree * tree, ...@@ -165,19 +237,28 @@ _AddDataToSplitNodes(Tree * tree,
retData = moreNode->data[0]; retData = moreNode->data[0];
} }
#ifdef USE_MEM_FUNC
memmove(&(moreNode->data[0]),
&(moreNode->data[1]),
i*sizeof(void *));
memmove(&(moreNode->children[0]),
&(moreNode->children[1]),
i*sizeof(TreeNode *));
#else
int j = 0; int j = 0;
for (; j < i; j++) for (; j < i; j++)
{ {
moreNode->data[j] = moreNode->data[j+1]; moreNode->data[j] = moreNode->data[j+1];
moreNode->children[j] = moreNode->children[j+1]; moreNode->children[j] = moreNode->children[j+1];
} }
#endif
assert(!moreNode->children[j-1] || assert(!moreNode->children[i-1] ||
tree->compareData(data, tree->compareData(data,
moreNode->children[j]->data[0]) > 0); moreNode->children[i]->data[0]) > 0);
moreNode->data[j-1] = data; moreNode->data[i-1] = data;
moreNode->children[j] = newNode; moreNode->children[i] = newNode;
} }
return retData; return retData;
...@@ -236,18 +317,90 @@ _InsertAt(TreeIterator * iter, void * data) ...@@ -236,18 +317,90 @@ _InsertAt(TreeIterator * iter, void * data)
return; return;
} }
void SetIteratorToBegin(TreeIterator * iter, Tree * tree) static void _SetTreeIteratorToRoot(TreeIterator * iter, Tree * tree)
{ {
iter->tree = tree; iter->tree = tree;
iter->node = tree->rootNode; iter->node = tree->rootNode;
iter->which = 0; iter->which = 0;
} }
/************************* PUBLIC METHODS ***********************************/
Tree *
MakeTree(TreeCompareDataFunction compareData, TreeFreeDataFunction freeData)
{
Tree * ret = malloc(sizeof(Tree));
ret->compareData = compareData;
ret->freeData = freeData;
ret->rootNode = _MakeNode();
return ret;
}
void SetTreeIteratorToBegin(TreeIterator * iter, Tree * tree)
{
_SetTreeIteratorToRoot(iter, tree);
IncrementTreeIterator(iter);
}
int IsTreeIteratorAtEnd(const TreeIterator * iter)
{
return (iter->node == NULL);
}
void IncrementTreeIterator(TreeIterator * iter)
{
while(iter->node)
{
if (iter->node->children[iter->which])
{
iter->node = iter->node->children[iter->which];
iter->which = 0;
}
else
{
iter->which++;
}
while (iter->node && iter->which > iter->node->dataCount)
{
TreeNode * childNode = iter->node;
iter->node = childNode->parent;
if (iter->node)
{
for (iter->which = 0;
childNode !=
iter->node->children[iter->which];
iter->which++)
{
assert(iter->which <=
iter->node->dataCount);
}
iter->which++;
}
}
if (iter->node &&
iter->which > 0 && iter->which <= iter->node->dataCount)
{
return;
}
}
}
void *
GetDataFromTreeIterator(TreeIterator * iter)
{
assert(iter->node &&
iter->which > 0 &&
iter->which <= iter->node->dataCount);
return iter->node->data[iter->which-1];
}
int int
InsertIntoTree(Tree * tree, void * data) InsertIntoTree(Tree * tree, void * data)
{ {
TreeIterator iter; TreeIterator iter;
SetIteratorToBegin(&iter, tree); _SetTreeIteratorToRoot(&iter, tree);
if (_Find(&iter, data)) if (_Find(&iter, data))
{ {
......
#define CHILDREN_PER_NODE 3 #ifndef TREE_H
#define DATA_PER_NODE 2 #define TREE_H
typedef struct _TreeNode typedef struct _Tree Tree;
{ typedef struct _TreeNode TreeNode;
void * data[DATA_PER_NODE]; typedef struct _TreeIterator TreeIterator;
struct _TreeNode * parent;
struct _TreeNode * children[CHILDREN_PER_NODE];
unsigned dataCount;
} TreeNode;
typedef int (*TreeCompareDataFunction)(void * data1, void * data2);
typedef void (*TreeFreeDataFunction)(void * data);
typedef struct _Tree
{
TreeCompareDataFunction compareData;
TreeFreeDataFunction freeData;
TreeNode * rootNode;
} Tree;
typedef struct _TreeIterator struct _TreeIterator
{ {
Tree * tree; Tree * tree;
TreeNode * node; TreeNode * node;
unsigned which; int which;
} TreeIterator; };
typedef int (*TreeCompareDataFunction)(const void * data1, const void * data2);
typedef void (*TreeFreeDataFunction)(void * data);
Tree * MakeTree(TreeCompareDataFunction compareFunc, Tree * MakeTree(TreeCompareDataFunction compareFunc,
TreeFreeDataFunction freeData); TreeFreeDataFunction freeData);
void SetIteratorToBegin(TreeIterator * iter, Tree * tree); void SetTreeIteratorToBegin(TreeIterator * iter, Tree * tree);
int IsTreeIteratorAtEnd(const TreeIterator * iter);
void IncrementTreeIterator(TreeIterator * iter);
void * GetDataFromTreeIterator(TreeIterator * iter);
int InsertIntoTree(Tree * tree, void * data); int InsertIntoTree(Tree * tree, void * data);
void DeleteFromTree(Tree * tree, void * data); void DeleteFromTree(Tree * tree, void * data);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment