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 }