从链表中释放内存

时间:2014-10-16 13:08:16

标签: c++ linked-list

我试图删除第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
        }

3 个答案:

答案 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;
}

这应该可以正常工作。检查将阻止我们解除引用空指针,这可能是导致您崩溃的原因。没有完整的代码就无法分辨。