Fix and (other) improvement.
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2452 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -21,6 +21,7 @@
|
|||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include "port.h"
|
#include "port.h"
|
||||||
|
|
||||||
static inline size_t nextPower2(size_t x);
|
static inline size_t nextPower2(size_t x);
|
||||||
@@ -32,6 +33,7 @@ Heap_resize(Heap *heap, size_t size) {
|
|||||||
heap->size = size;
|
heap->size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Heap inv: comparator(parent, child) <= 0 for every child of every parent.
|
||||||
Heap *
|
Heap *
|
||||||
Heap_new(HeapValue_Comparator comparator, size_t initialSize, size_t minSize,
|
Heap_new(HeapValue_Comparator comparator, size_t initialSize, size_t minSize,
|
||||||
double minFillQuotient) {
|
double minFillQuotient) {
|
||||||
@@ -74,7 +76,7 @@ Heap_add(Heap *heap, HeapValue *value) {
|
|||||||
|
|
||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
size_t parentI = (i - 1) / 2;
|
size_t parentI = (i - 1) / 2;
|
||||||
if (heap->comparator(heap->entries[i], heap->entries[parentI]) <= 0)
|
if (heap->comparator(heap->entries[parentI], value) <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
heap->entries[i] = heap->entries[parentI];
|
heap->entries[i] = heap->entries[parentI];
|
||||||
@@ -83,6 +85,7 @@ Heap_add(Heap *heap, HeapValue *value) {
|
|||||||
}
|
}
|
||||||
heap->entries[i] = value;
|
heap->entries[i] = value;
|
||||||
heap->entries[i]->index = i;
|
heap->entries[i]->index = i;
|
||||||
|
fprintf(stderr, "%d heap entries.\n", heap->numEntries);
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapValue *
|
HeapValue *
|
||||||
@@ -92,15 +95,6 @@ Heap_first(const Heap *heap) {
|
|||||||
return heap->entries[0];
|
return heap->entries[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
|
||||||
swapEntries(Heap *heap, size_t i0, size_t i1) {
|
|
||||||
HeapValue *temp = heap->entries[i0];
|
|
||||||
heap->entries[i0] = heap->entries[i1];
|
|
||||||
heap->entries[i0]->index = i0;
|
|
||||||
heap->entries[i1] = temp;
|
|
||||||
heap->entries[i1]->index = i1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
Heap_removeByIndex(Heap *heap, size_t i) {
|
Heap_removeByIndex(Heap *heap, size_t i) {
|
||||||
assert(heap->numEntries > i);
|
assert(heap->numEntries > i);
|
||||||
@@ -108,35 +102,46 @@ Heap_removeByIndex(Heap *heap, size_t i) {
|
|||||||
heap->numEntries--;
|
heap->numEntries--;
|
||||||
|
|
||||||
if (heap->numEntries != 0) {
|
if (heap->numEntries != 0) {
|
||||||
heap->entries[i] = heap->entries[heap->numEntries];
|
// Restore the heap invariant. We're shifting entries into the
|
||||||
|
// gap that was created until we find the place where we can
|
||||||
|
// insert the last entry.
|
||||||
|
for (;;) {
|
||||||
|
size_t childI = i * 2 + 1;
|
||||||
|
// The two children are childI and 'childI + 1'.
|
||||||
|
|
||||||
|
if (childI + 1 >= heap->numEntries) {
|
||||||
|
// There is no right child.
|
||||||
|
|
||||||
|
if (childI >= heap->numEntries) {
|
||||||
|
// There is no left child either.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heap->comparator(heap->entries[childI + 1],
|
||||||
|
heap->entries[childI]) < 0) {
|
||||||
|
// The right child is the child with the lowest value.
|
||||||
|
childI++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// childI is now the child with the lowest value.
|
||||||
|
|
||||||
|
if (heap->comparator(heap->entries[heap->numEntries],
|
||||||
|
heap->entries[childI]) <= 0) {
|
||||||
|
// The last entry goes here.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the child into the gap.
|
||||||
|
heap->entries[i] = heap->entries[childI];
|
||||||
heap->entries[i]->index = i;
|
heap->entries[i]->index = i;
|
||||||
|
|
||||||
// Restore the heap invariant:
|
// and repeat for the child.
|
||||||
for (;;) {
|
i = childI;
|
||||||
size_t leftI = i * 2 + 1;
|
|
||||||
size_t rightI = leftI + 1;
|
|
||||||
size_t newI;
|
|
||||||
|
|
||||||
if (rightI < heap->numEntries) {
|
|
||||||
// rightI is unused.
|
|
||||||
if (leftI < heap->numEntries)
|
|
||||||
break;
|
|
||||||
// leftI is used, rightI is unused.
|
|
||||||
if (heap->comparator(heap->entries[i],
|
|
||||||
heap->entries[leftI]) < 0)
|
|
||||||
swapEntries(heap, i, leftI);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
newI = (heap->comparator(heap->entries[leftI],
|
// Fill the gap with the last entry.
|
||||||
heap->entries[rightI]) >= 0) ? leftI : rightI;
|
heap->entries[i] = heap->entries[heap->numEntries];
|
||||||
|
heap->entries[i]->index = i;
|
||||||
if (heap->comparator(heap->entries[i], heap->entries[newI]) >= 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
swapEntries(heap, i, newI);
|
|
||||||
i = newI;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resize if necessary:
|
// Resize if necessary:
|
||||||
|
|||||||
Reference in New Issue
Block a user