Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Implementacja rozbudowanych struktur danych - problem z pamięcią

Ostatnio zmodyfikowano 2016-03-24 20:20
Autor Wiadomość
arciobus
Temat założony przez niniejszego użytkownika
Implementacja rozbudowanych struktur danych - problem z pamięcią
» 2016-03-24 20:07:17
Witam, mam dość skomplikowany problem, postaram się go przedstawić jak najprościej, na początek kod.
C/C++
#include <iostream>
#include <cstdio>
typedef long long ll;
using namespace std;



#define Template_Class template < class Type >
template < class Type >
class Vector {
public:
    Vector();
    Vector( const Vector & );
    ~Vector();
    Vector & operator =( const Vector & _Vector );
    inline bool empty() const;
    inline size_t size() const;
    void push_back( const Type & ), pop();
    inline Type & top() const;
    Type & operator []( const size_t );
private:
    Type * ARRAY;
    static int default_size;
    int array_size, real_size;
    void size_up(), size_down();
};

Template_Class Vector < Type >::Vector()
    : ARRAY( new Type[ default_size ] )
     , array_size( 0 )
     , real_size( default_size )
{ }

Template_Class Vector < Type >::Vector( const Vector & _Vector )
    : array_size( _Vector.array_size )
     , real_size( _Vector.real_size )
     , ARRAY( new Type[ real_size ] )
{
    for( int i = 0; i < array_size; i++ )
         ARRAY[ i ] = _Vector.ARRAY[ i ];
   
}

Template_Class Vector < Type >& Vector < Type >::operator =( const Vector & _Vector ) {
    if( & _Vector != this ) {
        delete[] ARRAY;
        array_size = _Vector.array_size;
        real_size = _Vector.real_size;
        ARRAY = new Type[ real_size ];
        for( int i = 0; i < array_size; i++ )
             ARRAY[ i ] = _Vector.ARRAY[ i ];
       
    }
    return * this;
}

Template_Class Vector < Type >::~Vector() {
    delete[] ARRAY;
}

Template_Class inline bool Vector < Type >::empty() const {
    return !array_size;
}

Template_Class inline size_t Vector < Type >::size() const {
    return array_size;
}

Template_Class void Vector < Type >::push_back( const Type & value ) {
    ARRAY[ array_size++ ] = value;
    if( array_size == real_size )
         size_up();
   
}

Template_Class void Vector < Type >::pop() {
    array_size--;
    if(( real_size >> 1 ) > array_size && array_size > default_size )
         size_down();
   
}

Template_Class inline Type & Vector < Type >::top() const {
    return ARRAY[ array_size - 1 ];
}

Template_Class Type & Vector < Type >::operator []( const size_t pos ) {
    return ARRAY[ pos ];
}

Template_Class int Vector < Type >::default_size = 1;

Template_Class void Vector < Type >::size_up() {
    real_size <<= 1;
    Type * TMP = new Type[ real_size ];
    for( int i = 0; i < array_size; i++ )
         TMP[ i ] = ARRAY[ i ];
   
    delete[] ARRAY;
    ARRAY = TMP;
}

Template_Class void Vector < Type >::size_down() {
    real_size >>= 1;
    Type * TMP = new Type[ real_size ];
    for( int i = 0; i < array_size; i++ )
         TMP[ i ] = ARRAY[ i ];
   
    delete[] ARRAY;
    ARRAY = TMP;
}
#undef Template_Class





#define Template_Class template < class Type >
template < class Type >
class Queue {
public:
    Queue();
    ~Queue();
    void push( const Type & ), pop();
    inline bool empty_queue();
    inline size_t queue_size();
    inline Type & first(), & last();
private:
    Type * QUE;
    size_t array_size, real_size, first_element, last_element;
    static int default_size;
    void size_up(), size_down();
};

Template_Class Queue < Type >::Queue()
    : array_size( 0 )
     , real_size( default_size )
     , first_element( 0 )
     , last_element( - 1 )
     , QUE( new Type[ default_size ] )
{ }

Template_Class Queue < Type >::~Queue() {
    delete[] QUE;
}

Template_Class void Queue < Type >::push( const Type & value ) {
    QUE[ last_element =( last_element + 1 ) % real_size ] = value;
    array_size++;
    if( array_size == real_size )
         size_up();
   
}

Template_Class void Queue < Type >::pop() {
    first_element =( real_size + first_element + 1 ) % real_size;
    array_size--;
    if(( real_size >> 1 ) > array_size && array_size > default_size )
         size_down();
   
}

Template_Class inline bool Queue < Type >::empty_queue() {
    return !array_size;
}

Template_Class inline size_t Queue < Type >::queue_size() {
    return array_size;
}

Template_Class inline Type & Queue < Type >::first() {
    return QUE[ first_element ];
}

Template_Class inline Type & Queue < Type >::last() {
    return QUE[ last_element ];
}

Template_Class int Queue < Type >::default_size = 1;

Template_Class void Queue < Type >::size_up() {
    Type * TEMP = new Type[ real_size << 1 ];
    for( int i = first_element, j = 0; j < real_size; i =( i + real_size + 1 ) % real_size, j++ )
         TEMP[ j ] = QUE[ i ];
   
    delete[] QUE;
    QUE = TEMP;
    real_size <<= 1, first_element = 0, last_element = array_size - 1;
}

Template_Class void Queue < Type >::size_down() {
    Type * TEMP = new Type[ real_size >> 1 ];
    for( int i = first_element, j = 0; j < array_size; i =( i + real_size + 1 ) % real_size, j++ )
         TEMP[ j ] = QUE[ i ];
   
    delete[] QUE;
    QUE = TEMP;
    real_size >>= 1, first_element = 0, last_element = array_size - 1;
}
#undef Template_Class





class Graph {
public:
    Graph();
    Graph( const size_t );
    ~Graph();
    void add_edge( const size_t, const size_t ), breadth_first_search( int );
private:
    class Element {
    public:
        Vector < size_t > Connection;
        bool visit;
        int distance;
    } * GRAPH;
    int used_vertex, friend_groups;
    size_t vertices_number;
};

Graph::Graph() { }

Graph::Graph( const size_t _size )
    : vertices_number( _size )
     , GRAPH( new Element[ _size ] )
{
    for( int i = 0; i < vertices_number; i++ )
         GRAPH[ i ].visit = false;
   
}

Graph::~Graph() {
    delete[] GRAPH;
}

void Graph::add_edge( const size_t left_vertex, const size_t right_vertex ) {
    GRAPH[ left_vertex - 1 ].Connection.push_back( right_vertex - 1 );
    GRAPH[ right_vertex - 1 ].Connection.push_back( left_vertex - 1 );
}

void Graph::breadth_first_search( int user ) {
    used_vertex = user - 1;
    int group_number = 1;
    GRAPH[ used_vertex ].distance = 0, GRAPH[ used_vertex ].visit = true;
    Queue < Element > Q;
    Q.push( GRAPH[ used_vertex ] );
    while( !Q.empty_queue() ) {
        Element current = Q.first();
        for( size_t i = 0; i < current.Connection.size(); i++ )
        if( !GRAPH[ current.Connection[ i ] ].visit ) {
            GRAPH[ current.Connection[ i ] ].visit = true, GRAPH[ current.Connection[ i ] ].distance = current.distance + 1;
            Q.push( GRAPH[ current.Connection[ i ] ] );
        }
        Q.pop();
    }
    GRAPH[ used_vertex ].visit = false;
    cout << "Znajomi numeru " << used_vertex + 1 << ":\n";
    for( int i = 0; i < vertices_number; i++ )
    if( GRAPH[ i ].visit )
         cout << i + 1 << ": " << GRAPH[ i ].distance << '\n';
   
    GRAPH[ used_vertex ].visit = true;
    for( int i = 0; i < vertices_number; i++ )
    if( !GRAPH[ i ].visit ) {
        GRAPH[ i ].visit = true;
        group_number++;
        Q.push( GRAPH[ i ] );
        while( !Q.empty_queue() ) {
            Element current = Q.first();
            for( size_t j = 0; j < current.Connection.size(); j++ )
            if( !GRAPH[ current.Connection[ j ] ].visit ) {
                GRAPH[ current.Connection[ j ] ].visit = true;
                Q.push( GRAPH[ current.Connection[ j ] ] );
            }
            Q.pop();
        }
    }
    cout << "Grup znajomych jest " << group_number << ".\n";
}





int main() {
    ios_base::sync_with_stdio( false );
    int test;
    cin >> test;
    while( test-- ) {
        size_t number, friendships, user;
        cin >> number >> friendships;
        Graph A( number );
        for( int i = 0, left, right; i < friendships; i++ ) {
            cin >> left >> right;
            A.add_edge( left, right );
        }
        cin >> user;
        A.breadth_first_search( user );
    }
}

Dość dużo tego. Problem występuje w funkcji klasy "Graph" (breadth_first_search). Chodzi o szablonową klasę którą napisałem - "Vektor". Mam taką strukturę:
C/C++
class Element {
public:
    Vector < size_t > Connection;
    bool visit;
    int distance;
} * GRAPH;
Brak konstruktorów i destruktorów. W funkcji w której występuje problem używam kolejki do której wrzucane są elementy tego typu. Wewnątrz pętli jest również jeden obiekt tej klasy. Kod:
C/C++
Queue < Element > Q;
Q.push( GRAPH[ used_vertex ] );
while( !Q.empty_queue() ) {
    Element current = Q.first();
    for( size_t i = 0; i < current.Connection.size(); i++ )
    if( !GRAPH[ current.Connection[ i ] ].visit ) {
        GRAPH[ current.Connection[ i ] ].visit = true, GRAPH[ current.Connection[ i ] ].distance = current.distance + 1;
        Q.push( GRAPH[ current.Connection[ i ] ] );
    }
    Q.pop();
}
Na początek powiem że kiedy skorzystałem z własnej implementacji kolejki i STL-owego vectora program działał bez zarzutów. Link do zadania: http://main2.edu.pl/c​/konkurs-podstaw-algorytmiki/p​/por/.
Problem występuje natomiast przy mojej implementacji. Polega on na tym, że otrzymuję "process exited due to signal 11", czyli prawdopodobnie pisanie po nieprzydzielonej pamięci. I teraz moje pytanie. Co powinienem zmienić/dodać/usunąć w szablonowej klasie 'Vector', abym mógł go wykorzystać tak, że każdy obiekt klasy 'Element' mogę wrzucić do kolejki albo przypisać do zmiennej poprawnie. Podejrzewam, że problem leży gdzieś po stronie konstruktorów (i także operatora przypisania). Jakieś wskazówki co mogę zrobić?
P-146527
Monika90
» 2016-03-24 20:14:24
tu jest błąd
C/C++
Template_Class Vector < Type >::Vector( const Vector & _Vector )
    : array_size( _Vector.array_size )
     , real_size( _Vector.real_size )
     , ARRAY( new Type[ real_size ] )
{
    for( int i = 0; i < array_size; i++ )
         ARRAY[ i ] = _Vector.ARRAY[ i ];
   
}

W momencie inicjalizacji składowej ARRAY składowa real_size nie jest jeszcze zainicjalizowana, ponieważ kolejność inicjalizacji nie zależy od kolejności w konstruktorze, ale jest taka sama jak kolejność deklaracji składowych w klasie.

To znaczy
int array_size, real_size;

powinno być przed
Type * ARRAY;
P-146528
arciobus
Temat założony przez niniejszego użytkownika
» 2016-03-24 20:20:11
Aż nie wierzę że to było takie proste...
Dziękuję za pomoc i cenną wskazówkę na przyszłość :D
P-146529
« 1 »
  Strona 1 z 1