I have an array of structs (actually it\'s a heap array sorted by priority).
typedef struct {
char name[MAX_CHARACTERS+1];
int priority;
} person;
perso
It sounds like you are trying to implement a heap sort. You don't actually need to "remove" the first element of the heap, or even the last one.
Instead, the algorithm is to copy the values from the the first element (the element with the highest priority) for output, then to copy the node from the "end" of the array to the first position in preparation to bubble it down into the correct position. The "end" of the array is indicated by the current heap_size.
To "remove" the last item of the array, just reduce the heap_size by 1.
I vaguely recall that the bubbling down is accomplished by checking the priorities of the children on the moving item, and then swapping it with the one with the highest priority. Repeat this on the moved item until the item is of equal or higher priority to its children.
The trick to find the children of an item is easy: they are the nodes at 2*i and 2*i+1, where the array starts at 1 instead of 0. (Would it be 2*(i+1)-1 and 2*(1+1) for 0-based arrays? Check my math, please. Or just waste one element of the array to keep the math simple.)
An array is a continuous block of memory. So if you want to remove the first element, you have to move all the following elements towards the beginning by one element:
void remove(void)
{
memmove(&p[0], &p[1], (MAX_HEAPSIZE - 1) * sizeof(person));
}
This is pretty inefficient. Popping the first element is a common operation with a heap, so you'd usually do it the other way around - remove the last element of an array - which is very fast, because the other elements of the array aren't affected.
void remove(void)
{
heapsize--;
}
heapsize
can then be used as the index of the top element of the heap (assuming you preserve the heap property, of course).
If you want to overwrite the first element of the array with the last one and zero out the memory of the last element, which is not used anymore, you can use memcpy and memset:
void remove(void)
{
memcpy(&p[0], &p[heapsize - 1], sizeof(person));
memset(&p[heapsize - 1], 0x00, sizeof(person));
}
Zeroing out the memory of the last element is not strictly necessary, though, because you shouldn't be accessing it in the first place. Instead of overwriting the first element with the last using memcpy, it can also be done with strcpy
and assignment of the priority (like in your remove
); using memcpy is simply easier.