在c++中找到所有匹配的链表节点

Find all matching nodes in linked list c++

本文关键字:链表 节点 c++      更新时间:2023-10-16

我正在编写一个函数来查找链表中节点的所有出现次数,该函数将返回出现次数到主函数,然后主函数将显示这些出现次数。程序确实编译,但它只是冻结,当我输入要查找的正确名称时似乎没有发生任何事情,如果我输入错误的名称,不在列表中,findall函数返回0,程序的其余部分工作正常。请看一看。

main.cpp

#include <iostream>
#include <fstream>
#include <string>
using namespace std;
#include "List.h"
void extra(list &);
/***********************************
 * Main
 * Test function - DO NOT CHANGE
 ***********************************/ 
void main()
{
  list a;
  extra(a);
}
/***********************************
 * Extra Credit
 * Test function - DO NOT CHANGE
 ***********************************/ 
void extra(list &a)
{ int i,n;
  node_ptr map[4];
  string first,last;
// Find node
  cout << endl;
  cout << "Enter First and Last name: ";
  cin >> first >> last;
  n = a.findall(first,last,map,4);
 // Display forwards
  cout << endl;
  cout << "Find Listn--------------n";
  for (i = 0; i < n; i++)
  {
      map[i]->put(cout);
  }
}

List.h

#include "Node.h"
#include <iostream>
#include <string>
using namespace std;
class list 
{  public:
        list();                                             // Empty constructor
        ~list();                                            // Destructor
        int findall(string, string, node_ptr*, int);
        node *find(string, string);                         // Locate a note

    private:
        node *head;
};

Node.h

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

class list;
class node
{ friend list;
  public:
    node();                           // Null constructor
    ~node();                          // Destructor 
    void put(ostream &out);           // Put
  private:
    string first,last;
    int age;
    node *next;
};
typedef node * node_ptr;

List.cpp

#include "List.h"
#include <iostream>
#include <string>
using namespace std;
/**
* Empty Constructor
*
*/
list::list()
{
    head = nullptr;
}
/**
* Destructor Constructor
*
*/
list::~list()
{  if (head == nullptr) return;
    node *p = head, *t;
    while (p) 
    {
        t = p;
        p = p->next;
        delete t;
    }
    head = nullptr;
}
/**
* Locate node
*
*/
node *list::find(string last, string first) 
{
    node *temp = head;
    while (temp)
    {
        if (temp->first == first && temp->last == last) return temp;
        temp = temp->next;
    }
    return nullptr;
}

/**
* Find all.
*
*/
int list::findall(string first, string last, node_ptr* map, int n)
{
    int ans;
    ans = 0;
    *map = find(first, last);
    while (*map != NULL)
    {
        ans++;
        *map = (*map)->next;
        *map = find(first, last);
    }
    return ans;
}

Node.cpp

#include "Node.h"
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
/**
* Empty Constructor
* 
*/
node::node()
{
    last  = "";
    first = "";
    age   = 0;
    next  = nullptr;
}

/**
* Destructor
*
*/
node::~node()
{ if (next != nullptr) next = nullptr; 
}
/**
* Put
*
*/
void node::put(ostream &out)
{ out << setw(14) << left << last << setw(14) << first << setw(10) <<   age << endl; 
}
我真的很感谢你的帮助。谢谢你。

findall()冻结,因为它被困在一个无限循环中。

如果没有找到匹配的节点,第一次调用find()返回nullptr,退出findall()

但是如果找到匹配的节点,则进入循环,调用find()从头开始重新搜索整个列表。它会找到和之前相同的节点。然后再次调用find(),如此反复。

要解决此问题,如果find()返回匹配节点,则需要在以下调用中将next节点传递给find(),以便它可以在先前搜索停止的地方开始搜索。重复,直到你到达列表的末尾。

class list 
{  public:
    ...
        int findall(string first, string last, node_ptr *map, int n);
        node_ptr find(string first, string last, node_ptr start = nullptr);               // Locate a note
    ...
};

node_ptr list::find(string last, string first, node_ptr start) 
{
    node_ptr temp = (start) ? start : head;
    while (temp)
    {
        if ((temp->first == first) && (temp->last == last)) break;
        temp = temp->next;
    }
    return temp;
}
int list::findall(string first, string last, node_ptr* map, int n)
{
    int ans = 0;
    node_ptr temp = nullptr;
    while (ans < n)
    {
        temp = find(first, last, temp);
        if (!temp) break;
        *map++ = temp;
        ++ans;
        temp = temp->next;
    }
    return ans;
}

更新:如果你不能改变find()的签名,那么你将不得不重写findall()来复制find()的功能:

class list 
{  public:
    ...
        int findall(string first, string last, node_ptr *map, int n);
        node_ptr find(string first, string last);               // Locate a node
    ...
};

node_ptr list::find(string last, string first) 
{
    node_ptr temp = head;
    while (temp)
    {
        if ((temp->first == first) && (temp->last == last)) break;
        temp = temp->next;
    }
    return temp;
}
int list::findall(string first, string last, node_ptr* map, int n)
{
    int ans = 0;
    node_ptr temp = head;
    while (ans < n)
    {
        while (temp)
        {
            if ((temp->first == first) && (temp->last == last)) break;
            temp = temp->next;
        }
        if (!temp) break;
        *map++ = temp;
        ++ans;
        temp = temp->next;
    }
    return ans;
}