C++ 从链表中释放内存

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]); } /

我试图删除第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
        }
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)
add
std::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;
}