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.fail (8414B)


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