【问题标题】:Searching a linked list, Different data types搜索链表,不同的数据类型
【发布时间】:2012-04-20 19:40:51
【问题描述】:

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

但有一个问题,我们只允许一个搜索函数通过链表执行搜索。此外,在该搜索功能中,我们只允许使用一个 while 循环——我假设在我的情况下将类似于...

  while (moviePtr != NULL)

显然,如果是演员搜索或类型搜索,它们将有许多不同的实例。对于演员、流派、评级、年份、子流派和配角,它应该输出找到的每一个实例。 (例如,如果 Kevin Bacon 在 x-men 和 notebook 中,它应该输出两者而不仅仅是其中之一(输出文件而不是屏幕)。

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

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

编辑: 大家好,我想更新你们我所做的事情。我有 3 种不同的搜索功能。一个用于数值(年份和评分),1 用于类型和演员,最后一个用于标题。

这是所有三个的代码。 首先是标题搜索。

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. 在任何给定函数中只有一个返回(但是,id 假设这将是一个 void 函数)

我认为我的主要问题是我的整数和字符串。我不允许将等级或年份声明为字符串。只是将这三者结合起来的代码格式让我很头疼

【问题讨论】:

  • 您的搜索条件是否指定了您要查找的内容,即“Kevin Bacon”+“演员”,还是您应该猜测他们要查找的内容?
  • 用户使用枚举类型从菜单中选择他们想要搜索的内容,例如,他们输入 0,退出,1 - 标题搜索,2- 搜索我的评分,3 - 按年份搜索, 4- 按演员搜索等
  • 添加了新的编辑。谢谢大家!

标签: c++ search linked-list


【解决方案1】:

您可以以接受谓词作为参数的方式编写搜索函数。谓词是某种“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);
}

这是一种来自函数式编程思想的技术——将函数传递给函数(将函数视为“一等公民”)。

【讨论】:

    【解决方案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 是来自 &lt;functional&gt; 的 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));
    

    【讨论】:

    • 对不起,我忘了提到我们的所有功能都只允许返回一个,包括这个。
    • @RileyFrancona:你在哪里看到多个回报?
    【解决方案3】:

    除了传递函子来检查匹配的选项外,还有其他选项。一个这样的选项是采用一组可选条件来检查(您可以使用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 类型来封装您要测试的字段(使用不同方法的示例:布尔值来确定可选性):

    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 模式::matches( 电影成本& m ) const { 返回 (!check_year || m.year == year ) &&(!check_actor || m.actor == 演员); } 无效打印匹配(节点*列表,模式常量和p){ // 遍历列表: 尽管 (...) { 如果(p.matches(列表->数据)) { // 电影匹配,打印 } } }

    【讨论】:

    • 大家好,我想我会告诉你我决定做什么。我把搜索功能分成三个不同的功能,一个是标题,一个是年份和评分,一个是类型和演员。这是每个人的代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-24
    • 1970-01-01
    • 1970-01-01
    • 2021-03-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多