搜索链表,不同的数据类型

时间:2012-04-20 19:40:52

标签: c++ search linked-list

我的任务是制作一个程序,按标题,流派,年份,评级,主演等搜索400多部电影(使用链接列表链接)。

虽然有一个问题,我们只允许一个搜索功能通过链表预先形成搜索。此外,在该搜索功能中,我们只允许一个循环 - 我假设在我的情况下将是... ...

  while (moviePtr != NULL)

显然,如果是演员搜索或类型搜索,他们将会有许多不同的实例。在演员,流派,评级,年份,子流派和支持演员的情况下,它应该输出它的每个单个实例。 (例如,如果Kevin Bacon在x-men和笔记本中,它应该输出的不仅仅是其中一个(输出文件而不是屏幕)。)

我发现自己完全被我们获得的这些限制所困扰。 我的搜索功能如何处理不同的数据类型? (年份和评级必须声明为整数)。它将如何知道我正在寻找什么?如果我正在寻找演员,我也不希望它也能搜索演出。

非常感谢任何关于如何开始和开始的建议。

编辑:  嗨,所有的想法id更新你们在我做了什么。我有3种不同的搜索功能。一个用于数值(年份和评级),一个用于流派和演员,最后一个用于标题。

以下是这三个代码。 首先是标题搜索。

void TitleSearched(MovieNode*head,
                string titleSearched,
                ofstream& outFile)
{
MovieNode* moviePtr;
bool found;

moviePtr = head;
found = false;

while (moviePtr !=NULL & !found)
{
    if (moviePtr-> title == titleSearched)
    {
        found = true;
    }
    else
    {
        moviePtr = moviePtr -> next;
    }

}
if (found)
{
    cout << endl << titleSearched << " has been found!\n";
    TitleOutput (moviePtr,outFile);
}
else
{
    cout << endl << titleSearched << " was not found.\n";
}
}

现在是年度/评级搜索。

int NumSearched(MovieNode* head, int numSearched)
{

int instances;
MovieNode* moviePtr;

ofstream outFile;


    moviePtr = head;
    instances = 0;
    while (moviePtr !=NULL)
    {
        if (moviePtr-> year == numSearched)
        {

            instances = instances +1;
            NumOutList(moviePtr,outFile,"year",numSearched,instances);
            moviePtr = moviePtr -> next;
        }
        else if (moviePtr->rating == numSearched)
        {

            instances = instances +1;
            NumOutList(moviePtr,outFile,"rating",numSearched,instances);
            moviePtr = moviePtr -> next;
        }
        else
        {
            moviePtr = moviePtr ->next;
        }


    }
return instances;
}

最后是流派/演员搜索。

int ItemSearch (MovieNode* head,string itemSearched, ofstream& outFile)
{
int instances;
MovieNode* moviePtr;


moviePtr = head;
instances = 0;






    while (moviePtr !=NULL)
    {
        if (moviePtr-> genre == itemSearched || moviePtr ->subGenre == itemSearched)
        {

            instances = instances +1;
            OutList(moviePtr,outFile,"Genre",itemSearched,instances);
            moviePtr = moviePtr -> next;
        }
        else if (moviePtr->leadActor == itemSearched || moviePtr->supportActor == itemSearched)
        {

            instances = instances +1;
            OutList(moviePtr,outFile,"Actor",itemSearched,instances);
            moviePtr = moviePtr -> next;
        }
        else
        {
            moviePtr = moviePtr ->next;
        }


    }



    return instances;
}

我想提醒大家我的任务是什么。 1.将这三个搜索功能合二为一 2.搜索中只有一个while循环 3.在任何给定函数中只返回一个(但是,假设这在组合时将是一个无效函数)

我的主要问题是我的内容和字符串。我不被允许将评级或年份声明为字符串。只是整理这三个代码的代码格式给了我一个头痛

3 个答案:

答案 0 :(得分:2)

您可以以接受谓词作为参数的方式编写搜索功能。谓词是某种“functionoid”(意思是,任何能够像函数一样被“调用”的东西 - 它可以是函数,或lambda,或函数对象。)

在C ++标准库中,谓词用于许多标准算法,所以你会看到代码(使用标准容器),如下所示:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>

bool begins_with_s(std::string s)
{
    return  s.length() > 0                  && 
            std::toupper( s.at(0) ) == 'S';
}

bool contains_a_number(std::string s)
{
    return std::find_if(s.begin(), s.end(), std::isdigit) != s.end(); 
}

int main()
{
    std::string movies_array[] =  
    { 
        "King Kong", 
        "Singin in the Rain", 
        "Die Hard 2", 
        "Superman", 
        "Star Wars", 
        "Jaws 3"
    };
    std::vector<std::string> movies( std::begin(movies_array), 
                                     std::end(movies_array) );

    // Use predicate - count if the movie name begins with "S"
    std::cout << "Movies beginning with S: " 
        << std::count_if(movies.begin(), movies.end(), begins_with_s) 
        << std::endl;

    // Use predicate - count if the movie name contains a number
    std::cout << "Movies containing a number: " 
        << std::count_if(movies.begin(), movies.end(), contains_a_number) 
        << std::endl;
}

以这种方式实现C ++标准算法的方式是接受表示谓词的模板参数,沿着

行。
template< typename PredicateType >
void my_function(PredicateType predicate)
{
    Movie my_movie;
    predicate(my_movie);
}

这是一种来自功能性编程学派的思考 - 将函数传递给函数(将函数视为“一等公民”)。

答案 1 :(得分:2)

您可以让搜索功能将“匹配”功能作为其参数之一,并在每部电影上调用此匹配功能以查看电影是否匹配。然后,您可以使用不同的匹配功能调用搜索功能。

这样的事情:

template <typename MatchFunction>
void search_movies(movie* moviePtr, MatchFunction match)
{
    while (moviePtr != NULL)
    {
        if (match(*moviePtr))
        {
            // output movie
        }
        moviePtr = moviePtr->next;
    }
}

然后您可以声明匹配函数:

bool matches_actor(movie& m, const std::string& actor)
{
    return m.actor == actor;
}

并使用如下特定查询调用它:

search_movies(moviePtr, std::bind(matches_actor, _1, "Morgan Freeman"));

std::bind是来自<functional>的C ++ 11函数;您可以等效地使用boost::bindstd::bind2nd

或者,如果您更喜欢采用更C风格的做事方式,您可以这样做:

void search_movies(movie* moviePtr, bool (*match)(movie*, void*), void* match_arg)
{
    while (moviePtr != NULL)
    {
        if (match(moviePtr, match_arg))
        {
            // output movie
        }
        moviePtr = moviePtr->next;
    }
}
...
bool matches_actor(movie* m, void* actor)
{
    return m.actor == *((std::string*)actor);
}
...
std::string actor = "Morgan Freeman";
search_movies(moviePtr, &matches_actor, (void*)(&actor));

答案 2 :(得分:2)

除了传递函子来检查匹配的选项外,还有其他选项。一个这样的选择是采取一组可选条件来检查(您可以使用boost::optional或手工制作的方法,或使用指针。例如:

void print_matching( node* list, int * year, std::string * actor... ) {
   // iterate over the list:
   while (...) {
      if (  ( !year  || ptr->year == *year )
         && ( !actor || ptr->actor == *actor ) 
         && ...
         )
      {
          // Film matches, print it
      }
   }
}

为了简化函数签名,您可以创建一个search_pattern类型来封装您要测试的字段(例如使用不同的方法:bool来确定可选性):

struct pattern {
   bool check_actor;
   std::string actor;
   bool check_year;
   int year;
};

void print_matching( node* list, pattern const & p ) {
   // iterate over the list:
   while (...) {
      if (  ( !p.check_year  || ptr->year == p.year )
         && ( !p.check_actor || ptr->actor == p.actor ) 
         && ...
         )
      {
          // Film matches, print it
      }
   }
}

在最后一种情况下,您实际上可以将测试移动到pattern对象中,并具有一个函数:

bool pattern :: matches(movie cosnt&amp; m)const {    返回(!check_year || m.year == year)         &amp;&amp;(!check_actor || m.actor == actor); }     void print_matching(node * list,pattern const&amp; p){        //遍历列表:        而(...){           if(p.matches(list-&gt; data))           {               //电影匹配,打印出来           }        }     }