C++ 从链表中释放内存
我试图删除第n个元素,它是一个从1到n的随机数。 我的代码做得很好(删除了正确的元素并连接了周围的元素),但说到效率,当我取消注释行C++ 从链表中释放内存,c++,linked-list,C++,Linked List,我试图删除第n个元素,它是一个从1到n的随机数。 我的代码做得很好(删除了正确的元素并连接了周围的元素),但说到效率,当我取消注释行delete(nodeToRemove)时,它就崩溃了下一步; } 其他的 { for(int i=1;i下一步; nodeToRemove=temp->next; 临时->下一步=临时->下一步->下一步; } //删除(nodeToRemove);数据=(rand()%n[i]+1); InsertNodeInNorder(头部、温度、列表阵列[j]); } /
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
}
struct节点{
int data;//存储在节点上的数据
Node*next;//指向下一个节点的指针
};
//------------------------------------------------------------------------------
void deleteNthElement(节点*&head、节点*&temp、int-random)
{
温度=水头;
Node*nodeToRemove;
如果(随机==1)
{
nodeToRemove=温度;
头部=头部->下一步;
}
其他的
{
for(int i=1;i下一步;
nodeToRemove=temp->next;
临时->下一步=临时->下一步->下一步;
}
//删除(nodeToRemove);数据=(rand()%n[i]+1);
InsertNodeInNorder(头部、温度、列表阵列[j]);
}
//删除它
对于(int j=0;j
至少,您必须检查列表的末尾,也就是说,您需要避免访问空指针(我真的希望您在列表末尾设置为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()
void deleteNthElement(节点*&head,节点*&temp,int-random)
{
温度=水头;
Node*nodeToRemove;
如果(随机==1)
{
nodeToRemove=温度;
如果(头!=0)
头部=头部->下一步;
}否则{
for(int i=1;i下一步;
else抛出1;//没有这样的索引;抛出更详细的内容:)
如果(温度==0)
抛出1;//与上述情况相同
nodeToRemove=temp->next;
if(nodeToRemove==0)
抛出1;//与上述情况相同
临时->下一步=临时->下一步->下一步;
}
if(nodeToRemove==0)
抛出1;//没有上述3的索引
删除nodeToRemove;
}//end deleteNthElement()
您选择了错误的节点
,您需要:
...
nodeToRemove = temp;
...
首先进行一些清理:
为什么在这里传递两个指针?您需要临时输出的值吗?如果是,为什么不退回呢?
还有为什么要使用节点*&temp
?(我可以理解为什么对头)执行此操作。
int random
可能应该被称为index
,因为它更好地描述了功能(就函数而言,它没有任何随机性)。
与temp
相同
我提议:
void delete_element (Node* &head, int index)
{
Node* parent_node = head;
Node* node_to_remove;
//...
如果我们正在移除头部,则不需要temp。此外,我们通常0
索引事物,因此我们也应该反映这一点。因此,它变成:
if (index== 0)
{
node_to_remove= head;
head = head->next;
}
现在我们进入主要部分。循环只是为了逐步到达要删除的节点的父节点,因此我们可以稍微简化它并添加检查,以确保我们不会从列表末尾“掉下来”。
然后,我们必须确保有一个节点要删除(因此需要再次检查)。由于分配nullptr
不是问题,因此我们不需要检查节点以外的节点(我假设此处将无效指针设置为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;
}
这应该可以很好地工作。这些检查将防止我们取消对空指针的引用,这可能是是什么导致你崩溃的?没有完整的代码就不能判断。< /P>你有没有显示过?你没有显示任何代码<新的< /代码>或<代码>删除<代码>代码,所以我们在这里不太了解。但是这看起来比C++更像C代码。显示更多的代码……你是如何创建/插入列表的。检查节点是如何分配的,注意每个删除都可以做一些内存。如果是通过newInitialize将指针分配给NULL值,那么在delete(nodeToRemove)
addstd::assert(nodeToRemove!=NULL)之前
,调试器应该允许您单步进入代码以查看程序状态及其错误。-刚刚添加的分配部分还不够完整,无法看到足够的信息。此外,它看起来有点凌乱,很难弄清楚发生了什么。您至少应该为InsertNodeInoder添加代码。
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;
}