【问题标题】:Min-heap insertion function最小堆插入函数
【发布时间】:2020-09-04 13:46:44
【问题描述】:

这是一个最小堆的插入函数。我不明白为什么它不起作用。

void insertHeapMin(Heap* h, int x){
if(isFull(h)){
    printf("heap is full\n");
    return;
}
for(i=0; i<h->size;i++) //I don't wan't to insert one number more than once; 
{
    if(x==h->data[i]) return;
}
int pos = h->size;
h->data[pos]=x;
while(pos>0){
    int parentPos = (pos-1)/2; 
    if (h->data[pos] < h->data[parentPos]){
        int temp = h->data[pos];
        h->data[pos] = h->data[parentPos];
        h->data[parentPos] = temp;
        pos = parentPos;
    } else
        break;
}
h->size++;
}

主要:

int a[] ={4,3,6,4,5};
size_t n = sizeof(a)/sizeof(a[0]);
Heap h;
initHeap(&h,100);
int i;
for(i=0;i<n;i++){
    insertHeapMin(&h, a[i]);
}
for(i=0;i<n;i++){
    printf("%d ",h.data[i]);
}
printf("\n");

它返回 3 4 6 5 1666986547。我真的看不出错误在哪里,当我修改 max-heap 的插入函数时它工作得很好,当没有重复元素时,仍然不知道如何修复重复元素的 for 循环。

【问题讨论】:

  • 您不会两次插入一个元素,因此您的堆中的元素可能少于n。当你打印出堆时,使用h.size 作为限制。
  • 看起来 1666986547 是一个未初始化的 int。你检查过n吗?可能n 太大而您不小心访问了a[5]
  • (顺便说一下,重复的线性搜索会降低堆性能。从堆中弹出元素时处理重复可能会更好。)
  • 堆未完全排序。它仅具有每个父级不大于其子​​级的条件。 (排序是通过将项目从堆中弹出并重新堆来​​实现的。)
  • 如果要保持排序,可以从最初的迭代搜索中找到插入点进行重复。

标签: c heap


【解决方案1】:

首先,垃圾值 1666986547 是从哪里来的?此数组元素未初始化,因为您有重复的元素,您在插入之前将其过滤掉。您的原始数组长度为 5,堆数组的长度仅为 4。打印时使用堆大小 h.size 作为限制。

二、为什么堆数组没有排序?堆数组只是部分排序的:它们满足任何节点的父节点不得大于其任何子节点的条件。你的平面阵列

3 4 6 5

看起来像这样的堆:

    3
  4   6
5

满足堆不变量,但未确定每行元素的顺序。如果要对数组进行排序,请弹出顶部元素,直到堆为空。删除 to 元素后,用较小的孩子反复填充间隙,直到碰到叶子。在你的堆中,它看起来像这样:

    3           4           5           6
  4   6       5   6       6*   
5

在第 3 步中,移动了六个 (*),因为在平面阵列中不能有间隙。

我评论说,在插入之前对重复项进行线性搜索会降低堆的性能。每次从顶部删除和每次插入都将访问 log(n) 个元素 - log(n) 是您的 n 个元素堆的深度。通过首先进行线性搜索,您可以得到 n log(n)。

相反,插入所有元素(如果有很多重复元素,则会增加空间)。移除顶部元素后,重新堆化堆,直到新的顶部元素不同。在大多数情况下,这应该会给您带来更好的性能。

【讨论】:

  • 另一种防止重复的方法是维护一个哈希表或类似的数据结构来跟踪堆中的哪些项目。这是更多的内存,但不会降低性能。
猜你喜欢
  • 2023-04-10
  • 1970-01-01
  • 2013-03-29
  • 1970-01-01
  • 2021-10-31
  • 1970-01-01
  • 2022-01-22
  • 2021-06-08
  • 1970-01-01
相关资源
最近更新 更多