繁体   English   中英

如何在C ++中从向量链接删除对?

[英]How to chain delete pairs from a vector in C++?

我有这个文本文件,我在其中将每一行读入std::vector<std::pair>

handgun bullets
bullets ore
bombs ore
turret bullets

第一项取决于第二项。 我正在编写一个删除功能,当用户输入项目名称时,它将删除包含该项目的对作为第二个项目。 由于存在依赖关系,因此依赖于已删除项目的项目也将被删除,因为它不再可用。 例如,如果我删除ore ,则由于ore不可用, bulletsbombs将不再可用。 因此, handgunturret也应删除,因为这些对取决于bullets ,而bullets取决于ore即间接依赖于ore 该链应该继续直到删除所有相关对。

我尝试在当前示例中执行此操作,并附带以下伪代码,

for vector_iterator_1 = vector.begin to vector.end
{
    if user_input == vector_iterator_1->second
    {
        for vector_iterator_2 = vector.begin to vector.end
        {
            if vector_iterator_1->first == vector_iterator_2->second
            {
                delete pair_of_vector_iterator_2
            }
        }

        delete pair_of_vector_iterator_1
    }
}

这不是一个很好的算法,但是它解释了我打算做什么。 在示例中,如果我删除ore ,那么bulletsbombs将被删除。 随后,取决于orebullets对也将被删除( bombs没有依赖性)。 由于只有一个单长度链( ore-->bullets ),因此只有一个嵌套的for循环可以对其进行检查。 然而,可以是零或大量的单链依赖性导致很多的或没有嵌套for环路。 因此,这不是一个非常实用的解决方案。 如何使用可变长度的依赖项链来做到这一点? 请告诉我。 感谢您的耐心等待。

PS:如果您不明白我的问题,请告诉我。

一种(幼稚的)解决方案:

  • 创建要删除项目的队列
  • 添加您的第一项(用户输入)
  • While(!empty(item-to-delete))遍历您的向量
  • 每次您在列表中找到当前项目作为第二个项目时,将第一个项目添加到队列中,然后删除该对

简单的优化:

  • 确保您永远不会将项目添加到队列两次(哈希表/等)

就个人而言,我只是使用标准库进行删除:

vector.erase(remove_if(vector.begin(), vector.end(), [](pair<string,string> pair){ return pair.second == "ore"; }));

的remove_if()给你一个迭代匹配条件的元素,因此你可以有一个函数,它在一个.second值来擦除,并删除匹配对同时节省了.first在那些被擦除值。 从那里,您可以循环播放,直到没有任何内容被删除为止。

对于您的解决方案,在循环中使用find_if可能会更简单,但是无论哪种方式,标准库都可以在此处使用一些有用的东西。

我忍不住不使用C ++标准库中的标准算法和数据结构编写解决方案。 我使用std::set来记住我们删除的对象(我更喜欢它,因为它具有日志访问权限并且不包含重复项)。 该算法与@Beth Crane提出的算法基本相同。

#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
#include <string>
#include <set>

int main()
{
    std::vector<std::pair<std::string, std::string>> v
    {   {"handgun", "bullets"},
        {"bullets", "ore"},
        {"bombs", "ore"},
        {"turret", "bullets"}};

    std::cout << "Initially: " << std::endl << std::endl;
    for (auto && elem : v)
        std::cout << elem.first << " " << elem.second << std::endl;

    // let's remove "ore", this is our "queue"
    std::set<std::string> to_remove{"bullets"}; // unique elements

    while (!to_remove.empty()) // loop as long we still have elements to remove
    {
        // "pop" an element, then remove it via erase-remove idiom
        //  and a bit of lambdas
        std::string obj = *to_remove.begin();
        v.erase(
            std::remove_if(v.begin(), v.end(),
                           [&to_remove](const std::pair<const std::string,
                                        const std::string>& elem)->bool
            {
                // is it on the first position?
                if (to_remove.find(elem.first) != to_remove.end())
                {
                    return true;
                }
                // is it in the queue?
                if (to_remove.find(elem.second) != to_remove.end())
                {
                    // add the first element in the queue
                    to_remove.insert(elem.first);
                    return true;
                }
                return false;
            }
                          ),
            v.end()
        );
        to_remove.erase(obj); // delete it from the queue once we're done with it
    }

    std::cout << std::endl << "Finally: " << std::endl << std::endl;
    for (auto && elem : v)
        std::cout << elem.first << " " << elem.second << std::endl;
}

@vsoftco我查看了Beth的答案,然后尝试了解决方法。 直到我回来,我才看到您的代码。 在仔细检查您的代码后,我发现我们做了几乎相同的事情。 这就是我所做的

std::string Node;

std::cout << "Enter Node to delete: ";

std::cin >> Node;

std::queue<std::string> Deleted_Nodes;

Deleted_Nodes.push(Node);

while(!Deleted_Nodes.empty())
{
    std::vector<std::pair<std::string, std::string>>::iterator Current_Iterator = Pair_Vector.begin(), Temporary_Iterator;

    while(Current_Iterator != Pair_Vector.end())
    {
        Temporary_Iterator = Current_Iterator;

        Temporary_Iterator++;

        if(Deleted_Nodes.front() == Current_Iterator->second)
        {
            Deleted_Nodes.push(Current_Iterator->first);

            Pair_Vector.erase(Current_Iterator);
        }

        else if(Deleted_Nodes.front() == Current_Iterator->first)
        {
            Pair_Vector.erase(Current_Iterator);
        }

        Current_Iterator = Temporary_Iterator;
    }

    Deleted_Nodes.pop();
}

要在我的问题的评论中回答您的问题,这就是else if语句的作用。 它应该是有向图,因此它仅删除链中的下一级元素。 更高层次的元素不会被触及。

1 --> 2 --> 3 --> 4 --> 5

删除5: 1 --> 2 --> 3 --> 4

移除3: 1 --> 2 4 5

移除1: 2 3 4 5

尽管我的代码与您的代码相似,但我还是C ++的专家(至今)。 告诉我是否犯了任何错误或忽略了任何内容。 谢谢。 :-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM