带插入的链接列表问题

时间:2010-05-10 16:14:41

标签: c++ linked-list

我写的插入函数出现了问题。

3条件必须有效,我测试了b / w 1和2,b / w 2和3,作为最后一个元素,它们有效。


修改; 这是我自己的问题。我没有意识到我把MAXINPUT = 3(而不是4)。我非常感谢所有努力帮助我成为更好的程序员,使用更先进和更简洁的C ++功能。

基本上,问题已经解决了。


效率不是我关注的(尚未)。请指导我完成这个调试过程。

非常感谢。

#include<iostream>
#include<string>
   using namespace std;

    struct List    // we create a structure called List
   {
      string name;  
      string tele;
      List *nextAddr;
   };

   void populate(List *);
   void display(List *);
   void insert(List *);

    int main()
   {
      const int MAXINPUT = 3;
      char ans;  

      List * data, * current, * point;  // create two pointers
      data = new List;
      current = data;

      for (int i = 0; i < (MAXINPUT - 1); i++)
      {
         populate(current);
         current->nextAddr = new List;
         current = current->nextAddr;
      }

   // last record we want to do it sepeartely

      populate(current);
      current->nextAddr = NULL;
      cout << "The current list consists of the following data records: " << endl;
      display(data);

   // now ask whether user wants to insert new record or not

      cout << "Do you want to add a new record (Y/N)?";

      cin  >> ans;

      if (ans == 'Y' || ans == 'y')
      {
     /* 

   To insert b/w first and second, use point as parameter
   between second and third uses point->nextAddr
   between third and fourth uses point->nextAddr->nextAddr
   and insert as last element, uses current instead 

   */       
   point = data;
   insert(());  
         display(data);
      }

      return 0;  
   }


    void populate(List *data)
   {
      cout << "Enter a name: ";
      cin >> data->name;
      cout << "Enter a phone number: ";
      cin >> data->tele;

      return;
   }

    void display(List *content)
   {
      while (content != NULL)
      {
         cout << content->name << "     " << content->tele;
         content = content->nextAddr;
         cout << endl; // we skip to next line
      }

      return;
   }

    void insert(List *last)
   {
      List * temp = last->nextAddr; //save the next address to temp
  last->nextAddr = new List; // now modify the address pointed to new allocation
      last = last->nextAddr; 
      populate(last);
      last->nextAddr = temp; // now link all three together, eg 1-NEW-2

      return;
   }

4 个答案:

答案 0 :(得分:2)

您的代码在我的机器上运行正常(一旦insert(())语句被“填写”正确,如代码注释中所述。插入适用于所有位置。


其他东西,但是:我最初看了你的insert函数。我想我会给你一个关于如何缩短它并且更容易理解正在发生的事情的提示:

void insert(List *last)
{
    // create a new item and populate it:
    List* new_item = new List;
    populate(new_item);

    // insert it between 'last' and the item succeeding 'last':
    new_item->nextAddr = last->nextAddr;
    last->nextAddr = new_item;
}

这是首选,因为它首先创建一个新的单独项目,准备插入,只有这样,当成功运行时,该功能将“混乱”链接列表。也就是说,链接列表不受影响,除非在最后一个语句中,使您的函数“更安全”。将此与您的insert版本进行对比,您可以将用于构建新项目的代码与实际插入混合在一起。如果在这个函数中出现问题,那么链接列表也可能被搞砸了。

(什么仍然缺少btw。是初始检查传递的参数last是否实际有效,即不是空指针。)


PS:当然您可以使用标准的C ++ std::list容器,而不是构建自己的链接列表,但是看到您标记了问题beginner,我认为你想知道它是如何运作的。

答案 1 :(得分:1)

第一步应该是将列表放入一个对象,而不是仅仅在main()中保留一堆指针。你想要一个名为List的对象,它知道它自己的第一个(也许是最后一个)元素。它还应该包含List.append()List.insert()等方法。

您当前的代码几乎无法读取。

答案 2 :(得分:1)

使用std :: list,除非这是作业,在这种情况下需要标记。

答案 3 :(得分:1)

根据我的经验,我学会了从小开始测试,然后积累。我将指导您完成这些步骤。

BTW,链表是节点的容器。所以我们首先从节点类开始。

最低限度,节点必须有指向另一个节点的指针:

#include <iostream>
#include <cstdlib> // for EXIT_SUCCESS
#include <string>

using std::cout;
using std::endl;
using std::cerr;
using std::cin;
using std::string;

struct Node
{
  // Add a default constructor to set pointer to null.
  Node()
  : p_next(NULL)
  { ; }

  Node * p_next;
};

// And the testing framework
int main(void)
{
  Node *  p_list_start(NULL);

  // Allocate first node.
  p_list_start = new Node;

  // Test the allocation.
  // ALWAYS test dynamic allocation for success.
  if (!p_list_start)
  {
    cerr << "Error allocating memory for first node." << endl;
    return EXIT_FAILURE;
  }

  // Validate the constructor
  ASSERT(p_list_start->p_next == 0);

  // Announce to user that test is successful.
  cout << "Test successful." << endl;

  // Delete the allocated object.
  delete p_list_start;

  // Pause if necessary.
  cin.ignore(100000, '\n'); // Ignore input chars until limit of 100,000 or '\n'

  return EXIT_SUCCESS;
}

编译,然后运行这个简单的测试。修复错误,直到它正确运行。

接下来,修改测试仪以链接两个节点:

int main(void) {   Node * p_list_start(NULL);   Node * p_node(NULL); //&lt; - 这是第二个节点的新语句。   //...

  // Validate the constructor
  ASSERT(p_list_start->p_next == 0);

  // Allocate a second node.
  p_node = new Node;
  if (!p_node)
  {
      cerr << "Error allocating memory for 2nd node." << endl;

      // Remember to delete the previously allocated objects here.
      delete p_list start;

      return EXIT_FAILURE;
  }

  // Link the first node to the second.
  p_list_start->Link_To(p_node);

  // Test the link
  ASSERT(p_list_start.p_next == &p_node);

  //...

  // Delete the allocated object(s)
  delete p_list_start;
  delete p_node;

  //...

}

编译修改。
无法编译,未定义的方法:Node :: Link_To
不用担心,这是预料之中的。告诉我们编译器正在工作。 :-)

Link_To方法添加到Node结构:

struct Node
{
  // ...
  void Link_To(const Node& n)
  {
     p_next = &n;
     return;
  }
  //...
};

编译并运行。测试应该通过。

此时,链接过程已经过验证。在向节点添加内容。

由于Node对象已经过测试,我们不想触摸它。所以让我们继承它来创建一个包含内容的节点:

struct Name_Node
: public Node  // Inherit from the tested object.
{      
    std::string  name;
    std::string  phone;
};

如果您尚未学习继承,则可以附加到现有节点:

struct Node
{
  //...
  std::string  name;
  std::string  phone;
}

此时,您可以添加设置和显示内容的功能。添加测试语句。运行并验证。

下一步是创建两个内容节点并将它们链接在一起。在构建时,请保留测试代码。此外,如果东西工作,您可能希望将功能放入单独的功能。

有关此流程的详细信息,请查看Test Driven Development