我正在尝试实现van emde boas树,但是当我多次调用我的插入函数时,却遇到了Segmentation Fault 11。当我尝试在insert函数中打印值时,我意识到问题出在将群集初始化为NULL时。我不明白为什么在使用for循环时会出现这种情况。我也尝试使用calloc,但它给了我同样的错误。我的代码如下:
class vEB
{
int u;
int *m;
int *M;
vEB *summary;
vEB **cluster;
public:
vEB(int);
bool member(int);
void insert(int);
void Delete(int);
int min();
int max();
int* pred(int);
int* succ(int);
};
vEB::vEB(int u){
this -> u = u;
this -> m = NULL;
this -> M = NULL;
if (u == 2){
this -> summary = NULL;
this -> cluster = NULL;
} else {
int subSize = (int)sqrt(u);
this -> summary = new vEB(subSize);
this -> cluster = new vEB*[subSize];
for (int i=0;i<=subSize;i++){
cluster[i]=NULL;
}
}
}
bool vEB::member(int x){
if (u == 2){
if (m == NULL){
return false;
}
if (x == 0){
return ((*m) == 0);
} else if (x == 1){
return ((*M) == 1);
}
return false;
}else{
if (m == NULL) {
return false;
}
if (x < (*m) || x > (*M)){
return false;
}else if (x == (*m) || (x == (*M))){
return true;
}else{
int subSize = (int)sqrt(u);
int hi = x / subSize;
int lo = x % subSize;
if (cluster[hi] == NULL){
return false;
} else{
return cluster[hi] -> member(lo);
}
}
}
}
void vEB::insert(int x) {
if (u == 2) {
if (x == 0) {
if (m == NULL){
m = new int;
M = new int;
(*m) = (*M) = x;
} else {
(*m) = x;
}
} else if (x == 1) {
if (M == NULL){
m = new int;
M = new int;
(*m) = (*M) = x;
} else{
(*M) = x;
}
}
} else {
if (m == NULL) {
m = new int;
M = new int;
(*m) = (*M) = x;
} else {
if (x < (*m)) {
int currMin = (*m);
(*m) = x;
this -> insert(currMin);
}else {
int subSize = (int)sqrt(u);
int hi = x / subSize;
printf("%d - %d\n",x, hi);
int lo = x % subSize;
printf("%d - %d\n",x, hi);
if (cluster[hi] == NULL){
cluster[hi] = new vEB(subSize);
cluster[hi] -> insert(lo);
summary -> insert(hi);
}else {
cluster[hi] -> insert(lo);
}
if (x > (*M)){
(*M) = x;
}
}
}
}
}
void vEB::Delete(int x){
if (u == 2) {
if (x == 0) {
if ((*M) == 0){
m = M = NULL;
} else{
(*m) = 1;
}
} else if (x == 1) {
if ((*m) == 1) {
m = M = NULL;
}
else {
(*M) = 0;
}
}
}else{
int subSize = (int)sqrt(u);
int hi = x / subSize;
int lo = x % subSize;
if (x == (*m)){
if (x == (*M)){
m = M = NULL;
} else {
int nextMinHi = summary -> min();
int nextMinLo = cluster[summary -> min()] -> min();
int nextMin = nextMinHi * subSize + nextMinLo;
this -> Delete(nextMin);
(*m) = nextMin;
}
} else {
cluster[hi] -> Delete(lo);
if (cluster[hi] -> m == NULL){
summary -> Delete(hi);
delete cluster[hi];
cluster[hi] = NULL;
}
if (x == (*M)){
if (summary -> m == NULL) {
(*M) = (*m);
} else{
int nextMaxHi = summary -> max();
int nextMaxLo = cluster[summary -> max()] -> max();
(*M) = nextMaxHi * subSize + nextMaxLo;
}
}
}
}
}
int vEB::min() {
return (*m);
}
int vEB::max() {
return (*M);
}
int* vEB::pred(int x){
if (u == 2){
if (x == 0) {
return NULL;
} else if (x == 1){
if (m == NULL){
return NULL;
}
if ((*m) == 1){
return NULL;
}
return m;
}
else {
return NULL;
}
} else {
if (m == NULL) {
return NULL;
}
if (x <= (*m)) {
return NULL;
}
if (x > (*M)) {
return M;
}
int subSize = (int)sqrt(u);
int hi = x / subSize;
int lo = x % subSize;
if (cluster[hi] == NULL){
int* prev = summary -> pred(hi);
int* ret = new int;
(*ret) = (*prev) * subSize + cluster[(*prev)] -> max();
return ret;
} else {
int *newLo, *newHi;
newHi = new int;
newLo = new int;
(*newHi) = hi;
int minInCluster = cluster[hi] -> min();
if (lo > minInCluster){
newLo = cluster[hi] -> pred(lo);
}else {
newHi = summary -> pred(hi);
(*newLo) = cluster[(*newHi)] -> max();
}
int *ret = new int;
(*ret) = (*newHi) * subSize + (*newLo);
return ret;
}
}
}
int* vEB::succ(int x) {
if (u == 2) {
if (x == 1) {
return NULL;
}else if (x == 0) {
if (M == NULL) {
return NULL;
}
if ((*M) == 0) {
return NULL;
}
return M;
}else {
return NULL;
}
}else{
if (m == NULL) {
return NULL;
}
if (x >= (*M)) {
return NULL;
}
if (x < (*m)) {
return m;
}
int subSize = (int)sqrt(u);
int hi = x / subSize;
int lo = x % subSize;
if (cluster[hi] == NULL) {
int* next = summary -> succ(hi);
int* ret = new int;
(*ret) = (*next) * subSize + cluster[(*next)] -> min();
return ret;
} else {
int *newLo, *newHi;
newHi = new int;
newLo = new int;
(*newHi) = hi;
int maxInCluster = cluster[hi] -> max();
if (lo < maxInCluster){
newLo = cluster[hi] -> succ(lo);
}else {
newHi = summary -> succ(hi);
(*newLo) = cluster[(*newHi)] -> min();
}
int *ret = new int;
(*ret) = (*newHi) * subSize + (*newLo);
return ret;
}
}
}
int main(){
vEB *vEB = new class vEB(8);
vEB -> insert(1);
vEB -> insert(2);
vEB -> insert(5);
vEB -> insert(6);
vEB -> insert(7);
printf("%d\n", (*vEB -> pred(2)));
printf("%d\n", (*vEB -> succ(2)));
vEB -> Delete(2);
return 0;
}
是否存在正确的方法来初始化我不知道的指针?任何建议将不胜感激。谢谢。
答案 0 :(得分:0)
在 import collections
wordcount = collections.Counter()
with open('./tekst1.txt') as infile, open('tekst2.txt', 'w') as outfile:
for line in infile:
wordcount.update(line.split())
for k,v in wordcount.iteritems():
outfile.write(line)
vEB::vEB(int u)
必须
for (int i=0;i<=subSize;i++){ cluster[i]=NULL; }
因为for (int i=0;i<subSize;i++){
cluster[i]=NULL;
}
而不是this -> cluster = new vEB*[subSize];
当我多次调用我的插入函数时,我遇到了Segmentation Fault 11。
当您执行this -> cluster = new vEB*[subSize+1];
时, hi 的值太高,并且vEB -> insert(5);
不在集群中。
答案 1 :(得分:0)
虽然“一次性关闭”错误很严重,但您有一个更严重的错误:可能无限递归。
在您的VEC
构造函数中,您要检查u == 2
,但是如果u
是例如3
?然后进入else
的情况,得到3
的平方根,该平方根将被截断为整数1
。然后,执行new VEC(1)
,它会使用值1
(不等于2
)来调用构造函数,进入else
分支并获得{{ 1}}等于1
。然后,您会1
(再次!)等等,直到永远。
您需要检查是否new VEC(1)
以避免发生这种情况。
答案 2 :(得分:0)
这不能解决您的问题,但希望对您有所帮助。 经过一些调试,我发现您的问题出在调用insert(5)时。 产生段错误的代码是:
if (cluster[hi] == NULL) {
cluster[hi] = new vEB(subSize);
cluster[hi]->insert(lo);
summary->insert(hi);
}
else {
cluster[hi]->insert(lo); //here something is wrong with cluster[hi]
}
我无法找到答案,但是如果将代码放在IDE中并对其进行调试,则您有更好的机会解决此问题,因为您比我更了解代码。
答案 3 :(得分:0)
我的发现与布鲁诺的发现相同。这是live test of your code。您可以修复它并再次测试。
===========#0扩展运行时消息的开头===========
运行时错误: [越界写入]
继续执行会导致不确定的行为,中止!
-
- Writing 4 bytes to 0x8aaa078 will corrupt the adjacent data.
-
- The memory-space-to-be-written (start:0x8aaa070, size:8 bytes) is allocated at
- file:/src/new.cpp::54, 17
-
- 0x8aaa070 0x8aaa077
- +------------------------------+
- |the memory-space-to-be-written|......
- +------------------------------+
- ^~~~~~~~~~
- the write starts at 0x8aaa078 that is right after the memory end.
-
- Stack trace (most recent call first) of the write.
- [1] file:/prog.cc::35, 13
- [2] file:/prog.cc::290, 10
- [3] [libc-start-main]
-
============#0扩展运行时消息结束============