2013-05-22 10 views
5

Powiedzmy, że mam klasę Foo. Zawiera wektor typu Foo. Jak można napisać pętlę iterację wektora w foo i nieustannie iterację wektorów sub aż osiągniemy poziom, na którym na wektorów jest pustyJak iterować przez wszystkie podektory w wektorze?

class Foo 
{ 
    Foo(); 
    std::vector<Foo> foos; 
} 

mogę to zrobić iteracyjne go przez, ale w jaki sposób iteruję wektorami w obiektach foo wewnątrz oryginalnego wektora rekurencyjnie, aż osiągnę poziom, w którym wektor jest pusty?

Foo f; 
if(!f->foos.empty()) 
{ 

    std::vector<Foo>::const_iterator itr; 

    for (itr = f.foos.begin(); itr!=f.foos.end(); ++itr) 
    { 
    } 
} 
+0

Jeśli Foo ma wektor Foos, wtedy otrzymasz przepełnienie stosu z powodu natury rekursywnej. Jesteś pewien, że to nie jest wektor Bar? –

+0

@ ChristristBales ma rację, ta struktura danych faktycznie implementuje drzewo ... – Exceptyon

+1

Opublikowany kod jest niedozwolony i nie kompiluje się z g ++ i typowymi opcjami (w tym '-D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC', co zmienia wiele nieokreślonych zachowanie na twarde błędy). –

Odpowiedz

8

Zastosowanie rekurencji:

class Foo 
{ 
    Foo(); 
    std::vector<Foo> foos; 

    void iterate() 
    { 
     std::vector<Foo>::const_iterator itr; 

     for (itr = foos.begin(); itr!=foos.end(); ++itr) 
     { 
      // do stuff breadth-first 
      (*itr).iterate(); 
      // do stuff depth-first 
     } 
    } 
} 
+0

-1: Sprytnie, ale rekursja rzadko ma miejsce w kodzie na poziomie produkcji. –

+0

@JohnDibling Całkowicie zależy od wymagań. W rzeczywistości często jest to dobre (na poziomie produkcji) rozwiązanie. – leemes

+0

W przypadku komentarzy, te punkty nie są odwiedzane w zamówieniu BFS i DFS. Oba są DFS ze względu na naturę rekursji. Rekursja * to * DFS. Drugim punktem w twoim kodzie jest * po * odwiedzeniu węzłów potomnych, zwanych również "cofaniem". BFS zwykle używa kolejki zamiast stosu (który jest niejawnie używany podczas implementacji za pomocą rekursji). – leemes

2

Użyj kolejkę:

std::deque<Foo> q; 
q.push_back(f); 
while (!q.empty()) { 
    Foo curr = q.back(); 

    typedef std::vector<Foo>::iterator iter; 
    iter end = curr.foos.end(); 
    for(iter it = curr.foos.begin(); it != end; ++it) { 
     if(!it->empty()) { 
      q.push_back(*it); 
      continue; 
     } 
     // do stuff with *it 
    } 

    q.pop_back(); 
} 
+0

Rozwiązanie rekurencyjne jest prostsze. –

+0

@JamesKanze Recursion zwykle tworzy prostsze rozwiązanie, ale zawsze istnieje ryzyko awarii programu, jeśli nie masz miejsca na stosie. – andre

+0

Istnieje ryzyko awarii programu, jeśli nie masz odpowiedniej sterty. Istnieje ryzyko, że program ulegnie awarii, jeśli popełnisz błąd programistyczny, co jest bardziej prawdopodobne, jeśli wybrane rozwiązanie jest bardziej skomplikowane. –

0

Twoje Foo obiekty tworzą strukturę danych drzewo. Możesz reprezentować dowolną ścieżkę z katalogu głównego do jakiegoś węzła jako std::stack<Foo*>, aby śledzić swoją pozycję w drzewie. Używając tego pomysłu i pierwszego wyszukiwania, możesz wykonać operację przeglądania wszystkich obiektów Foo bez użycia rekursji.

Powiązane problemy