liblash

A bianry tree implementation used for game development from scratch
git clone git://holbrook.no/liblash.git
Log | Files | Refs | LICENSE

lash_tree.c (7330B)


      1 #include <stdlib.h>
      2 #include "liblash/lash_tree.h"
      3 #include <stdio.h>
      4 #include "liblash/lash_tree_dump.h"
      5 
      6 lash_tree_t *lash_treeInit(lash_tree_t *tree, const unsigned int size) {
      7 	int i;
      8 	tree = (lash_tree_t*)malloc(sizeof(lash_tree_t));
      9 	tree->heap = (long int*)malloc(sizeof(long int) * size);
     10 	tree->local = (unsigned int*)calloc(size, sizeof(unsigned int*));
     11 	tree->idx = (int*)malloc(sizeof(int) * size);
     12 	if (tree->heap == NULL || tree->idx == NULL)
     13 		return NULL;
     14 	
     15 	for (i = 0; i < size; i++)
     16 		*(tree->idx + i) = -1;
     17 		
     18 	tree->position = 0;
     19 	tree->capacity = size;
     20 	*tree->idx = 0;
     21 	
     22 	return tree;
     23 }
     24 
     25 
     26 //int lash_treePush(lash_tree_t *ptree, const long int sortvalue, void *content) {
     27 int lash_treePush(lash_tree_t *tree, const long int sortvalue, const int local) {
     28 	
     29 	if (tree->position == tree->capacity)
     30 		return -1;
     31 	
     32 	tree->position++;
     33 	
     34 	// put the new number at the end of the content array and update the current position
     35 	*(tree->idx + tree->position - 1) = tree->position - 1;
     36 	*(tree->heap + tree->position - 1) = sortvalue;
     37 	*(tree->local + tree->position - 1) = local;
     38 	
     39 	// put the content array index to the new number on the index array
     40 	
     41 	
     42 	// increase the average (for faster searching later)
     43 	int tmpaverage = tree->average;
     44 	tmpaverage *= (tree->position - 1);
     45 	tmpaverage += sortvalue;
     46 	tmpaverage /= tree->position;
     47 	tree->average = tmpaverage; 
     48 	
     49 	return lash_treeItemProcess(tree, tree->position);
     50 }
     51 
     52 int lash_treeShift(lash_tree_t *tree, long int *number, unsigned int *local) {
     53 	return lash_treeRemove(tree, 0, number, local);
     54 }
     55 
     56 // note that here position is 1 for first, not 0
     57 int lash_treeRemove(lash_tree_t *tree, unsigned int position, long int *number, unsigned int *local) {	
     58 	long int currentnumber;
     59 	long int currentindex;
     60 	int i;
     61 	int result;
     62 	
     63 	if (tree->position == 0)
     64 		return -1;
     65 	
     66 	if (position > tree->position) 
     67 		return -1;
     68 		
     69 	// if there is only one item, retrieve this and finish	
     70 	if (tree->position == 1) {
     71 		if (number != NULL)
     72 			*number = *(tree->heap + *tree->idx);
     73 		if (local != NULL)
     74 			*local = *(tree->local + *tree->idx);
     75 		tree->position = 0;
     76 		//tree->idx = 0;
     77 		return 0;
     78 	}
     79 	
     80 	// if no position is set, then take the top of the heap
     81 	if (position == 0)
     82 		position = 1;
     83 	
     84 	// remove the number on the supplied index, and move the number from the bottom in its place
     85 	currentindex = *(tree->idx + position - 1);
     86 	currentnumber = *(tree->heap + currentindex);
     87 	
     88 	if (number != NULL)
     89 		*number = currentnumber;
     90 	if (local != NULL)
     91 		*local = *(tree->local + currentindex);
     92 		
     93 	*(tree->idx + currentindex) = tree->position - 1;
     94 	
     95 	//*(tree->local + currentindex) = *(tree->local + *(tree->idx + tree->position - 1));
     96 	//*(tree->heap + currentindex) = *(tree->heap + *(tree->idx + tree->position - 1));
     97 	//*(tree->idx + position - 1) = *(tree->idx + tree->position - 1);
     98 	//*(tree->idx + tree->position - 1) = currentindex;
     99 	
    100 	tree->position--;
    101 	
    102 	// decrease the average (for faster searching later)
    103 	if (tree->position == 0) {
    104 		tree->average = 0;
    105 	} else {
    106 		int tmpaverage = tree->average;
    107 		tmpaverage *= (tree->position + 1);
    108 		//tmpaverage -= *number;
    109 		tmpaverage -= currentnumber;
    110 		tmpaverage /= tree->position;
    111 		tree->average = tmpaverage;
    112 	}
    113 	
    114 	result = lash_treeItemProcess(tree, position);
    115 	
    116 	// this probably defeats the speed gain from binary tree.
    117 	for (i = position; i <= tree->position; i++) {
    118 		*(tree->heap + i - 1) = *(tree->heap + i);
    119 		*(tree->local + i - 1) = *(tree->local + i);
    120 		*(tree->idx + i - 1) -= 1;
    121 	}
    122 	
    123 	return result;
    124 	
    125 	
    126 }
    127 
    128 // note that here currentposition is 1 for first, not 0
    129 int lash_treeItemProcess(lash_tree_t *tree, unsigned int currentposition) {
    130 	
    131 	// choose direction (-1 is up, 1 is down)
    132 	int direction = 0;
    133 	unsigned int newposition = 0;
    134 	
    135 	if (tree->position == 1) {
    136 		return (int)1;
    137 	} else if (currentposition <= 1) {
    138 		currentposition = 1;
    139 		direction = 1;
    140 		newposition = currentposition * 2;
    141 		// if it's the first value
    142 		
    143 	} else if (currentposition * 2 <= tree->position) {
    144 		if (*(tree->heap + *(tree->idx + currentposition - 1)) > *(tree->heap + *(tree->idx + (currentposition * 2) - 1)) || *(tree->heap + *(tree->idx + currentposition - 1)) > *(tree->heap + *(tree->idx + (currentposition * 2)))) {
    145 			direction = 1;
    146 			newposition = (currentposition * 2);
    147 		}
    148 	} else if (*(tree->heap + *(tree->idx + currentposition - 1)) < *(tree->heap + *(tree->idx + (int)(currentposition / 2) - 1))) {
    149 		direction = -1;	
    150 		newposition = (unsigned int)currentposition / 2;
    151 	}
    152 	
    153 	switch (direction) {
    154 		case -1:
    155 			// move the content index up the index array until the number above in the heap is smaller or equal, or until we hit the start of the heap
    156 			while (newposition > 0) {
    157 				if (*(tree->heap + *(tree->idx + newposition - 1)) > *(tree->heap + *(tree->idx + currentposition - 1))) {
    158 					int tmpindex = *(tree->idx + newposition - 1);
    159 					*(tree->idx + newposition - 1) = *(tree->idx + currentposition - 1);
    160 					*(tree->idx + currentposition - 1) = tmpindex;
    161 				} else {
    162 					break;
    163 				}
    164 				currentposition = newposition;
    165 				newposition = (unsigned int)newposition / 2;
    166 			}
    167 			break;
    168 		case 1:
    169 			// until end of heap is reached, or the next number is higher
    170 			while (newposition <= tree->position) {
    171 				unsigned int swapposition = currentposition;
    172 				// move to next level if the next level child is higher
    173 				if (*(tree->heap + *(tree->idx + newposition - 1)) < *(tree->heap + *(tree->idx + currentposition - 1))) {
    174 					swapposition = newposition;
    175 					// check if either of the left or right children are higher (if there are two children, if not we're at the end of the heap)
    176 					if (newposition + 1 <= tree->position)
    177 						// if the right child is higher, then move there
    178 						if (*(tree->heap + *(tree->idx + newposition)) < *(tree->heap + *(tree->idx + newposition - 1)))
    179 							swapposition = newposition + 1;
    180 				} else if (newposition + 1 <= tree->position) {
    181 					if (*(tree->heap + *(tree->idx + newposition)) < *(tree->heap + *(tree->idx + currentposition - 1)))
    182 						// if the right child is higher, then move there
    183 						if (*(tree->heap + *(tree->idx + newposition)) < *(tree->heap + *(tree->idx + newposition - 1)))
    184 							swapposition = newposition + 1;
    185 				}
    186 		
    187 				// if a move has taken place
    188 				if (swapposition != currentposition) {
    189 					unsigned int tmpindex = *(tree->idx + currentposition - 1);
    190 					*(tree->idx + currentposition - 1) = *(tree->idx + swapposition - 1);
    191 					*(tree->idx + swapposition - 1) = tmpindex;
    192 				} else {
    193 					break;
    194 				}
    195 		
    196 				currentposition = swapposition;
    197 				newposition = swapposition * 2;
    198 			}
    199 			break;
    200 		default:
    201 			currentposition = 0;
    202 			newposition = 0;
    203 	}
    204 	
    205 	return (int)currentposition;
    206 }
    207 
    208 int lash_treeFindByLocal(lash_tree_t *tree, const int local) {
    209 	int i;
    210 	for (i = tree->position - 1; i >= 0; i--) {
    211 		if (*(tree->local + *(tree->idx + i)) == local)
    212 			return i;
    213 	}
    214 	return -1;
    215 }
    216 
    217 int lash_treeFindBySort(lash_tree_t *tree, const int sortvalue) {
    218 	int i;
    219 	for (i = tree->position - 1; i >= 0; i--) {
    220 		if (*(tree->heap + *(tree->idx + i)) == sortvalue)		
    221 			return i;
    222 	}
    223 	return -1;
    224 }
    225 
    226 void lash_treeFree(lash_tree_t *tree) {
    227 	if (tree != NULL) {
    228 		if (tree->local != NULL)
    229 			free(tree->local);
    230 		if (tree->heap != NULL)
    231 			free(tree->heap);
    232 		if (tree->idx != NULL)
    233 			free(tree->idx);
    234 		free(tree);
    235 	}
    236 }