Kłopot ze zmiennymi typu <vector>, <list>

0

Cześć.
Zacząłem pracę nad programem wyszukującym cykl Eulera w grafie nieskierowanym, spójnym o zadanej gęstości. Po drodze natomiast natknąłem się na pewien problem. Otóż jeżeli liczba wierzchołków będzie większa od około 300, przy gęstości 20%, to program wysypuje się. Zakładam, iż jest to problem z przepełnieniem stosu, natomiast słabo radzę sobie zarówno z klasą vector jak i list. Jeżeli ktoś znalazłby jakieś rozwiązanie tego problemu, prosiłbym o odpowiedź. :) Próbowałem już na starcie programu "resize'ować" zarówno listę jak i vector. Krawędzie wczytywane są z pliku tekstowego (przykładowy, "niedziałający" w załączniku).

#include <iostream>
#include<stdio.h>
#include<fstream>
#include<windows.h>
#include<conio.h>
#include<vector>
#include<list>

using namespace std;

list <int> LIGraph[5000];
vector<int> wynik(5000);
bool visited[5000];

void DFS(int v){
    visited[v] = true;
    for(list<int>::iterator i = LIGraph[v].begin(); i!= LIGraph[v].end(); i++)
        if(!visited[*i]) DFS(*i);
}

void DFSEuler(int v){
    while(!LIGraph[v].empty()){
        int w = LIGraph[v].front();
        LIGraph[v].pop_front();
        DFSEuler(w);
        wynik.push_back(v);
    }
}

double GetTime(){
  long long f,t;
  QueryPerformanceFrequency((PLARGE_INTEGER)&f);
  QueryPerformanceCounter((PLARGE_INTEGER)&t);
  return (double)t/(double)f;
}


int main(){

    int x, y, N;
    char nazwa[10];
    fstream plik;

    N = 400; // ilosc wierzcholkow & nazwa pliku 
    itoa(N, nazwa, 10);
    strncat(nazwa, ".txt", 4);
    plik.open(nazwa, ios::in);
    if(plik.good() == true){
        while(!plik.eof()){
            plik >> x;
            plik >> y;
            LIGraph[x].push_back(y);
        }
    }
    plik.close();

//------WARUNEK_KONIECZNY_&&_WARUNEK_DOSTATECZNY---------
    int c = 0;

    bool test = true;
    for(int i=1; i<=N; i++) visited[i] = false;

    for(int i=1; i<=N; i++){
        //if(LIGraph[i].size() % 2){
            //test = false;
           // break;
       // }

        if(!visited[i]){
            c++;
            DFS(i);
        }
    }

    if(c != 1) test = false;
//------------------------------------------------------
    double Start, Stop;
    if(test){
        wynik.clear();
        Start = GetTime();
        DFSEuler(1);
        Stop = GetTime();
        //for(vector<int>::iterator i = wynik.begin(); i != wynik.end(); i++)
            //cout << (*i) << " ";
    }else printf("BRAK CYKLU EULERA!");

    printf("Czas wyszukiwania %d, elementow:\t%lf\n", N, (double)(Stop-Start));
    getch();
    return 0;
}
 
1

wtf sa te [5000] w wektorze :D? pierwszy raz sie z czyms takich spotykam

vector<vector<int> > wynik

dwuwymiarowy wektor. To samo z lista, nie powinienes miec juz wtedy problemow

zawsze staraj sie robic uniwersalne rozwiazania zamiast jednego czy dwoch (5000 to jest jedno rozwiazanie, staraj sie uzywac zeby obslugiwal N a nie 5k)

0

Da się w ogóle w C++ zrobić coś takiego jak

list<list<int> > LIGraph; 

. Ponieważ wypluwa mi błędy 'error: no match for 'operator[]' in 'LIGraph[v]'. Poważnie nie wiem jak obsługiwać <list>.
*Te [5000] to już był akt desperacji :D

1

Używaj vector<T> wszędzie, gdzie to jest możliwe, dopóki profiler nie powie inaczej.

0

Z resztą nie jestem pewien czy problem leży w miejscu rozmiaru vectora. Ponieważ dla 400 wierzchołków powinien wystarczać rozmiar 401 (dla 300 wierzchołków, 301 wystarcza), a nawet gdy ustawie rozmiar na stałe na 10k to i tak program się zawiesza.

0

Generalnie to potrzebujesz takiego potworka:

vector<pair<bool,vector<int> > > Graph;

Ale nikt o zdrowych zmysłach czegoś takiego nie użyje, wiec dzielisz to sobie:

struct node { bool visited; vector<int> neighbors; node():visited(false) {} };
vector<node> Graph;

Wtedy użycie jest proste.

Natomiast jeżeli za każdym razem wiesz ile będzie wierzchołków to można użyć czegoś takiego:

struct node { bool visited; vector<node*> neighbors; node():visited(false) {} };
vector<node> Graph(NodeCount);

Przy takiej strukturze dodawanie krawędzi a -> b wygląda tak:

Graph[a].neighbors.push_back(&Graph[b]);

Natomiast użycie w algorytmach jest prostsze.

1 użytkowników online, w tym zalogowanych: 0, gości: 1