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 }