liblash

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

tree.c (5901B)


      1 #include <stdlib.h>
      2 #include <stdio.h>
      3 #include <string.h>
      4 
      5 #include "tree.h"
      6 
      7 
      8 lash_tree_t *lash_treeInit(lash_tree_t *tree, const unsigned int size) {
      9 	tree = (lash_tree_t*)malloc(sizeof(lash_tree_t));
     10 	tree->key = (lash_tree_key_t**)malloc(sizeof(lash_tree_key_t*) * size + 1);
     11 	tree->item = (void*)malloc(sizeof(void*) * size + 1);
     12 	
     13 	if (tree->key == NULL || tree->item == NULL)
     14 		return NULL;
     15 		
     16 	tree->count = 0;
     17 	//tree->shiftpos = 0;
     18 	tree->capacity = size;
     19 	//tree->foldbackthreshold = tree->capacity / 2;
     20 	
     21 	return tree;
     22 }
     23 
     24 void lash_treeFree(lash_tree_t *tree) {
     25 	if (tree == NULL)
     26 		return;
     27 		
     28 	if (tree->key != NULL)
     29 		free(tree->key);
     30 	
     31 	if (tree->item != NULL)
     32 		free(tree->item);
     33 	
     34 	free(tree);
     35 }
     36 
     37 // key is optional, if NULL is passed, then tree assumes a lash_tree_key_t at first address of item pointer
     38 int lash_treePush(lash_tree_t *tree, void *item, lash_tree_key_t *key) {
     39 	//printf("%p", item);
     40 	
     41 	if (tree->count == tree->capacity)
     42 		return -1;
     43 	
     44 	tree->count++;
     45 	
     46 	if (key != NULL)
     47 		*(tree->key + tree->count - 1) = key;
     48 	else
     49 		*(tree->key + tree->count - 1) = (lash_tree_key_t*)item;
     50 		
     51 	*(tree->item + tree->count - 1) = item;
     52 	
     53 	_lash_treeProcess(tree, tree->count, -1);
     54 	
     55 	return tree->count;
     56 }
     57 
     58 int lash_treeShift(lash_tree_t *tree, void **item) {
     59 	return lash_treeRemove(tree, 0, item);
     60 }	
     61 
     62 int lash_treeRemove(lash_tree_t *tree, unsigned int position, void **item) {
     63 
     64 	if (tree->count == 0)
     65 		return -1;
     66 	
     67 	// retrieve the values from the position from the argument
     68 	*item = *(tree->item + position);
     69 	
     70 	// move the values from the end of the tree to the position from the argument
     71 	*(tree->key + position) = *(tree->key + tree->count - 1);
     72 	*(tree->item + position) = *(tree->item + tree->count - 1);
     73 	
     74 	// reduce the count of the tree
     75 	tree->count--;
     76 	
     77 	// iterate the new value down the tree to its proper place
     78 	_lash_treeProcess(tree, position + 1, 1);
     79 	
     80 	return tree->count;
     81 }
     82 
     83 int _lash_treeProcess(lash_tree_t *tree, unsigned int currentposition, int direction) {
     84 
     85 	// towards end of pointer is downwards in the tree
     86 	// the direction to sort, -1 is from end towards start, 1 is from startposition towards end
     87 	
     88 	while (direction != 0) {
     89 		
     90 		lash_tree_key_t *currentkey = *(tree->key + currentposition - 1);
     91 		lash_tree_key_t *nextkey = NULL;
     92 		lash_tree_key_t *swapkey;
     93 		//lash_tree_key_t swapkey;
     94 		void *swapitem;;
     95 		void *currentitem;
     96 		void *nextitem;
     97 		
     98 		unsigned int nextposition;
     99 	
    100 		switch(direction) {
    101 			
    102 			// if there is still room to ascend in the tree, that is if the current position isn't 0 already.
    103 			case -1:
    104 				if (currentposition == 1) {
    105 					direction = 0;
    106 				} else {
    107 					nextposition = currentposition >> 1;	
    108 					nextkey = *(tree->key + nextposition - 1);
    109 					if (*currentkey < *nextkey) {
    110 						/*swapkey = *currentkey;
    111 						*currentkey = *nextkey;
    112 						*nextkey = swapkey;*/
    113 						
    114 						currentitem = *(tree->item + currentposition - 1);
    115 						nextitem = *(tree->item + nextposition - 1);
    116 						
    117 						swapkey = currentkey;
    118 						*(tree->key + currentposition - 1) = nextkey;
    119 						*(tree->key + nextposition - 1) = swapkey;
    120 						
    121 						// ORIGINALLY IT SEEMED LIKE WHEN THE ADDRESS WAS THE SAME THAT THIS WOULD SHIFT THINGS AROUND TWICE
    122 						// NOW IT WORKS IF THE ADDRESS OF THE KEY AND THE FIRST ADDRESS OF THE ITEM ARE THE SAME
    123 						// if the position of the key is not in the first address of the item we need to move it separately
    124 						// note that swapkey now holds the original currentkey
    125 						//if ((lash_tree_key_t *)currentitem != swapkey) {
    126 							swapitem = currentitem;
    127 							*(tree->item + currentposition - 1) = nextitem;
    128 							*(tree->item + nextposition - 1) = swapitem;
    129 						//}
    130 						
    131 						currentposition = nextposition;
    132 					} else {
    133 						direction = 0;
    134 					}
    135 				}
    136 				break;
    137 			
    138 			// if there is still room from the current position to descend one level in the tree):
    139 			// level 0 has 2^0 = entry 1
    140 			// level 1 has 2^1 = entries 2-3
    141 			// level 2 has 2^2 = entries 4-7
    142 			// if we're at position 3, the check will be 3*2 = 6, which is within bounds of level 2, and points to elements 6 and 7 (the children of 3)
    143 			// If we're at position 4, the check will be 4*2 = 8, which is out of bounds of level 2.
    144 			
    145 			case 1:
    146 				nextposition = currentposition << 1;	
    147 				
    148 				if (nextposition <= tree->count) {
    149 					
    150 					// compare both the child values, to pick the higher one
    151 					nextkey = *(tree->key + nextposition - 1);
    152 					if (*nextkey > **(tree->key + nextposition)) {
    153 						nextkey = *(tree->key + nextposition); 
    154 						nextposition++;
    155 					}
    156 					
    157 					// compare the values, set nextkey back to null to stop the swapping if the value is not higher
    158 					if (*currentkey <= *nextkey) {
    159 						nextkey = NULL;
    160 					}
    161 				
    162 					if (nextkey != NULL) {
    163 						/*swapkey = *currentkey;
    164 						*currentkey = *nextkey;
    165 						*nextkey = swapkey;*/
    166 						
    167 						currentitem = *(tree->item + currentposition - 1);
    168 						nextitem = *(tree->item + nextposition - 1);
    169 						
    170 						swapkey = currentkey;
    171 						*(tree->key + currentposition - 1) = nextkey;
    172 						*(tree->key + nextposition - 1) = swapkey;
    173 						
    174 						// ORIGINALLY IT SEEMED LIKE WHEN THE ADDRESS WAS THE SAME THAT THIS WOULD SHIFT THINGS AROUND TWICE
    175 						// NOW IT WORKS IF THE ADDRESS OF THE KEY AND THE FIRST ADDRESS OF THE ITEM ARE THE SAME
    176 						// if the position of the key is not in the first address of the item we need to move it separately
    177 						// note that swapkey holds the original currentkey value
    178 						//if ((lash_tree_key_t *)currentitem != swapkey) {
    179 							swapitem = currentitem;
    180 							*(tree->item + currentposition - 1) = nextitem;
    181 							*(tree->item + nextposition - 1) = swapitem;
    182 						//}
    183 						
    184 						currentposition = nextposition;
    185 					} else {
    186 						direction = 0;
    187 					}
    188 				} else {
    189 					direction = 0;
    190 				}
    191 				break;
    192 			default:
    193 				direction = 0;
    194 		}
    195 	}	
    196 	
    197 	return currentposition;
    198 }