cynizm Temat założony przez niniejszego użytkownika |
[c++] implementacje lista/tablica/kopiec » 2014-04-10 00:02:52 Witam, przejdę od razu do sedna, jako projekt miałem stworzyć program implementujący tablice dynamiczną, listę, kopiec oraz zmierzyć czas wykonywania tych operacji dla zadanej liczby prób. Poświęciłem wiele czasu na to jednak program nie działa jak powinien, wiem ze jest to trochę linijek kodu (ok 800), ale byłbym wdzięczny za pomoc w rozwikłaniu paru problemów które mi się tu pojawiły: TABLICA: 1. funkcja dodawania do tablicy jedynie ją powiększa i wyswietla jakieś smieci, nie dodając zadanego elementu, pomiar czasu wykazuje cały czas 0. <- nieaktualne, poprawiono i działa 2. funkcja usuwania z tablicy nie działa wcale, pomiar czasu wykazuje cały czas 0. <- nieaktualne, poprawiono i działa LISTA: 3. funkcja wyświetlania list wyświetla podwójnie ostatni element, przypuszczam ze coś pomieszałem ze wskaźnikami w trakcie wczytywania listy. 4. funkcja dodawania do listy nie dodaje elementu ale kopiuje zawartosc list i dokleją ją na koniec <- poprawiono, działa 5. funkcja usuwania wysypuje program "access violation reading location" w linijce "if (temp->nastepna == 0)" KOPIEC: 6. tu jest jakaś totalna masakra, nie wiem jak opisac te błędy, wyświetlanie wyrzuca mi śmieci z pamięci, dodawanie nie zwieksza ilości wyświetlanych elementów, usuwanie nie zmniejsza ich ilości. przypuszczam że cała implementacja jest zła :/ byłbym niezmiernie wdzięczny gdyby ktoś nakierował mnie gdzie są błędy i jakiego typu oraz jak je poprawić, wiem że proszę o dużo ale nie mam już siły z tym walczyć. oto kod: #include "stdafx.h" #include <iostream> #include <cmath> #include <stdlib.h> #include <fstream> #include <cstdlib> #include <ctime>
#define MAX true #define MIN false
using namespace std;
struct liczba { signed int nbr; liczba * nastepna; liczba(); };
liczba::liczba() { nastepna = 0; }
struct lista { liczba * pierwszy; void dodaj_element( signed int war ); void usun_element( signed int nr ); void wyswietl_elementy(); void dodaj_poz( signed int war, signed int alt ); void wyszukaj( signed int war ); void zaladuj(); lista(); };
lista::lista() { pierwszy = 0; }
void lista::wyszukaj( signed int war ) { liczba * temp = pierwszy; while( temp ) { if( temp->nbr == war ) { cout << "liczba " << war << " wystepuje na liscie"; break; } temp = temp->nastepna; } system( "PAUSE" ); } void lista::dodaj_poz( signed int war, signed int alt ) { liczba * nowa = new liczba; liczba * temp = pierwszy; bool is = true; while( temp ) { if( temp->nbr == war ) { is = false; break; } temp = temp->nastepna; } if( is ) { nowa->nbr = alt; nowa->nastepna = pierwszy; pierwszy = nowa; } } void lista::dodaj_element( signed int war ) { liczba * nowa = new liczba; nowa->nbr = war; if( pierwszy == 0 ) { pierwszy = nowa; } else { liczba * temp = pierwszy; while( temp->nastepna ) { temp = temp->nastepna; } temp->nastepna = nowa; nowa->nastepna = NULL; } }
void lista::wyswietl_elementy() { liczba * temp = pierwszy; while( temp ) { cout << temp->nbr << endl; temp = temp->nastepna; } }
void lista::usun_element( signed int nr ) { liczba * poprzednia = pierwszy; if( pierwszy->nbr == nr ) { liczba * temp = pierwszy; pierwszy = temp->nastepna; } else { int j = 1; liczba * temp = pierwszy; while( temp ) { poprzednia = temp; if( temp->nbr == nr ) { break; } temp = temp->nastepna; ++j; } if( temp->nastepna == 0 ) { poprzednia->nastepna = 0; } else { poprzednia->nastepna = temp->nastepna->nastepna; } } }
void lista::zaladuj() { ifstream liczby( "liczby.txt" ); int war; if( !liczby ) { cout << "Nie mozna otworzyc pliku"; } else { while( !liczby.eof() ) { liczby >> war; dodaj_element( war ); } } liczby.close(); }
void obsluga_list() { lista lis; ifstream liczby( "liczby.txt" ); signed int buf; signed int war; int ch = 0; clock_t time; clock_t sr( 0 ); int testy = 0; double czas = 0; while( ch != 6 ) { system( "CLS" ); cout << "wybierz opcje:" << endl; cout << "0. ustaw liczbe testów." << endl; cout << "1. wczytaj liste z pliku" << endl; cout << "2. dodaj element" << endl; cout << "3. usun element" << endl; cout << "4. wyswietl tablice" << endl; cout << "5. wyszukaj" << endl; cin >> ch; switch( ch ) { case 0: cout << "ile testów chcesz wykonwac?"; cin >> testy; break; case 1: lis.zaladuj(); break; case 2: for( int i = 0; i < testy; i++ ) { war = rand() % 9999 - 4998; buf = rand() % testy; lis.zaladuj(); time = clock(); lis.dodaj_poz( war, buf ); time =( clock() - time ); czas = czas + time; } cout << "czas wykonania:" << czas << " ms" << endl; system( "PAUSE" ); break; case 3: for( int i = 0; i < testy; i++ ) { war = rand() % 9999 - 4998; lis.zaladuj(); time = clock(); lis.usun_element( war ); time =( clock() - time ); czas = czas + time; } cout << "czas wykonania:" << czas << " ms" << endl; system( "PAUSE" ); break; case 4: for( int i = 0; i < testy; i++ ) { time = clock(); lis.wyswietl_elementy(); time =( clock() - time ); czas = czas + time; } cout << "czas wykonania:" << czas << " ms" << endl; system( "PAUSE" ); break; case 5: for( int i = 0; i < testy; i++ ) { war = rand() % 9999 - 4998; time = clock(); lis.wyszukaj( buf ); time =( clock() - time ); czas = czas + time; } cout << "czas wykonania:" << czas << " ms" << endl; system( "PAUSE" ); break; case 6: break; } } }
struct kopiec { signed int * dane; unsigned max_roz, rozmiar; bool k; void zamien( unsigned int index_a, unsigned int index_b ) { unsigned int buff = dane[ index_a ]; dane[ index_a ] = dane[ index_b ]; dane[ index_b ] = buff; } bool porownaj( unsigned int index_a, unsigned int index_b ) { return k ?( dane[ index_a ] < dane[ index_b ] ? true: false ) :( dane[ index_a ] > dane[ index_b ] ? true : false ); } bool wstaw( signed int wartosc ); unsigned int usun(); bool odbuduj( unsigned nowy_roz ); void wyswietl(); kopiec( unsigned int max_roz, bool max = true ); void zaladuj( int roz ); };
kopiec::kopiec( unsigned int ssize, bool max ) : max_roz( ssize ) , dane( new signed int[ ssize + 2 ] ) , rozmiar( 0 ) , k( max ) { memset( dane,( max ? 0: 0xFFFFFFFF ), ssize + 2 ); }
bool kopiec::wstaw( signed int wartosc )
{ if( rozmiar == max_roz ) { return false; } dane[ rozmiar++ ] = wartosc; for( unsigned int i = rozmiar; i != 1; i /= 2 ) { if( porownaj(( i / 2 ) - 1, i - 1 ) ) { zamien(( i / 2 ) - 1, i - 1 ); } else { break; } } return true; }
unsigned kopiec::usun()
{ if( rozmiar == 0 ) return 0; signed wartosc = dane[ 0 ]; dane[ 0 ] = dane[ --rozmiar ]; unsigned i = 1; while( i * 2 <= rozmiar ) { register unsigned temp = porownaj(( i * 2 ) - 1, i * 2 ) ?( i * 2 ) :( i * 2 ) - 1; if( porownaj( i - 1, temp ) ) { zamien( i - 1, temp ); i = temp + 1; } else { break; } } return wartosc; }
bool kopiec::odbuduj( unsigned nowy_roz )
{ if( nowy_roz < rozmiar ) { return false; } max_roz = nowy_roz; signed * temp = new signed[ nowy_roz ]; memset( temp,( k ? 0: ~0 ), nowy_roz ); memcpy( temp, dane, rozmiar ); delete[] dane; dane = temp; return true; }
void kopiec::wyswietl() { int cnt = 0; int j = 0; int sum = 0; for( unsigned i = 0; i < rozmiar; ++i ) { cout << dane[ i ] << endl; if( i == 0 ) { cout << "----------------------" << endl; ++j; } else { if( cnt == pow( 2, j ) ) { cout << "----------------------" << endl; ++j; cnt = 0; } } ++cnt; } }
void kopiec::zaladuj( int roz ) { ifstream liczby( "liczby.txt" ); signed int war; delete[] dane; dane = new signed int[ roz ]; if( !liczby ) { cout << "Nie mozna otworzyc pliku"; } else { while( !liczby.eof() ) { liczby >> war; wstaw( war ); } } liczby.close(); }
void obsluga_kopca( int roz ) { srand( time( NULL ) ); kopiec heap( roz ); int ch = 0; clock_t time; clock_t sr( 0 ); int testy = 0; double czas = 0; int war; system( "CLS" ); cout << "wybierz opcje:" << endl; cout << "0. ustaw liczbe testów." << endl; cout << "1. wczytaj kopiec z pliku" << endl; cout << "2. dodaj element" << endl; cout << "3. usun element" << endl; cout << "4. wyswietl kopiec" << endl; cin >> ch; switch( ch ) { case 0: cout << "ile testów chcesz wykonwac?"; cin >> testy; break; case 1: heap.zaladuj( roz ); break; case 2: for( int i = 0; i < testy; i++ ) { war = rand() % 9999 - 4998; heap.zaladuj( roz ); time = clock(); heap.wstaw( war ); time =( clock() - time ); czas = czas + time; } cout << "czas wykonania:" << czas << " ms" << endl; system( "PAUSE" ); break; case 3: for( int i = 0; i < testy; i++ ) { heap.zaladuj( roz ); time = clock(); heap.usun(); time =( clock() - time ); czas = czas + time; } cout << "czas wykonania:" << czas << " ms" << endl; system( "PAUSE" ); break; case 4: for( int i = 0; i < testy; i++ ) { heap.zaladuj( roz ); time = clock(); heap.wyswietl(); time =( clock() - time ); czas = czas + time; } cout << "czas wykonania:" << czas << " ms" << endl; system( "PAUSE" ); break; case 5: cout << "powrót"; break; } }
struct tablica { int roz; signed int * tab; tablica( int roz ); void dodaj( int nr, signed int * tab, signed int wartosc ); void wyswietl( int roz ); void usun( int nr, signed int * tab ); void zaladuj( int ilosc ); };
tablica::tablica( int roz2 ) { tab = new signed int[ roz2 ]; roz = roz2; } void tablica::dodaj( int nr, signed int * tab, signed int wartosc ) { signed int * buff = new signed int[ roz ]; memcpy(( signed int * ) buff,( signed int * ) tab, roz * sizeof( signed int ) ); ++roz; delete[] tab; tab = new signed int[ roz ]; int j = 0; int i = 0; while( i <= roz ) { if( i ==( nr - 1 ) ) { tab[ i ] = wartosc; } else { tab[ i ] = buff[ j ]; ++j; } ++i; } delete[] buff; }
void tablica::usun( int nr, signed int * tab ) { signed int * buff = new signed int[ roz ]; memcpy(( signed int * ) buff,( signed int * ) tab, roz * sizeof( signed int ) ); --roz; delete[] tab; tab = new signed int[ roz ]; int j = 0; int i = 0; while( i <= roz ) { if( i ==( nr - 1 ) ) { } else { tab[ j ] = buff[ i ]; ++j; } ++i; } delete[] buff; }
void tablica::wyswietl( int roz ) { for( int i = 0; i < roz; i++ ) cout << tab[ i ] << endl; }
void tablica::zaladuj( int ilosc ) { ifstream liczby; int tmp = 0; tab = new signed int[ ilosc ]; liczby.open( "liczby.txt" ); if( !liczby ) { cout << "Nie mozna otworzyc pliku"; system( "PAUSE" ); } else { while( !liczby.eof() ) liczby >> tab[ tmp++ ]; } liczby.close(); }
void obsluga_tablic( int ilosc ) { int ch = 0; int spc = 0; tablica tab1( ilosc ); double czas; clock_t time; clock_t sr( 0 ); int testy = 0; int buf; signed int war; ifstream liczby; while( ch != 5 ) { system( "CLS" ); cout << "wybierz opcje:" << endl; cout << "0. ustaw liczbe testów." << endl; cout << "1. wczytaj tablice z pliku" << endl; cout << "2. dodaj element" << endl; cout << "3. usun element" << endl; cout << "4. wyswietl tablice" << endl; cin >> ch; switch( ch ) { case 0: cout << "ile testów chcesz wykonwac?"; cin >> testy; break; case 1: tab1.zaladuj( ilosc ); break; case 2: czas = 0; for( int i = 0; i < testy; i++ ) { buf =( rand() % 9999 ) - 4998; war =( rand() % testy ); tab1.zaladuj( ilosc ); time = clock(); tab1.dodaj( buf, tab1.tab, war ); time =( clock() - time ); czas = czas + time; } cout << "czas wykonania:" << czas << " ms" << endl; system( "PAUSE" ); ++ilosc; break; case 3: czas = 0; for( int i = 0; i < testy; i++ ) { tab1.zaladuj( ilosc ); buf =( rand() % 9999 ) - 4998; time = clock(); tab1.usun( buf, tab1.tab ); time =( clock() - time ); czas = czas + time; } cout << "czas wykonania:" << czas / testy << " ms" << endl; system( "PAUSE" ); break; case 4: czas = 0; for( int i = 0; i < testy; i++ ) { tab1.zaladuj( ilosc ); time = clock(); tab1.wyswietl( ilosc ); time =( clock() - time ); czas = czas + time; } cout << "czas wykonania:" << czas / testy << " ms" << endl; system( "PAUSE" ); break; case 5: cout << "powrót"; break; } } }
int _tmain( int argc, _TCHAR * argv[] ) { int ilosc; int ch = 0; signed int liczba; ofstream nowyplik; srand( time( NULL ) ); double czas = 0; while( ch != 5 ) { cout << "wybierz opcje:" << endl; cout << "1. wygeneruj plik." << endl; cout << "2. tablica" << endl; cout << "3. kopiec" << endl; cout << "4. lista" << endl; cin >> ch; switch( ch ) { case 1: nowyplik.open( "liczby.txt" ); cout << "ile liczb chcesz przetestowac?"; cin >> ilosc; if( nowyplik.is_open() == 1 ) { cout << "otwarto plik" << endl; for( int i = 0; i < ilosc; ++i ) { liczba =( rand() % 9999 ) - 4998; nowyplik << liczba << endl; } } nowyplik.close(); break; case 2: obsluga_tablic( ilosc ); break; case 3: obsluga_kopca( ilosc ); break; case 4: obsluga_list(); break; default: break; } } system( "PAUSE" ); return 0; }
|
|
alixir |
» 2014-04-10 13:12:47 Masa prostych błędów. Nie wiem czy komuś będzie się chciało przeglądać całość. Odnośnie tablic: - każdorazowo niezależnie od wyboru ładujesz tablicę z pliku, co powoduje, że nawet jak dodasz nowy element, to i tak za chwilę załadujesz poprzednią tablicę i zakryjesz to co dodałeś - index nowego element losowany jest z zakresu 0 do 'testy', natomiast podczas dodawania masz warunek typu if i==(index-1) - strukturę zamieniłbym na klasę, ukrywając pola i dodając destructor, bo obecnie masz wyciek pamięci - np. tak: class tablica { private: unsigned int roz; int * tab; public: tablica(); tablica( unsigned int rozmiar ); ~tablica(); void dodaj( int index, int wartosc ); void wyswietl(); void usun( int index ); void zaladuj(); }; - wywaliłbym niepotrzebne argumenty funkcji (rozmiar i wskaźnik do tablicy jest przecież składową i nie musi być podawany każdorazowo) - możnaby pokusić się też o wywalenie funkcji zaladuj() Możesz wykorzystać funkcję dodaj() do tego celu Tablica przy drobnych modyfikacjach, które nadmieniłem wyżej działa poprawnie, reszty jednak nie chce mi się przeglądać. |
|
cynizm Temat założony przez niniejszego użytkownika |
» 2014-04-10 14:50:50 Tablice już poprawiłem i działa porawnie, w programie chodzi o mierzenie czasu operacji a nie o samą operacje dlatego wszystko jest ladowane od nowa po kazdej operacji. Gdybyś mógł przyjrzeć się liscie byłbym wdzięczny, nie bardzo wiem jakie tam sa błędy |
|
michal11 |
» 2014-04-10 16:48:27 Nie możesz zrobić czegoś takiego lista::lista() { pierwszy = 0; } jak nie masz napisanego operatora =. Edit. @Down Racja, w sumie nie wiem dlaczego to napisałem, teraz nie ma to sensu. |
|
killjoy |
» 2014-04-10 18:18:59 @up pierwszy jest wskaźnikiem, więc jeżeli kompilator nie będzie się rzucał, może tak zrobić, gdyż jest to zwykłe zerowanie wskaźnika. Generalnie do tych celów powinno używać się NULL zamiast 0, gdyż NULL może być rzutowane na dowolny typ. |
|
alixir |
» 2014-04-10 19:05:36 Nie chce mi się przeglądać całego twojego programu bo nie rozumiem dokładnie zamiaru. Ogólnie sama struktura listy wygląda ok. Wyświetlanie i dodawanie działa poprawnie, oczywiście nie w twoim menu, bo jak zwykle wczytujesz za każdym razem dane z pliku, więc przy każdym dodaniu nowego elementu, dodajesz również zawartość całego pliku. Funkcję usuwającą element natomiast bym zmienił na taką: void lista::usun_element( signed int nr ) { if( nr == 1 ) { liczba * temp = pierwszy; pierwszy = temp->nastepna; } if( nr >= 2 ) { int j = 1; liczba * temp = pierwszy; while( temp ) { if(( j + 1 ) == nr ) break; temp = temp->nastepna; j++; } if( temp->nastepna->nastepna == 0 ) temp->nastepna = 0; else temp->nastepna = temp->nastepna->nastepna; } } |
|
cynizm Temat założony przez niniejszego użytkownika |
» 2014-04-10 22:12:48 ok poprawiłem to dodawanie elementu w menu, działa teraz poprawnie, dodaje jeden element do listy, ale nadal nie wiem czemu ostatni element jest wyswietlany/wczytywany dwa razy, co do usuwania to ma działać tak ze podaje się wartosc która ma byc usunieta z listy (pierwsze jej wystąpienie) @up funkcja usuwająca która zamieściłeś wyrzuca mi błąd "Access violation reading location" w if( temp->nastepna->nastepna == 0 ) |
|
alixir |
» 2014-04-11 08:11:49 Źle odebrałem twój zamysł. Moja funkcja usuwa po numerze indeksu, a nie po wartości. |
|
« 1 » |