簡體   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