我试图删除第n个元素,这是一个从1到n的随机数。
我的代码做得很好(删除了正确的元素并且连接了周围的元素)但是当它有效时,当我取消注释行delete (nodeToRemove);
并且我不确定原因时它会崩溃。有没有人有任何见解?
假设我的结构如下:
struct Node {
int data; // The data being stored at the node
Node *next; // Pointer to the next node
};
//------------------------------------------------------------------------------
void deleteNthElement (Node * & head, Node * &temp, int random)
{
temp = head;
Node *nodeToRemove;
if (random == 1)
{
nodeToRemove = temp;
head = head->next;
}
else
{
for (int i = 1; i < random - 1; i++)
temp = temp->next;
nodeToRemove = temp->next;
temp->next = temp->next->next;
}
// delete (nodeToRemove); <----- uncommenting this leads to crash,
}//end deleteNthElement()
//------------------------------------------
int main()
{
Node *head = NULL;
Node *temp;
Node *listarray[n[i]];
int n[] = {1000, 5000, 9000, 105000, 400000, 500000, 505000, 800000, 995000, 1000000};
for (int j = 0; j < n[i]; j++)
listarray[j] = new (Node);
//start timer
begin = clock();
//fill it
for (int j = 0; j < n[i]; j++)
{
listarray[j]->data = (rand() % n[i] + 1);
insertNodeInOrder (head, temp, listarray[j]);
}
//delete it
for (int j = 0; j < n[i]; j++)
deleteNthElement (head, temp, (rand() % (n[i] - j) + 1));
//deallocate
for (int j = 0; j < n[i]; j++)
delete listarray[j];
delete *listarray;
//end timer
}
答案 0 :(得分:1)
至少,你必须检查列表的结尾,也就是说,你需要避免访问空指针(我真的希望你在列表的末尾设置为0)。如果你添加分配部分,我会扩展我的答案。
void deleteNthElement (Node * & head, Node * &temp, int random)
{
temp = head;
Node *nodeToRemove;
if (random == 1)
{
nodeToRemove = temp;
if(head != 0)
head = head->next;
} else {
for (int i = 1; i < random - 1; i++)
if(temp != 0)
temp = temp->next;
else throw 1; // no such index; throw something more verbose :)
if(temp == 0)
throw 1; // same situation as above
nodeToRemove = temp->next;
if(nodeToRemove == 0)
throw 1; // same situation as above
temp->next = temp->next->next;
}
if(nodeToRemove == 0)
throw 1; //no such index; ... as the above 3
delete nodeToRemove;
}//end deleteNthElement()
答案 1 :(得分:1)
你想要选择错误的Node
:
...
nodeToRemove = temp;
...
答案 2 :(得分:0)
先清理一下:
为什么在这里输入两个指针?你需要temp out的价值吗?如果是这样,为什么不退货呢?
同样为什么node * & temp
? (我可以看出为什么head
完成了。)
int random
应该被称为类似index
的东西,因为它更好地描述了功能(就函数而言,它没有任何随机性)。
与temp
相同。
我建议:
void delete_element (Node* &head, int index)
{
Node* parent_node = head;
Node* node_to_remove;
//...
如果我们移除头部,我们不需要临时工。此外,我们通常0
索引事物,因此我们也应该反映这一点。因此它变成了:
if (index== 0)
{
node_to_remove= head;
head = head->next;
}
现在我们到达主要位置。循环就在那里逐步进入要删除的节点的父节点,因此我们可以稍微简化它并添加检查以确保我们不会“脱落”列表的末尾。
然后我们必须确保有一个要删除的节点,(所以另一个检查)。我们不需要检查超出节点,因为分配nullptr
不是问题(我假设这里有一个无效指针设置为nullptr
):
{
while(--index && parent_node->next){ //pre-decrement means we stop before the one we want (parent)
parent_node = parent_node->next;}
if (parent_node->next){node_to_remove= parent_node->next;}
else {return;} //no point deleting it if it doesnt exist
parent_node->next = node_to_remove->next;//less indirection is always good. Ok if this is nullptr
}
顺便说一下,这可能会导致一个错误。这可能是你的问题(它每次都崩溃了吗?只有在删除最后一个元素时?最后一个?
现在我们只需删除它。
全部放在一起:
void delete_element (Node* &head, int index)
{
Node* parent_node = head;
Node* node_to_remove;
if (index== 0)
{
node_to_remove= head;
head = head->next;
}
else
{
while(--index && parent_node->next){ //pre-decrement means we stop before the one we want (parent)
parent_node = parent_node->next;}
if (parent_node->next){node_to_remove= parent_node->next;}
else {return;} //no point deleting it if it doesnt exist
parent_node->next = node_to_remove->next;//less indirection is always good. Ok if this is nullptr
}
delete node_to_remove;
return;
}
这应该可以正常工作。检查将阻止我们解除引用空指针,这可能是导致您崩溃的原因。没有完整的代码就无法分辨。