以下代码在堆中线性搜索元素x后,将其从堆中删除
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#define MaxSize 100001
struct minheap {
long int a[MaxSize];
int end;
};
void minHeapify(struct minheap *h, int i) {
int largest;
long int temp;
int l=2*i+1;
int r=2*i+2;
largest=i;
if(l<=(h->end) && (h->a[l])<(h->a[i]))
largest=l;
if(r<=(h->end) && (h->a[r])<(h->a[largest]))
largest=r;
if(largest!=i) {
temp=h->a[i];
h->a[i]=h->a[largest];
h->a[largest]=temp;
minHeapify(h,largest);
}
}
int main() {
long int x,i=0,temp=0;
int N;
int type;
scanf("%d",&N);
struct minheap h;
h.end=-1;
while(N--) {
scanf("%d",&type);
if(type==1) {
scanf("%ld",&x);
h.end=h.end+1;
h.a[h.end]=x;
i=h.end;
while(i>0 && h.a[(i-1)/2]>h.a[i]) { //fix minheap on insertion
temp = h.a[(i-1)/2];
h.a[(i-1)/2]=h.a[i];
h.a[i]=temp;
i=(i-1)/2;
}
}
else if(type==2) {
scanf("%ld",&x);
for(i=0;i<=h.end;i++) {
if(x == h.a[i])
break;
}
h.a[i]=h.a[h.end];
h.end=h.end-1;
if(i!=(h.end+1))
minHeapify(&h,i);
}
else if(type==3) {
printf("%ld\n",h.a[0]);
}
}
return 0;
}
但是以下测试用例却给出了分段错误:
Program terminated with signal SIGSEGV, Segmentation fault.
#0 main () at solution.c:59
59 if(x == h.a[i])
#0 main () at solution.c:59
可以在此链接上找到整个测试用例:
为什么会发生分段错误?
答案 0 :(得分:0)
给出错误消息,
Option Explicit
Sub SetDateTime()
Dim lngRow As Long
For lngRow = 1 To 10
Cells(lngRow, 20).Value = Now
Next lngRow
End Sub
Sub ReformatDate()
Dim lngRow As Long
Dim datX As Date
Dim strX As String
For lngRow = 1 To 10
strX = Cells(lngRow, 20).Value
If IsDate(strX) Then
datX = CDate(strX)
Cells(lngRow, 20).NumberFormat = "@"
Cells(lngRow, 20).Value = Format(datX, "mm/dd/yy")
End If
Next lngRow
End Sub
...表达式> Program terminated with signal SIGSEGV, Segmentation fault.
> #0 main () at solution.c:59 59 if(x == h.a[i])
> #0 main () at solution.c:59
中的值i
可能超出范围。这会导致 undefined behavior ,在某些情况下似乎可行,而其他情况可能会导致分段错误。
查看此行可能的解决方案:
if(x == h.a[i])
调用该表达式时for(i=0;i<=h.a[h.end];i++)
的值是什么?
这里也存在潜在的问题:
a.end
表达式:while(i>0 && h.a[(i-1)/2]>h.a[i])
是整数除法,将跳过值。
答案 1 :(得分:0)
我在您的代码中看到一些删除项目的问题:
for(i=0;i<=h.end;i++) {
if(x == h.a[i])
break;
}
h.a[i]=h.a[h.end];
h.end=h.end-1;
if(i!=(h.end+1))
minHeapify(&h,i);
首先,如果找不到具有您输入的值的项目,则将因为i > h.end
而遇到麻烦。您最终要么从数组末尾索引,要么删除最后一项。
更重要的是,您不会处理替换项小于父项的情况。例如,考虑以下堆:
1
6 2
7 8 3
如果您删除具有值7的节点,则值3将替换它:
1
6 2
3 8
那不是有效的堆。您必须将3在堆中向上移动才能创建:
1
3 2
6 8
这里的关键是,如果要替换的项目与堆中的最后一个项目不在同一子树中,则替换节点的大小可能小于替换节点的父节点。
因此您的代码必须这样做:
h.a[i] = h.a[h.end];
h.end = h.end-1;
// here you have to:
// if (h.a[i] < parentOf(h.a[i]))
// move it up the heap
// else
// minHeapify(&h, i);