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

时间:2016-10-14 00:50:59

标签: c++

我正在编写一个函数来查找链表中所有出现的节点,该函数将返回主函数的出现次数,然后显示这些出现次数。该程序确实编译但它只是冻结,当我输入正确的名称来查找时似乎没有任何事情发生,如果我输入错误的名称,这不在列表中,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 List\n--------------\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; 
}

我非常感谢你的帮助。谢谢。

1 个答案:

答案 0 :(得分:3)

findall()冻结,因为它陷入无限循环。

如果找不到匹配的节点,则第一次调用find()会返回nullptrfindall()退出。

但如果找到匹配的节点,则输入一个循环,调用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;
}