gpt4 book ai didi

c++ - 从跳过列表中删除节点

转载 作者:太空狗 更新时间:2023-10-29 22:53:10 26 4
gpt4 key购买 nike

我在从跳过列表中删除节点时遇到了一些问题。我有以下结构:

struct Node
{
int info;
Node **link_;

Node(int v, int levels)
{
info = v;
link_ = new Node*[levels];

for ( int i = 0; i < levels; ++i )
link_[i] = NULL;
}
};

struct List
{
int H; // list height

Node *Header;

List()
{
Header = new Node(0, maxH);
H = 1;
}
};

我认为问题出在搜索具有给定值的节点然后将其删除的函数中。函数实现如下:

void Remove(int v, List *L)
{
Node *current = L->Header;

for ( int i = L->H - 1; i >= 0; --i )
{
for ( ; current->link_[i] != NULL; current = current->link_[i] )
if ( current->link_[i]->info > v )
break;
else if ( current->link_[i]->info == v )
{
// Node *del = current->link_[i];
current->link_[i] = current->link_[i]->link_[i];

// delete del;
break;
}
}
}

该函数按原样运行良好,但是如果我取消注释这两个注释行,列表似乎会中断。我所说的中断是指以下测试代码永远不会完成:

int main()
{
srand((unsigned)time(0));

List *SKL = new List();


for ( int i = 0; i < 1000000; ++i )
Insert(rand() * rand(), SKL);

for ( int i = 0; i < 1000000; ++i )
Search(rand() * rand(), SKL);

for ( int i = 0; i < 1000000; ++i )
Remove(rand() * rand(), SKL);

for ( int i = 0; i < 1000000; ++i )
Insert(rand() * rand(), SKL);


return 0;
}

问题出在最后一个 for 循环中,它在列表中插入了更多的值。如果这两行被注释掉,程序将在大约 10 秒内完成。如果我取消注释它们,它似乎进入了一个无限循环,因为它甚至没有在几分钟内完成。我不确定这是否是从跳过列表中删除节点的正确方法,所以我也发布了我的插入函数:

void Insert(int v, List *L)
{
// this section just determines the levels the new node will be part of
int newH = 0;

int tmp;
unsigned int rnd = rand() * rand();
do
{
tmp = lookup[rnd & 255];
rnd >>= 8;
newH += tmp;
} while ( tmp == 8 );

if ( newH >= L->H )
++L->H;

// this does the actual insertion
Node *newNode = new Node(v, L->H);
Node *current = L->Header;
for ( int i = L->H - 1; i >= 0; --i )
{
for ( ; current->link_[i] != NULL; current = current->link_[i] )
if ( current->link_[i]->info >= v )
break;

if ( i <= newH )
{
newNode->link_[i] = current->link_[i];
current->link_[i] = newNode;
}
}
}

所以,我的问题是:

  1. 为什么程序会中断,如何在实际删除我想从内存中删除的节点的同时让它继续运行?
  2. 这是实现跳过列表的正确方法,还是我使用了错误的方法?

最佳答案

如您所料,Remove 方法存在问题:

void Remove(int v, List *L)
{
Node *current = L->Header;

for ( int i = L->H - 1; i >= 0; --i )
{
for ( ; current->link_[i] != NULL; current = current->link_[i] )
{
if ( current->link_[i]->info > v )
{
break;
}
else if ( current->link_[i]->info == v )
{
// Node *del = current->link_[i];
current->link_[i] = current->link_[i]->link_[i];

// if (0 == i) delete del;
break;
}
}
}
}

为了举例,假设我们要删除的节点出现在 2 个级别:0 和 1。

L->H 到 2 层的 for 循环不做任何事情。

在第 1 层,它将找到请求的节点并将其删除。

在第 0 级,它将尝试跟随指向已删除节点的指针,从而导致未定义的行为。

解决方法:

只在0级删除节点。只要你在上层,节点仍然被引用,你需要保持它的存活。

关于c++ - 从跳过列表中删除节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2942235/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com