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 }