我有一个结构数组(实际上它是按优先级排序的堆数组)。
typedef struct {
char name[MAX_CHARACTERS+1];
int priority;
} person;
person p[MAX_HEAPSIZE+1];
并希望删除数组中的第一个元素。我不确定如何使用或使用什么命令。
到目前为止,我一直在做
void remove(){
swap(0, heapsize-1);
strcpy(p[heapsize-1].name, p[MAX_HEAP_SIZE+1].name);
p[heapsize-1].priority = p[MAX_HEAP_SIZE+1].priority;
}
这会交换数组中的第一个和最后一个非空元素。然后它尝试将空元素的数据复制到数组中的最后一个非空元素(我想要删除的元素)。
但我认为它只会复制记忆位置。我能做些什么事情很简单
p [0] = NULL?
答案 0 :(得分:3)
数组是连续的内存块。因此,如果要删除第一个元素,则必须将所有以下元素向前移动一个元素:
void remove(void)
{
memmove(&p[0], &p[1], (MAX_HEAPSIZE - 1) * sizeof(person));
}
效率很低。弹出第一个元素是一个带堆的常见操作,所以你通常会反过来做 - 删除数组的最后一个元素 - 这非常快,因为数组的其他元素不受影响。 / p>
void remove(void)
{
heapsize--;
}
然后可以将 heapsize
用作堆的顶部元素的索引(假设您保留堆属性)。
如果你想用最后一个元素覆盖数组的第一个元素并将最后一个元素的内存归零(不再使用它),你可以使用memcpy和memset:
void remove(void)
{
memcpy(&p[0], &p[heapsize - 1], sizeof(person));
memset(&p[heapsize - 1], 0x00, sizeof(person));
}
将最后一个元素的内存清零并不是绝对必要的,因为你不应该首先访问它。而不是使用最后一个使用memcpy覆盖第一个元素,也可以使用strcpy
并分配优先级(如remove
);使用memcpy简单易行。
答案 1 :(得分:0)
听起来你正在尝试实现堆排序。您实际上不需要“删除”堆的第一个元素,甚至是最后一个元素。
相反,算法是复制第一个元素(具有最高优先级的元素)的值用于输出,然后将节点从数组的“结束”复制到第一个位置以准备冒泡它落到正确的位置。数组的“结束”由当前的heap_size指示。
要“删除”数组的最后一项,只需将heap_size减少1。
我含糊地回忆起,通过检查移动物品上的孩子的优先级,然后将其与具有最高优先级的孩子交换来完成冒泡。在移动的项目上重复此操作,直到该项目与其子项目具有相同或更高的优先级。
找到项目子项的技巧很简单:它们是2 * i和2 * i + 1的节点,其中数组从1开始而不是0.(它是2 *(i + 1) )-1和2 *(1 + 1)用于基于0的数组?请检查我的数学。或者只是浪费数组的一个元素以保持数学简单。)