Algorytmy i Struktury Danych laboratorium (INZ1505L)



Podobne dokumenty
Wykład 5. Sortowanie w czasie liniowologarytmicznym

Algorytmy i Struktury Danych

Sortowanie - wybrane algorytmy

Rekurencja. Dla rozwiązania danego problemu, algorytm wywołuje sam siebie przy rozwiązywaniu podobnych podproblemów. Przykład: silnia: n! = n(n-1)!

Algorytmy i Struktury Danych.

ZASADY PROGRAMOWANIA KOMPUTERÓW ZAP zima 2014/2015. Drzewa BST c.d., równoważenie drzew, kopce.

Sortowanie. Bartman Jacek Algorytmy i struktury

Zadanie projektowe 1: Struktury danych i złożoność obliczeniowa

Definicja. Ciąg wejściowy: Funkcja uporządkowująca: Sortowanie polega na: a 1, a 2,, a n-1, a n. f(a 1 ) f(a 2 ) f(a n )

Podstawy algorytmiki i programowania - wykład 6 Sortowanie- algorytmy

Podstawowe algorytmy i ich implementacje w C. Wykład 9

Algorytm selekcji Hoare a. Łukasz Miemus

ALGORYTMY I STRUKTURY DANYCH

Kolejka priorytetowa. Często rozważa się kolejki priorytetowe, w których poszukuje się elementu minimalnego zamiast maksymalnego.

Wstęp do programowania

Zadanie 1 Przygotuj algorytm programu - sortowanie przez wstawianie.

prowadzący dr ADRIAN HORZYK /~horzyk tel.: Konsultacje paw. D-13/325

Zajęcia nr 5 Algorytmy i wskaźniki. dr inż. Łukasz Graczykowski mgr inż. Leszek Kosarzewski Wydział Fizyki Politechniki Warszawskiej

Programowanie Proceduralne

Wstęp do programowania

Sortowanie. Kolejki priorytetowe i algorytm Heapsort Dynamiczny problem sortowania:

Sortowanie bąbelkowe

Algorytmy i struktury danych

liniowa - elementy następują jeden za drugim. Graficznie możemy przedstawić to tak:

Wstęp do programowania

Podstawy programowania 2. Temat: Drzewa binarne. Przygotował: mgr inż. Tomasz Michno

Złożoność obliczeniowa algorytmu ilość zasobów komputera jakiej potrzebuje dany algorytm. Pojęcie to

DYNAMICZNE PRZYDZIELANIE PAMIECI

tablica: dane_liczbowe

Tablice. Monika Wrzosek (IM UG) Podstawy Programowania 96 / 119

Informacje wstępne #include <nazwa> - derektywa procesora umożliwiająca włączenie do programu pliku o podanej nazwie. Typy danych: char, signed char

Strategia "dziel i zwyciężaj"

Laboratorium nr 7 Sortowanie

INFORMATYKA SORTOWANIE DANYCH.

Uniwersytet Zielonogórski Instytut Sterowania i Systemów Informatycznych. Algorytmy i struktury danych Laboratorium 7. 2 Drzewa poszukiwań binarnych

Kolokwium ze wstępu do informatyki, I rok Mat. (Ściśle tajne przed godz. 10 : grudnia 2005.)

ZASADY PROGRAMOWANIA KOMPUTERÓW

Drzewa poszukiwań binarnych

Wstęp do programowania

Porównanie Heap Sort, Counting Sort, Shell Sort, Bubble Sort. Porównanie sortowao: HS, CS, Shs, BS

Programowanie w VB Proste algorytmy sortowania

Analiza algorytmów zadania podstawowe

Kontrola przebiegu programu

Matematyczne Podstawy Informatyki

Rozwiązanie. #include <cstdlib> #include <iostream> using namespace std;

Algorytmy i Struktury Danych.

Podstawy algorytmiki i programowania - wykład 3 Funkcje rekurencyjne Wyszukiwanie liniowe i binarne w tablicy

Algorytmy i złożoności. Wykład 3. Listy jednokierunkowe

Wykład I. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Wykład II. Programowanie II - semestr II Kierunek Informatyka. dr inż. Janusz Słupik. Wydział Matematyki Stosowanej Politechniki Śląskiej

Algorytmy i Struktury Danych. Co dziś? Drzewo decyzyjne. Wykład IV Sortowania cd. Elementarne struktury danych

Stos LIFO Last In First Out

Podstawy programowania skrót z wykładów:

Drzewa wyszukiwań binarnych (BST)

Projektowanie klas c.d. Projektowanie klas przykład

PDF stworzony przez wersję demonstracyjną pdffactory Pro Program 15

Algorytmy sortujące. sortowanie kubełkowe, sortowanie grzebieniowe

wykład IV uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C, a C++. wykład IV dr Jarosław Mederski Spis Język C++ - wstęp

Programowanie w języku C++

dodatkowe operacje dla kopca binarnego: typu min oraz typu max:

Część 4 życie programu

Drzewa poszukiwań binarnych

Algorytmy i Struktury Danych. (c) Marcin Sydow. Introduction. QuickSort. Sortowanie 2. Limit. CountSort. RadixSort. Summary

Język ludzki kod maszynowy

Wykład 2. Drzewa zbalansowane AVL i 2-3-4

WYKŁAD 9. Algorytmy sortowania elementów zbioru (tablic) Programy: c4_1.c... c4_3.c. Tomasz Zieliński

Materiał Typy zmiennych Instrukcje warunkowe Pętle Tablice statyczne Wskaźniki Tablice dynamiczne Referencje Funkcje

Wstęp do programowania

Ćwiczenie 7 z Podstaw programowania. Język C++, programy pisane w nieobiektowym stylu programowania. Zofia Kruczkiewicz

Zastosowania drzew binarnych

Zasady analizy algorytmów

Algorytmy i struktury danych. Drzewa: BST, kopce. Letnie Warsztaty Matematyczno-Informatyczne

Algorytmy sortujące i wyszukujące

Zmienne i struktury dynamiczne

Podstawy Informatyki. Sprawność algorytmów

Algorytmy i struktury danych

Rekurencja. Przygotowała: Agnieszka Reiter

Podstawowe elementy proceduralne w C++ Program i wyjście. Zmienne i arytmetyka. Wskaźniki i tablice. Testy i pętle. Funkcje.

typ y y p y z łoż o on o e n - tab a lice c e w iel e owym m ar a o r we, e stru r kt k ury

Programowanie Procedurale

Dla każdej operacji łącznie tworzenia danych i zapisu ich do pliku przeprowadzić pomiar czasu wykonania polecenia. Wyniki przedstawić w tabelce.

Strona główna. Strona tytułowa. Programowanie. Spis treści. Sobera Jolanta Strona 1 z 26. Powrót. Full Screen. Zamknij.

Struktury danych i złozoność obliczeniowa. Prof. dr hab. inż. Jan Magott

Wskaźniki. nie są konieczne, ale dają językowi siłę i elastyczność są języki w których nie używa się wskaźników typ wskaźnikowy typ pochodny:

Przykładowe sprawozdanie. Jan Pustelnik

12. Rekurencja. UWAGA Trzeba bardzo dokładnie ustalić <warunek>, żeby mieć pewność, że ciąg wywołań się zakończy.

Programowanie i struktury danych

Abstrakcyjne struktury danych w praktyce

Algorytmy i złożoność obliczeniowa. Wojciech Horzelski

Aby uzyskać zaliczenie w pierwszym terminie (do 30 stycznia 2018) rozliczyć trzeba co najmniej 8 projektów, po 4 z każdej z części: C++ oraz Python.

TABLICE W JĘZYKU C/C++ typ_elementu nazwa_tablicy [wymiar_1][wymiar_2]... [wymiar_n] ;

Jak Windows zarządza pamięcią?

wykład V uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C++ klasy i obiekty wykład V dr Jarosław Mederski Spis Język C++ - klasy

Wykład 5_2 Algorytm ograniczania liczby serii za pomocą kopcowego rozdzielania serii początkowych

Programowanie proceduralne INP001210WL rok akademicki 2017/18 semestr letni. Wykład 3. Karol Tarnowski A-1 p.

Informatyka 1. Złożoność obliczeniowa

Podstawy informatyki. Informatyka stosowana - studia niestacjonarne. Grzegorz Smyk. Wydział Inżynierii Metali i Informatyki Przemysłowej

Wykład 1_2 Algorytmy sortowania tablic Sortowanie bąbelkowe

Wybrane algorytmy tablicowe

Programowanie obiektowe i C++ dla matematyków

Transkrypt:

Wrocław 26.05.2006 Algorytmy i Struktury Danych laboratorium (INZ1505L) Autor: Wojciech Podgórski WIZ INF Prowadzący: mgr Marcin Parczewski Sprawozdanie dotyczące testowania algorytmu sortowania. Algorytm: Sortowanie stogowe (HeapSort). Uwaga : Floyd zauważył, że przy rozbieraniu stogu element wstawiany na wierzchołek stogu opada zazwyczaj na samo dno stogu. Zaproponował następujące ulepszenie : po usunięciu największego elementu schodź do dna stogu idąc zawsze w stronę większego z potomków i przesuwając go jednocześnie na wolne miejsce (ojca), po dojściu do dna wstaw tam ostatni element stogu i przesuwaj go DoGóry (bardzo rzadko zachodzi taka potrzeba). Jakie są efekty tego usprawnienia? Spis Treści: 1. Opis i charakterystyka algorytmu...2 2. Ciało algorytmu...3 3. Usprawnienia i modyfikacje algorytmu...4 4. Wnioski...5 5. Wyniki i pomiary...6 6. Implementacja w języku C++...9 7. Bibliografia...13 1

1. Opis i charakterystyka algorytmu. Algorytm sortowania stogowego, zwany również algorytmem sortowanie przez kopcowanie (Heap Sort) jest jednym z najciekawszych narzędzi sortujących. Opiera się on na drzewiastej strukturze danych zwanej stertą, stogiem lub kopcem. Kopiec jest strukturą o kilku ważnych cechach, o których należy wspomnieć aby wytłumaczyć istotę sortowania stogowego. Własności kopca: wartości potomków danego węzła są w stałej relacji z wartością rodzica (dla kopca typu max wartość rodzica jest zawsze większa od wartości potomka, dla kopca typu min odwrotnie). Jeżeli kopiec ma być kopcem zupełnym, wtedy dodatkowo spełnione muszą być warunki: 1. drzewo jest prawie pełne tzn. liście występują na ostatnim i ewentualnie przedostatnim poziomie w drzewie 2. liście na ostatnim poziomie są spójnie ułożone od strony lewej do prawej. Jeżeli implementujemy kopiec na tablicy i wybieramy węzeł o indeksie i, to jego lewy potomek będzie miał indeks 2i+1 prawy natomiast 2i+2 (w numeracji od 0 do n) Poprawnie zbudowany kopiec: Rys.1 Poprawnie zbudowany kopiec Heap Sort będący algorytmem prawie tak szybkim jak Quick Sort (a w przypadku pesymistycznym, nawet szybszym!), jest praktycznie nie wrażliwy na uporządkowanie danych wejściowych. Jego złożoność obliczeniowa (czasowa) wynosi: Złożoność optymistyczna: O( n log n) Złożoność oczekiwana: O( n log n) Złożoność pesymistyczna: O( n log n) Taki rodzaj złożoności jest spowodowany wywoływaniem procedur Build-Max-Heap (utwórz kopiec o własności typu max), która jest złożoności jest klasy O(n) oraz Max-Heapify (przywróć danym zawartym w strukturze własność kopca typu max), która jest złożoności O (log n). Złożoność pamięciowa jest klasy O(1) Heap Sort zawdzięcza to temu, iż jest tzw. algorytmem sortującym w miejscu. Oznacza to, iż w czasie procesu sortowania tylko stała 2

liczba elementów tablicy wejściowej jest przechowywana poza nią. Tak więc algorytmy, które nie działają w miejscu wymagają dodatkowej pamięci. Heap Sort cechuje się również tym, iż jest niestety algorytmem niestabilnym. Oznacza to, iż posiadając 2 lub więcej identycznych wartości, nie sortuje ich w kolejności wejściowej. 2. Ciało algorytmu Po utworzeniu struktury kopca następuje właściwe sortowanie. Polega ono na usunięciu wierzchołka kopca, zwierającego element maksymalny dla typu max (minimalny dla typu min), a następnie wstawieniu w jego miejsce elementu z końca kopca i odtworzenie porządku kopcowego (Max-Heapify). W zwolnione w ten sposób miejsce, zaraz za końcem zmniejszonego kopca wstawia się usunięty element maksymalny. Operacje te powtarza się aż do wyczerpania elementów w kopcu. Wygląd tablicy można tu schematycznie przedstawić następująco: 0 1 2 k k+1 k+2 n ------------------------------------------------------------------------- Kopiec elementów do posortowania Posortowana tablica ------------------------------------------------------------------------- Tym razem kopiec kurczy się, a tablica przyrasta (od elementu ostatniego do pierwszego). Także, tu złożoność usuwania elementu połączonego z odtwarzaniem porządku kopcowego, ma złożoność logarytmiczną, a zatem złożoność tej fazy to O( n log n). Algorytm można również opisać w pseudo kodzie w celu implementacji w różnych językach programowania, oto on: Heapsort(A) 1 Build-Max-Heap(A) 2 for i lenght[a] downto 2 3 do zamień A[1] A[i] 4 heap-size[a] heap-size[a] 1 5 Max-Heapify(A, 1) Build-Max-Heap(A) Max-Heapify(A, i) 1 heap-size[a] lenght[a] 1 l Left(i) 2 for i lenght[a] div 2 downto 1 2 r Right(i) 3 do Max-Heapify(A, i) 3 if l heap-size[a] i A[l] > A[i] 4 then largest l 5 else largest i 6 if r heap-size[a] i A[r] > A[largest] 7 then largest r 8 if largest i 9 then zamień A[i] A[largest] 10 Max-Heapify(A, largest) 3

Rysunek ukazujący działanie algorytmu na prostym kopcu 5 elementowym: Rys. 2 Sortowanie przez kopcowanie na kopcu 5-elementowym typu max proszę zauważyć że w kroku A przywraca się porządek kopca 3. Usprawnienia i modyfikacje algorytmu Trudno jest usprawnić algorytm, który i tak jest już bardzo sprawny, jednak wyróżniamy 2 podstawowe modyfikacje: a) Koncepcja Floyda Koncepcja Floyda, polega na zauważeniu, iż element ponownie wstawiony do kopca podczas procesu wysortowywania, przebywa z reguły całą drogę w dół. Możemy więc zaoszczędzić czas unikając sprawdzenia, czy element trafił na pozycję, promując większego z synów do czasu osiągnięcia najniższego poziomu, a potem przesuwając z powrotem w górę kopca na właściwe miejsce. Ten pomysł pozwala zmniejszyć liczbę porównań asymptotycznie dwukrotnie blisko wartości: lg n! n lg n n ln 2 będącym absolutnym minimum dla liczby porównań algorytmu sortowania. Metoda ta wymaga stosowania dodatkowej ewidencji i jest przydatna w praktyce tylko wtedy gdy koszt porównań jest stosunkowo wysoki(np. gdy sortuje się rekordy z łańcuchami znaków albo z innymi typami długich kluczy). b) Kopiec oparty na tablicowej reprezentacji pełnego drzewa trynarnego (trójkowego) Inna koncepcja usprawnienia polega na zbudowaniu kopca opartego na tablicowej reprezentacji pewnego drzewa trynarnego (trójkowego), 4

4. Wnioski uporządkowanego kopcowo, którego węzeł na pozycji k jest większy, lub równy węzłom na pozycjach 3k-1, 3k, 3k+1, jest mniejszy lub równy niż węzeł na pozycji E((k+1)/3) dla pozycji z przedziału od 1 do n w tablicy n- elementowej. Mniejszy koszt wypływający z faktu zredukowanej wysokości drzewa, pociąga ze sobą wyższy koszt sprawdzania 3 węzłów potomnych, w każdym rozpatrywanym węźle. Dalsze zwiększanie liczby potomków przypadających na jeden węzeł nie powoduje raczej zwiększenia ogólnej wydajności algorytmu. Sortowanie stogowe jest bardzo specyficznym rodzajem sortowania. Z pewnością nie nadaje się do sortowania małych zbiorów danych, ponieważ lepiej wtedy użyć algorytmu QuickSort, który jest szybszy. Wymaga zastosowania określonej struktury danych, co ogranicza jego stosowanie i komplikuje implementację. Niestety, jest również algorytmem niestabilnym co może, w niektórych wypadkach powodować niemożność posortowania danych(w takim przypadku wybiera się inny). Problemem jest również to, iż działając na strukturze statycznej (np. tablicy) pojawia się ograniczenie ilości danych. HeapSort na strukturze dynamicznej jest bardzo trudny do zaimplementowania, choć jego złożoność obliczeniowa jest mniej więcej taka sama (niestety w takiej strukturze złożoność pamięciowa nie jest już stała). HeapSort najlepiej sprawdza się w sortowaniu dużych zbiorów danych, ułożenie danych w strukturę kopca, powoduje zmniejszenie złożoności obliczeniowej wykonywanych operacji do rzędu O (log n) co daje dużą szybkość. Jest również algorytmem bardzo nie wrażliwym na uporządkowanie danych, co czyni go czasem szybszym niż QuickSort. Sortując w miejscu zapewnia sobie złożoność pamięciową rzędu O(1) co jest najlepszym wyborem. Bardzo ważne również jest to, iż w każdym, a nawet najgorszym wypadku jego złożoność obliczeniowa jest zaledwie liniowo-logarytmiczna. Wady: - niestabilność algorytmu - wymagana określona struktura danych - ograniczony rozmiar zbioru danych (struktura statyczna). - stosunkowo trudna implementacja - dla małych zbiorów danych wolniejszy od QuickSort, ale szybszy niż MergeSort! Zalety: - duża szybkość - bardzo mała wrażliwość na uporządkowanie - dla dużych zbiorów danych, szybszy nawet od QuickSort - wszystkie złożoności obliczeniowe (optymistyczna, pesymistyczna, oczekiwana) takie same i klasy O( n log n) - złożoność pamięciowa jest stała O (1) - sortowanie w miejscu 5

5. Wyniki i pomiary Testy dokonywane były na komputerze o parametrach: Procesor AMD Athlon 64 Processor 3000+ Płyta Główna ASUS K8V-X Pamięć RAM: 512 MB DDR2 Program został skompilowany pod Bloodshed Software Dev-C++ 4.9.9.2 korzystającego z kompilatora MinGW bez optymalizacji. 10 0 58 116 malejace 5 50 78 602 954 malejace 5 100 156 1491 2246 malejace 5 500 1125 10835 15214 malejace 5 1000 2547 24719 33945 malejace 5 5000 15906 157355 209189 malejace 5 10000 34985 344925 453730 malejace 5 50000 207922 2080397 2681608 malejace 5 10 0 62 112 malejace 50 50 78 642 1014 malejace 50 100 172 1535 2328 malejace 50 500 1172 11331 15786 malejace 50 1000 2641 25895 35317 malejace 50 5000 16328 163735 216773 malejace 50 10000 32250 357407 468173 malejace 50 50000 214235 2137401 2749728 malejace 50 10 15 62 124 malejace 100 50 78 678 1052 malejace 100 100 172 1665 2479 malejace 100 500 1203 11733 16297 malejace 100 1000 2750 26357 36092 malejace 100 5000 16985 167049 221466 malejace 100 10000 36844 364099 477887 malejace 100 50000 214641 2171443 2798593 malejace 100 10 0 76 143 rosnace 5 50 78 718 1118 rosnace 5 100 187 1757 2615 rosnace 5 6

500 1281 12455 17312 rosnace 5 1000 2875 27885 38010 rosnace 5 5000 17312 170293 226566 rosnace 5 10000 38172 376905 496394 rosnace 5 50000 226094 2228683 2879485 rosnace 5 10 16 72 135 rosnace 50 50 78 676 1069 rosnace 50 100 171 1677 2517 rosnace 50 500 1265 11967 16724 rosnace 50 1000 3000 27019 36983 rosnace 50 5000 16875 166221 220968 rosnace 50 10000 36829 366091 481735 rosnace 50 50000 217234 2181809 2816948 rosnace 50 10 0 70 126 rosnace 100 50 78 674 1064 rosnace 100 100 172 1629 2431 rosnace 100 500 1203 11719 16282 rosnace 100 1000 2687 26443 36123 rosnace 100 5000 16953 167195 221671 rosnace 100 10000 36328 364321 478220 rosnace 100 50000 220156 2171563 2799039 rosnace 100 10 0 40 83 stale 5 50 47 242 484 stale 5 100 78 553 1061 stale 5 500 422 3411 6078 stale 5 1000 859 6943 12209 stale 5 5000 4547 38367 65029 stale 5 10000 9562 80755 134993 stale 5 50000 59360 528423 824811 stale 5 10 0 60 117 stale 50 50 78 618 980 stale 50 100 156 1395 2152 stale 50 500 1078 10221 14459 stale 50 1000 2360 22631 31417 stale 50 5000 14562 142359 191947 stale 50 10000 31203 309917 412352 stale 50 50000 200062 2001465 2599158 stale 50 10 16 70 128 stale 100 7

50 78 688 1055 stale 100 100 172 1627 2432 stale 100 500 1219 11789 16307 stale 100 1000 2703 26483 36055 stale 100 5000 16860 166979 221355 stale 100 10000 36875 364799 478481 stale 100 50000 214172 2171715 2798431 stale 100 Wykresy: Sortowanie HeapSort dla uporządkowania malejącaego z rozrzutem 5% 3000000 2500000 2000000 czas[ms] 1500000 porownan 1000000 przepisan 500000 0 10 50 100 500 1000 5000 10000 50000 Sortowanie HepaSort dla uporządkowania rosnącego z rozrzutem 50% 3000000 2500000 2000000 czas[ms] 1500000 porownan 1000000 przepisan 500000 0 10 50 100 500 1000 5000 10000 50000 8

Sortowanie HeapSort dla uporządkowania stałego z rozrzutem 100% 3000000 2500000 2000000 czas[ms] 1500000 porownan 1000000 przepisan 500000 0 10 50 100 500 1000 5000 10000 50000 6. Implementacja w języku C++ 1. sorttab.cpp #include "sorttab.h" typedef int FunLos(int &w,int &nie,int i); int n; int wszystkie,niepopr; long lpor,lprzep; FunLos *losuj; int ciag,proc; clock_t pocz,kon; long czas; ofstream f; //plik z wynikami bool otwarty=false; int losujros(int &w,int &nie,int i) if (rand()/(float)rand_max <(float)nie/w--) nie--; return rand()*n/rand_max; return i; int losujst(int &w,int &nie,int i) if (rand()/(float)rand_max <(float)nie/w--) nie--; return rand()*2*n/rand_max; return n; int losujmalej(int &w,int &nie,int i) if (rand()/(float)rand_max<(float)nie/w--) nie--; return rand()*n/rand_max; return w; void ustawparam() cout<<"sortowanie TABLICY "<<endl; 9

cout<<"ile elementow : "; cin >>n; cout<<"jaki ciag: 1-rosnacy, 2-malejacy, 3-staly "; cin>>ciag; cout<< "Podaj procent losowych elementow "; cin >>proc; wszystkie=n;niepopr=(long)n*proc/100; cout << "Uporzadkowanie "; switch (ciag) case 1: cout<<"rosnace ";losuj=losujros;break; case 2: cout<<"malejace ";losuj=losujmalej;break; case 3: cout<<"stale ";losuj=losujst; cout <<"rozrzut "<<proc<<'%'<<endl; int ileelem() return n; void generuj(tab &tab) tab = new int[n]; for(int i=0;i<n;i++) tab[i]=losuj(wszystkie,niepopr,i+1); void kopiuj(tab tab1,tab &tab2) tab2= new int[n]; for (int i=0; i<n;i++) tab2[i]=tab1[i]; void druk() cout << "\rporownan : "<<setw(8)<<lpor <<" przepisan "<<setw(8)<<lprzep; void porown(long k) lpor+=k; druk(); void przep(long k) lprzep+=k;druk(); void start() lprzep=0; lpor=0; pocz=clock(); void stop() kon=clock(); czas=(kon-pocz)*1000/clocks_per_sec; void otworzplik() //przygotowuje plik do zapisu wynikow char nazwa[200]; cout<< "Podaj nazwe pliku "; cin >>nazwa; f.open(nazwa,ios::app); f.seekp(0,ios::end); if (!f.tellp()) f<<"dlugosc czas[ms] porownan przepisan uporzadkowanie rozrzut "<<endl; otwarty=true; void dopliku() f<<setw(6)<<n<<setw(10)<<czas<<setw(9)<<lpor<<setw(10)<<lprzep<<" "; switch (ciag) case 1: f<<" rosnace ";break; case 2: f<<" malejace ";break; 10

case 3: f<<" stale "; f<<setw(8)<<proc<<endl; void zamknijplik() f.close(); otwarty = false; void test(tab tab) int i; for(i=0;i<n-1 && tab[i] <= tab[i+1]; i++); cout <<" CZAS :"<<setw(9)<<czas<<" ms "; if (i==n-1) cout<<" SORT "<<con::fg_green<<" OK "<<con::fg_white<<endl; if (otwarty) dopliku(); else cout<<con::fg_red<<" BLAD "<<con::fg_white<<" SORT "<<endl; void zwolnij(tab &tab) delete [] tab ;tab=null; 2. sorttab.h #ifndef _sorttab_h_ #define _sorttab_h_ #include <fstream> #include <iostream> #include <iomanip> #include <ctime> #include <cstdlib> #include "Console.h" namespace con = JadedHoboConsole; using namespace std; typedef int *Tab; void ustawparam(); //dlug, rodzaj ciagu, losowosc int ileelem(); //dlugosc ciagu void generuj(tab &tab); //wypelnia tablice void kopiuj(tab tab1,tab &tab2); //tworzy kopie dla drugiego alg void porown(long k); //dolicza i wypisuje porownania void przep(long k); //dolicza i wypisuje przepisania void start(); //start stopera void stop(); //stop stopera void otworzplik(); //przygotowuje plik do zapisu wynikow void zamknijplik(); void test(tab tab); //sprawdza poprawnosc sortowania + zapis void zwolnij(tab &tab); //zwalnia pamiec tablicy #endif 11

3. HeapSort.cpp #include "sorttab.h" using namespace std; // Zmienne globalne // Funkcje Tab tab, tab1; void przywroc(int T[], int k, int n) // "Max-Heapify" funkcja przywracajaca tablicy wlasnosc kopca int i,j; i = T[k-1]; przep(1); while (k <= n/2) porown(1); j=2*k; przep(1); if((j<n) && ( T[j-1]<T[j]) ) porown(2); j++; przep(1); if (i >= T[j-1]) porown(1); break; else porown(1); T[k-1] = T[j-1]; k=j; przep(2); T[k-1]=i; przep(1); void heapsort(int T[], int n) // algorytm sortowania przez kopcowanie, Heap Sort int k, swap; przep(1); for(k=n/2; k>0; k--) // zbuduj kopiec porown(1); przep(1); przywroc(t, k, n); do // sortuj - rozbieraj kopiec i przywracaj mu własność kopca po każdym zdjętym elemencie. 12

porown(1); swap=t[0]; T[0]=T[n-1]; T[n-1]=swap; n--; przep(4); przywroc(t, 1, n); while (n > 1); int main() cout << con::fg_white <<"\t\t\t Heap Sort v. 1.0\n\n\n"; long int a=0; cout << "Ile testow chcesz przeprowadzic?:"; cin >> a; otworzplik(); for (int j=0; j<a; j++) unsigned int seed=time(null); cout <<seed<<endl; srand(seed); // losowy; srand(0) - powtarzalny ustawparam(); //wybor rodzaju ciagu i jego dlugosci generuj(tab); //utworzenie tablicy //for(int i =0; i<ileelem(); i++) cout<<tab[i]<<' '; cout << endl; start(); //start pomiaru czasu heapsort(tab, ileelem()); stop(); //zatrzymanie stopera test(tab); //sprawdzenie poprawnosci sortowania i zapis do pliku zwolnij(tab); // zwolnienie pamieci cout << "\n\n"; zamknijplik(); cout << con::bg_red <<"\n\nautor: Wojciech Podgorski\n\n" << con::bg_black; system("pause"); 7. Bibliografia 1. Cormen T., Leiserson C. E., Rivest R.L., Wprowadzenie do algorytmów, WNT Warszawa 1997. 2. Wróblewski P., Algorytmy, struktury danych i techniki programowania, Helion, Gliwice 1996. 3. Sedgewick R., Algorytmy w C++, Addison, Wesley, RM, Warszawa 1999. 13