/*! * swapUp() * * Input: lh (heap) * index (of array corresponding to node to be swapped up) * Return: 0 if OK, 1 on error * * Notes: * (1) This is called after a new item is put on the heap, at the * bottom of a complete tree. * (2) To regain the heap order, we let it bubble up, * iteratively swapping with its parent, until it either * reaches the root of the heap or it finds a parent that * is in the correct position already vis-a-vis the child. */ int MinHeap::swapUp(int index) { int ip; /* index to heap for parent; 1 larger than array index */ int ic; /* index into heap for child */ double valp, valc; if (index < 0 || index >= this->n) return 1; ic = index + 1; /* index into heap: add 1 to array index */ if (this->direction == L_SORT_INCREASING) { while (1) { if (ic == 1) /* root of heap */ break; ip = ic / 2; valc = this->ptrArray[ic - 1]->key; valp = this->ptrArray[ip - 1]->key; if (valp <= valc) break; SWAP_ITEMS(ip - 1, ic - 1); ic = ip; } } else { /* lh->direction == L_SORT_DECREASING */ while (1) { if (ic == 1) /* root of heap */ break; ip = ic / 2; valc = this->ptrArray[ic - 1]->key; valp = this->ptrArray[ip - 1]->key; if (valp >= valc) break; SWAP_ITEMS(ip - 1, ic - 1); ic = ip; } } return ic; }
/*! * lheapSwapUp() * * Input: lh (heap) * index (of array corresponding to node to be swapped up) * Return: 0 if OK, 1 on error * * Notes: * (1) This is called after a new item is put on the heap, at the * bottom of a complete tree. * (2) To regain the heap order, we let it bubble up, * iteratively swapping with its parent, until it either * reaches the root of the heap or it finds a parent that * is in the correct position already vis-a-vis the child. */ l_int32 lheapSwapUp(L_HEAP *lh, l_int32 index) { l_int32 ip; /* index to heap for parent; 1 larger than array index */ l_int32 ic; /* index into heap for child */ l_float32 valp, valc; PROCNAME("lheapSwapUp"); if (!lh) return ERROR_INT("lh not defined", procName, 1); if (index < 0 || index >= lh->n) return ERROR_INT("invalid index", procName, 1); ic = index + 1; /* index into heap: add 1 to array index */ if (lh->direction == L_SORT_INCREASING) { while (1) { if (ic == 1) /* root of heap */ break; ip = ic / 2; valc = *(l_float32 *)(lh->array[ic - 1]); valp = *(l_float32 *)(lh->array[ip - 1]); if (valp <= valc) break; SWAP_ITEMS(ip - 1, ic - 1); ic = ip; } } else { /* lh->direction == L_SORT_DECREASING */ while (1) { if (ic == 1) /* root of heap */ break; ip = ic / 2; valc = *(l_float32 *)(lh->array[ic - 1]); valp = *(l_float32 *)(lh->array[ip - 1]); if (valp >= valc) break; SWAP_ITEMS(ip - 1, ic - 1); ic = ip; } } return 0; }
/*! * sortStrictOrder() * * Input: lh (heap, with internal array) * Return: 0 if OK, 1 on error * * Notes: * (1) This sorts a heap into strict order. * (2) For each element, starting at the end of the array and * working forward, the element is swapped with the head * element and then allowed to swap down onto a heap of * size reduced by one. The result is that the heap is * reversed but in strict order. The array elements are * then reversed to put it in the original order. */ int MinHeap::sortStrictOrder() { int i, index, size; size = this->n; /* save the actual size */ for (i = 0; i < size; i++) { index = size - i; SWAP_ITEMS(0, index - 1); this->n--; /* reduce the apparent heap size by 1 */ swapDown(); } this->n = size; /* restore the size */ for (i = 0; i < size / 2; i++) /* reverse */ SWAP_ITEMS(i, size - i - 1); return 0; }
/*! * lheapSortStrictOrder() * * Input: lh (heap, with internal array) * Return: 0 if OK, 1 on error * * Notes: * (1) This sorts a heap into strict order. * (2) For each element, starting at the end of the array and * working forward, the element is swapped with the head * element and then allowed to swap down onto a heap of * size reduced by one. The result is that the heap is * reversed but in strict order. The array elements are * then reversed to put it in the original order. */ l_int32 lheapSortStrictOrder(L_HEAP *lh) { l_int32 i, index, size; PROCNAME("lheapSortStrictOrder"); if (!lh) return ERROR_INT("lh not defined", procName, 1); size = lh->n; /* save the actual size */ for (i = 0; i < size; i++) { index = size - i; SWAP_ITEMS(0, index - 1); lh->n--; /* reduce the apparent heap size by 1 */ lheapSwapDown(lh); } lh->n = size; /* restore the size */ for (i = 0; i < size / 2; i++) /* reverse */ SWAP_ITEMS(i, size - i - 1); return 0; }
/*! * lheapSwapDown() * * Input: lh (heap) * Return: 0 if OK, 1 on error * * Notes: * (1) This is called after an item has been popped off the * root of the heap, and the last item in the heap has * been placed at the root. * (2) To regain the heap order, we let it bubble down, * iteratively swapping with one of its children. For a * decreasing sort, it swaps with the largest child; for * an increasing sort, the smallest. This continues until * it either reaches the lowest level in the heap, or the * parent finds that neither child should swap with it * (e.g., for a decreasing heap, the parent is larger * than or equal to both children). */ l_int32 lheapSwapDown(L_HEAP *lh) { l_int32 ip; /* index to heap for parent; 1 larger than array index */ l_int32 icr, icl; /* index into heap for left/right children */ l_float32 valp, valcl, valcr; PROCNAME("lheapSwapDown"); if (!lh) return ERROR_INT("lh not defined", procName, 1); if (lheapGetCount(lh) < 1) return 0; ip = 1; /* index into top of heap: corresponds to array[0] */ if (lh->direction == L_SORT_INCREASING) { while (1) { icl = 2 * ip; if (icl > lh->n) break; valp = *(l_float32 *)(lh->array[ip - 1]); valcl = *(l_float32 *)(lh->array[icl - 1]); icr = icl + 1; if (icr > lh->n) { /* only a left child; no iters below */ if (valp > valcl) SWAP_ITEMS(ip - 1, icl - 1); break; } else { /* both children exist; swap with the smallest if bigger */ valcr = *(l_float32 *)(lh->array[icr - 1]); if (valp <= valcl && valp <= valcr) /* smaller than both */ break; if (valcl <= valcr) { /* left smaller; swap */ SWAP_ITEMS(ip - 1, icl - 1); ip = icl; } else { /* right smaller; swap */ SWAP_ITEMS(ip - 1, icr - 1); ip = icr; } } } } else { /* lh->direction == L_SORT_DECREASING */ while (1) { icl = 2 * ip; if (icl > lh->n) break; valp = *(l_float32 *)(lh->array[ip - 1]); valcl = *(l_float32 *)(lh->array[icl - 1]); icr = icl + 1; if (icr > lh->n) { /* only a left child; no iters below */ if (valp < valcl) SWAP_ITEMS(ip - 1, icl - 1); break; } else { /* both children exist; swap with the biggest if smaller */ valcr = *(l_float32 *)(lh->array[icr - 1]); if (valp >= valcl && valp >= valcr) /* bigger than both */ break; if (valcl >= valcr) { /* left bigger; swap */ SWAP_ITEMS(ip - 1, icl - 1); ip = icl; } else { /* right bigger; swap */ SWAP_ITEMS(ip - 1, icr - 1); ip = icr; } } } } return 0; }
/*! * swapDown() * * Input: lh (heap) * Return: 0 if OK, 1 on error * * Notes: * (1) This is called after an item has been popped off the * root of the heap, and the last item in the heap has * been placed at the root. * (2) To regain the heap order, we let it bubble down, * iteratively swapping with one of its children. For a * decreasing sort, it swaps with the largest child; for * an increasing sort, the smallest. This continues until * it either reaches the lowest level in the heap, or the * parent finds that neither child should swap with it * (e.g., for a decreasing heap, the parent is larger * than or equal to both children). */ int MinHeap::swapDown() { int ip; /* index to heap for parent; 1 larger than array index */ int icr, icl; /* index into heap for left/right children */ double valp, valcl, valcr; if (getCount() < 1) return 0; ip = 1; /* index into top of heap: corresponds to array[0] */ if (this->direction == L_SORT_INCREASING) { while (1) { icl = 2 * ip; if (icl > this->n) break; valp = this->ptrArray[ip - 1]->key; valcl = this->ptrArray[icl - 1]->key; icr = icl + 1; if (icr > this->n) { /* only a left child; no iters below */ if (valp > valcl) SWAP_ITEMS(ip - 1, icl - 1); break; } else { /* both children present; swap with the smallest if bigger */ valcr = this->ptrArray[icr - 1]->key; if (valp <= valcl && valp <= valcr) /* smaller than both */ break; if (valcl <= valcr) { /* left smaller; swap */ SWAP_ITEMS(ip - 1, icl - 1); ip = icl; } else { /* right smaller; swap */ SWAP_ITEMS(ip - 1, icr - 1); ip = icr; } } } } else { /* lh->direction == L_SORT_DECREASING */ while (1) { icl = 2 * ip; if (icl > this->n) break; valp = this->ptrArray[ip - 1]->key; valcl = this->ptrArray[icl - 1]->key; icr = icl + 1; if (icr > this->n) { /* only a left child; no iters below */ if (valp < valcl) SWAP_ITEMS(ip - 1, icl - 1); break; } else { /* both children present; swap with the biggest if smaller */ valcr = this->ptrArray[icr - 1]->key; if (valp >= valcl && valp >= valcr) /* bigger than both */ break; if (valcl >= valcr) { /* left bigger; swap */ SWAP_ITEMS(ip - 1, icl - 1); ip = icl; } else { /* right bigger; swap */ SWAP_ITEMS(ip - 1, icr - 1); ip = icr; } } } } return 0; }
// sort LR_ITEM_SET list for easy comparison LR_ITEM_SET* Sort(LR_ITEM_SET* I) { LR_ITEM_SET* itr; LR_ITEM* heap; int i, size; if (I == NULL) return I; // count elements [O(N)] size = 0; for (itr = I; itr; itr = itr->next) { size++; } // allocate heap [O(1)] heap = malloc(sizeof(LR_ITEM) * size); // add items to the heap [O(N log N)] for (itr = I, i = 0; itr; itr = itr->next, i++) { heap[i] = itr->item; int a = i; int b = (i-1)/2; while (a > 0 && CompareItems(heap[a], heap[b]) < 0) { SWAP_ITEMS(&heap[a], &heap[b]); a = b; b = (b-1)/2; } } // pop items off the heap [O(N log N)] for (itr = I; itr; itr = itr->next) { itr->item = heap[0]; size--; heap[0] = heap[size]; int j = 0; int a = 1; int b = 2; while (j < size && ((a < size && CompareItems(heap[j], heap[a]) > 0) || (b < size && CompareItems(heap[j], heap[b]) > 0))) { if (b < size && CompareItems(heap[a], heap[b]) > 0) { SWAP_ITEMS(&heap[b], &heap[j]); j = b; } else { SWAP_ITEMS(&heap[a], &heap[j]); j = a; } a = 2*j + 1; b = 2*j + 2; } } // free memory [O(1)] free(heap); return I; }