排序链表在每次执行时插入重复项

时间:2015-03-26 16:46:53

标签: c++ linked-list

我有一个从文件中读取数据的函数,然后根据每行数据中的特定字段按递增顺序插入。

如果我编译并运行这部分代码,它最初排序,但是一旦我重复动作,我得到一个排序的副本,如果我再跑一次,每个项目出现3次。

如何让此代码停止插入重复项?

void sortData(Node *& head, Node * data)
{
    ifstream fin("data.txt");
    int acc; string fname, lname; double bal;
    while (fin >> acc >> fname >> lname >> bal)
    {
        data = new Node;
        data->account = acc;
        data->fname = fname;
        data->lname = lname;
        data->balance = bal;
        data->next = NULL;

        if (head == NULL)
        {
            head = data;
        }

        else if (data->balance <= head->balance)
        {
            data->next = head;
            head = data;
        }

        else
        {
            Node * temp1 = head;
            Node * temp2 = temp1->next;

            while (temp2 != NULL && data->balance > temp2 ->balance)
            {
                temp1 = temp2 ;
                temp2 = temp2 ->next;
            }

            data->next = t2;
            temp1 ->next = data;
        }

    }

    Node * temp = head;
    while (temp != NULL)
    {
        cout << temp->account << " " << temp->fname << " " << temp->lname << " " << temp->balance << "\n";
        temp = temp->next;
    }

    fin.close();

}

净度。

程序运行一个简单的菜单,所以当我第一次构建和运行时,我可以做几件事,插入新记录,删除,显示所有记录(问题出在哪里),然后退出。我可以尽可能多地重复每个动作,期待退出(显然)。

初始运行,然后根据帐号显示所有记录:

1111 FName1 LName1 400.56

2222 FName2 LName2 23.45

3333 FName3 LName3 4599.91

4444 FName4 LName4 1000.5

运作良好。

但是

当我想再次显示所有记录时,我看到了这个

1111 FName1 LName1 400.56

1111 FName1 LName1 400.56

2222 FName2 LName2 23.45

2222 FName2 LName2 23.45

3333 FName3 LName3 4599.91

3333 FName3 LName3 4599.91

4444 FName4 LName4 1000.5

4444 FName4 LName4 1000.5

我没有重新插入文件,只是按递增顺序打印数据。

2 个答案:

答案 0 :(得分:1)

你在一个功能中做了太多事情。将它们分成更小,可重复使用的功能。

// Function to insert the data sorted in an order.
void insertSortedData(Node*& head,
                      int acc,
                      std::string const& fname,
                      std::string const& lname,
                      double bal)
{
   // If the list is empty, create a node and return.
   Node* newNode = new Node(acc, fname, lname, bal)
   if ( head == NULL )
   {
      head = newNode;
      return;
   }

   // If the value of the new node is less or equat to the value
   // of the head node, make it the head node and return.
   if (newNode->balance <= head->balance)
   {
      newNode->next = head;
      head = newNode;
      return;
   }

   // Insert new node at the right place.
   Node * temp1 = head;
   Node * temp2 = temp1->next;

   while (temp2 != NULL && newNode->balance > temp2->balance)
   {
      temp1 = temp2 ;
      temp2 = temp2->next;
   }

   newNode->next = temp2;
   temp1->next = newNode;
}

// Function to read data from a file and create
// a sorted list.
void readDataFromFile(std::string const& file,
                      Node*& head)
{
   std::ifstream fin(file);
   int acc;
   std::string fname;
   std::string lname;
   double bal;
   while (fin >> acc >> fname >> lname >> bal)
   {
      insertSortedData(head, acc, fname, lname, bal);
   }
}

// Functoin to print the contents of a list.
void printList(Node* head)
{
   Node* temp = head;
   while (temp != NULL)
   {
      cout << temp->account << " " << temp->fname << " " << temp->lname << " " << temp->balance << "\n";
      temp = temp->next;
   }
}

然后,你可以分别打电话给每个人:

int main()
{
   Node* head = NULL;

   // Read data from a file.
   readDataFromFile("data-1.txt", head);

   // Print the data
   printList(head);


   // Read data from a different file.
   readDataFromFile("data-2.txt", head);

   // Print again.
   printList(head);
}

答案 1 :(得分:1)

除了你的功能太多,甚至没有看到调用代码这一事实,我可以从你的输出中看出 - 如果你显示的是实际上唯一的输出 - 你多次调用sortedData 。每次调用sortedData时,sortedData都会以排序的方式插入输入文件中的所有条目,而不管它们是否已存在!因此,在n次调用之后,您的列表中将有n个数据元素副本。

想想你的功能要做什么。现在你的函数在每次调用上执行

while输入文件中有更多条目:

  1. 从输入文件中读取下一个条目。
  2. 以排序的方式将条目插入列表。
  3. 您现在拥有输入文件中所有条目的排序列表。您打印列表中的所有条目。

    返回后,您传入函数的列表头仍然指向包含您刚读过的所有条目的有效列表。

    如果您只想显示所有条目,则唯一需要重复的内容 是打印部分,但如果再次调用sortedData,您将重复整个函数,这次您传递的List不为空,但已包含输入文件中的每个条目,因此再次添加每个条目以有条件的方式为每个条目提供一个副本。因此,最简单的解决方案是在启动时调用您的函数,稍后再调用printList()函数,这只是打印部分:

    void printList(Node *head){//local copy of the pointer, can change this
        while (head != NULL)
        {
           cout << head->account << " " << head->fname << " " << 
               head->lname << " " << head->balance << "\n";
           head = head->next;
        }
    }