Informatyka w roku szkolnym 2006/07 w klasie 1A
Celem tych zajęć jest nauczenie Was posługiwania się komputerem do efektywnego rozwiązywania zadań obliczeniowych. Na lekcjach będą omawiane zarówno metody (algorytmika) jak i narzędzia (język C++).
Organizacja zajęć
Terminy
- lekcje: środa 9:50-11:30 s.215
- obozy naukowe: ...
Nauczyciele
- Krzysztof Loryś
- Paweł Rzechonek
- Dawid Matla
Materiały
Oceny
Zasady zaliczenia przedmiotu opierają się na systemie punktowym. Punkty można uzyskiwać za:
- sprawdziany
- aktywność na zajęciach
- rozwiązywanie zadań domowych
- udział w zawodach programistycznych
Lekcje
- 14.02.2007:
- Wskaźniki i operacje na wskaźnikach. Tworzenie i usuwanie obiektów ze sterty.
- 21.02.2007:
- Listy; operacje wstawiania i usuwania elementów na początku i na końcu listy; przeglądanie listy.
- 28.02.2007:
-
Listowa reprezentacja grafu.
Sortowanie topologiczne.
Sprawdzian:
Dane: krzyżówka o rozmiarach w×k zapisana w tablicy 2-wymiarowej (czarne pola mają wartość 0 a białe 1).
Zadanie: wyznacz pozycję i długość najdłuższego hasła w tej krzyżówce (należy podać współrzędne pola początkowego, długość hasła i kierunek poziomo/pionowo). - 14.03.2007:
-
Wykorzystanie list do pamiętania danych.
Sprawdzian:
Dane: przedział liczbowy <a,b> oraz liczby x i y; można założyć, że wszystkie liczby są naturalne oraz 1≤a≤b≤2000000000 i 1<x,y<40000.
Zadanie: podać, ile jest liczb w przedziale <a,b>, które są podzielne przez x lub przez y.
Wersja trudniejsza: mamy nie dwie liczby ale trzy - x, y i z. - 21.03.2007:
-
Drzewa BST.
Sprawdzian:
Dane: n liczb naturalnych x1...xn, gdzie 3≤n≤2000000000.
Zadanie: należy sprawdzić, czy wśród tych liczb jest taka trójka, która nie spełnia nierówności trójkąta.
Przypomnienie: trójka liczb a, b i c spełnia nierówność trójkąta, gdy a+b>c ∧ a+c>b ∧ b+c>a. - 28.03.2007:
-
Drzewa BST.
Sprawdzian:
Dane: wskaźnik head do pierwszego elementu listy z liczbami całkowitymi.
Zadanie: należy odwrócić kolejność elementów na liście.
Uwaga: należy zaprogramować procedurę, która po odwróceniu wskaźników na liście jednokierunkowej zwróci wskaźnik na początek zmodyfikowanej listyNode * odwrocenie (Node *pocz);
działanie procedury należy sprawdzić w funkcji main() następującoNode *pocz = NULL; // ... wpisanie danych na listę wypisz(pocz); pocz = odwrocenie(pocz); wypisz(pocz);
- 4.04.2007:
-
Drzewa BST.
Sprawdzian:
Dane: liczba naturalna K (K>1) oraz ciąg N (2<N<106) liczb A = (a0, a1,... aN-1) uporządkowanych rosnąco a0 < a1 < ... < aN-1.
Zadanie: należy wyznaczyć liczbę różnych par elementów ai i aj, które sumują się do K (ai+aj = K), przy czym 0≤i<j<N. - 11.04.2007:
-
Operacje bitowe.
Sprawdzian:
Dane: trójkąt prostokątny o całkowitych długościach boków 0 < a, b, c ≤ N ≤ 104, takich że a2 + b2 = c2.
Zadanie: należy wyznaczyć długości boków a i b wiedząc, że a jest największą możliwą wartością. - 18.04.2007:
-
Kopiec.
Sprawdzian:
Dane: 32-bitowa liczba całkowita bez znaku x oraz parametr całkowity k (0≤k≤32).
Zadanie: w liczbie x należy odwrócić k najmniej znaczących bitów.
Przykład: niech x = 3910 = (0...0111101000110)2; i k = 10; wtedy po odwróceniu 10 ostatnich bitów w liczbie 3910 dostaniemy wartość 3467 = (0...0110110001011)2. - 25.04.2007:
-
Kopiec.
Sprawdzian:
Dane: n-elementowy kopiec 8-arny, gdzie n≥1.
Zadanie: jak taki kopiec włożyć do tablicy i jak należy wyliczać indeksy ojca i każdego spośród ośmiu synów dla zadanego elementu? - 09.05.2007:
-
Mnożenie długich liczb.
Dane są dwie liczby naturalne o dużej liczbie cyfr (na przykład kilka tysięcy). Zadanie polega na obliczeniu iloczynu tych liczb. Załóżmy, że obie liczby A=(an-1an-2...a0) i B=(bn-1bn-2...b0) są tej samej długości n, gdzie n jest naturalną potęgą liczby 2.
Rozważmy najpierw metodę mnożenia pisemnego. Jedną liczbę mnożymy po kolei przez wszysytkie cyfry drugiej liczby, wyniki przesuwamy o odpowiednią liczbę pozycji w lewo (mnożenie przez potęgi 10 lub dopisywanie zer na końcu) i sumujemy. Koszt takiego mnożenia to Θ(n2), ponieważ każdą cyfrę z jednej liczby musimy przemnożyć przez każdą cyfrę z drugiej.function mnozenie_pisemne (n, A, B) { C := 0; while A>0 do { j := A mod 10; // ostatnia cyfra z bieżącego A C := C+j*B; // pomnożenie B przez liczbę jednocyfrową B := B*10; // dopisujemy cyfrę 0 na koniec B A := A/10; // obcinamy ostatnią cyfrę z A } return C; }
Podejście w stylu "dziel i zwyciężaj" to rozbicie obu liczb na cztery mniejsze o połowę i wykonywanie działań na mniejszych danych.
A = A1*10n/2 + A0
B = B1*10n/2 + B0
Załóżmy, że wynikiem mnożenia będzie liczba C = A*B, którą teraz można zapisać w następującej postaci:
C = (A1*10n/2+A0)(B1*10n/2+B0) = (A1*B1)*10n + (A0*B1+A1*B0)*10n/2 + (A0*B0)*100
Gdybyśmy zaimplementowali bezpośrenio obliczenia z tego wzoru, to otrzymalibyśmy funkcję rekurencyjną, której czas działania byłby tak jak poprzednio rzędu Θ(n2) - przyczyną jest czterokrotne wywołanie rekurencyjnej procedury mnożącej dane o połowę mniejsze. Aby przyspieszyć mnożenie należy zastosować trik, który zmniejszy liczbę rekurencyjnych wywołań procedury do trzech:
R = (A1+A0)*(B1+B0)
S2 = A1*B1
S0 = A0*B0
S1 = R-S2-S0
Liczby S2, S1, S0 odpowiadają współczynnikom przy potęgach 10 z poprzedniego wzoru. Koszt tak zmodyfikowanego mnożenia wynosi teraz Θ(nlog 3) ≈ Θ(n1.585).function mnozenie_dzielzwyc (n, A, B) { if n=1 then oblicz wynik ad-hoc mnożąc dwie cyfry else { A0 := A mod 10n/2; A1 := A div 10n/2; B0 := B mod 10n/2; B1 := B div 10n/2; R := mnozenie_dzielzwyc (n/2, A1+A0, B1+B0); // uwaga na przeniesienia w dodawaniu S2 := mnozenie_dzielzwyc (n/2, A1, B1); S0 := mnozenie_dzielzwyc (n/2, A0, B0); S1 := R-S2-S0; return S2*10n+S1*10n/2+S0; } }
- 16.05.2007:
- Sortowanie szybkie.
- 23.05.2007:
-
Wyszukiwanie binarne.
Sprawdzian:
Dane: n-elementowa nieuporządkowana tablica liczb A[0...n-1], gdzie n≥2.
Zadanie: należy dokonać podziału tej tablicy względem dwóch różnych piwotów x i y wybranych losowo z tablicy A; następnie trzeba wydrukować zawartość tablicy po podziale i wypisać ile jest elementów <x i >y. - 30.05.2007:
-
Drzewiaste struktury danych dla zbiorów rozłącznych.
Dany jest zbiór S = {e1, e2, ..., en} zawierający n różnych elementów oraz rodzina n jednoelementowych rozłącznych zbiorów S1, S2, ..., Sn pokrywająca zbiór S (początkowo Si = {ei} dla i=1,2,...,n). Dany jest też ciąg m operacji union i find. Zadanie polega na efektywnej realizacji ciągu tych instrukcji.
Zadania
- 14.03.2007: sortowanie topologiczne wierzchołków w grafie
-
Dany jest graf skierowany D=(V,E) o n=|V| wierzchołkach
(wierzchołki są numerowane od 0 do n-1) i m=|E|
krawędziach.
Należy wypisać te wierzchołki w takiej kolejności, aby dla każdej krawędzi
(u,v)∈E wierzchołek o numerze u występował przed
v; jeśli nie można w taki sposób posortować krawędzi, to wypisz
pojedynczą wartość -1 (wypisywanie wierzchołków można traktować jak
ich numerowanie).
Uwaga! Dane do programu wczytaj ze standardowego wejścia cin a wyniki zapisz na standardowym wyjściu cout. Dane wejściowe mają następującą postać:n m u1 v1 u2 v2 ... um vm
Algorytm, który rozwiązuje ten problem można następująco opisać:
(1) tworzymy reprezentację grafu w postaci list sąsiadów (od razu podczas czytania danych wejściowych);
(2) wyliczamy stopień wejściowy dla każdego wierzchołka (to także można zrobić podczas czytania danych wejściowych);
(3) na liście GDW wierzchołków gotowych do wypisania umieszczamy wszystkie wierzchołki o stopniu wejściowym =0 (są one dobrymi kandydatami na nadanie im najmniejszych numerów, bo nie mają żadnych poprzedników); tworzymy też pustą listę WKT wierzchołków w kolejności topologicznej;
(4) dopóki na GDW są jakieś wierzchołki powtarzamy operacje:
(4a) wyciągnij dowolny wierzchołek v z listy GDW (może być pierwszy),
(4b) zmniejsz stponie wejściowe o 1 wszystkim sąsiadom wierzchołka v (to tak jakbyśmy usuwali go z grafu),
(4c) wstaw wierzchołek v na początek listy wynikowej WKT (ostatnio wstawiony będzie miał największy numer);
(5) jeśli na liście WKT znajduje się n=|V| wierzchołków, to wypisz je w odwrotnej kolejności, w przeciwnym przypadku wypisz liczbę -1 (nie ma rozwiązania).
Wskazówka! Do zapamiętania grafu wykorzystaj reprezentację listową.
- 21.03.2007: optymalna trasa przez góry
-
Na mapie mamy zaznaczone dwa punkty i prostą, która przez nie przechodzi.
Wzdłuż tej prostej należy poprowadzić linię energetyczną.
Wyznacz jaka jest minimalna liczba słupów, które należy umieścić pomiędzy
docelowymi punktami, aby kabel nie leżał na ziemi.
Wysokości wszystkich przeszkód odczytujemy na podstawie poziomic.
Odległości przeszkód są liczone od pierwszego punktu.
Uwaga! Dane do programu wczytaj ze standardowego wejścia cin a wyniki zapisz na standardowym wyjściu cout. Dane to liczba n oraz n+1 punktów na mapie postaci (di,hi), gdzie di to odległość od pierwszego punktu a hi) to wysokość przeszkody (pierwszy i ostatni punkt to punkty docelowe). Dane wejściowe mają następującą postać:n 0 h0 d1 h1 d2 h2 ... dn hn
Przykładowe dane z lekcji:11 0 10 1 12 2 20 3 17 4 13 5 19 6 18 7 11 8 16 9 15 10 14 11 10
Odpowiedzią powinna być liczba 3 (pomiędzy punktem 0-wym i 11-tym należy postawić trzy słupy w punktach 2, 5 i 10).
Wskazówka! Do zapamiętania danych wykorzystaj listę jednokierunkową.
- 28.03.2007: przeglądanie drzewa BST
-
Napisz program, który umieści w drzewie BST n liczb całkowitych
(rekurencyjna procedura wstawiająca była dokładnie omówiona na lekcjach).
Na końcu program powinien wypisać inorder zawartość drzewa.
Uwaga! Dane do programu wczytaj ze standardowego wejścia cin a wyniki zapisz na standardowym wyjściu cout. Dane to liczba n oraz n liczb całkowitych x1...xn. Dane wejściowe mają następującą postać:n x1 ... xn
Odpowiedzią powinien być ciąg liczb wypisanych w porządku niemalejącym.
Wskazówka! Napisz rekurencyjną procedurę wypisującą zawartość drzewa BST.
- 4.04.2007: wstawianie i usuwanie z drzewa BST
-
Napisz program, który umieści w drzewie BST n liczb całkowitych,
a potem usunie z niego m wartości (o ile są zapamiętane w drzewie).
Na końcu program powinien wypisać inorder zawartość drzewa.
Uwaga! Dane do programu wczytaj ze standardowego wejścia cin a wyniki zapisz na standardowym wyjściu cout. Dane to liczby n i m oraz n liczb całkowitych x1...xn do wstawienia i m wartości całkowitych y1...ym które trzeba usunąć z drzewa. Dane wejściowe mają następującą postać:n m x1 ... xn y1 ... ym
Odpowiedzią powinien być ciąg liczb wypisanych w porządku niemalejącym.
Wskazówka! W przypadku usuwania węzła wewnętrznego, który posiada dwa niepuste poddrzewa, zastosuj jedną z technik omówionych na lekcji (i) przeniesienia w mijsce usuwanego elementu maksimum z lewego poddrzewa (albo minimum z prawego) lub (ii) podczepienia jednego poddrzewa do drugiego.
- 11.04.2007: liczba różnych drzew BST
-
Jak wyliczyć liczbę Cn różnych drzew BST składających się
z n węzłów?
Uwaga! Dla n=0 (drzewo puste) i dla n=1 (drzewo jednoelementowe) C0 = C1 = 1, bo tylko w jeden sposób można takie drzewo zbudować.
Wskazówka! Rozważ na ile sposobów można zbudować drzewo BST, które ma k węzłów w lewym poddrzewie oraz n-1-k w prawym.
Wskazówka! Zapoznaj się z definicją i wzorami na liczby Catalana.
- 18.04.2007: odwracanie bitów w słowie
-
Przez odwrócenie kolejności bitów w 32-bitowym słowie typu int
należy rozumieć wykonanie lustrzanego odbicia (pierwszy bit ma się znaleźć
na ostatniej pozycji, drugi na przedostatniej,... a ostatni na pozycji
pierwszej), na przykład odwrócenie 8-bitowego słowa 01001111 to
11110010.
Odwrócenie bitów w słowie (operacja rev(int)) może zostać wykonane
w stosunkowo wydajny sposób przez zamianę kolejności sąsiadujących bitów,
następnie zamieniamy ze sobą sąsiadujące pary bitów, itd, a na końcu
zamieniamy miejscami obydwie połówki słowa.
Dane do programu to pojedyncza liczba całkowita x. W wyniku należy wypisać liczbę rev(x).
Uwaga! Napisz odpowiednią funkcję odwracającą bity, która wykorzystuje do obliczeń tylko operacje bitowe i wykonuje tylko pięć podstawień (5=log(32)).
Wskazówka! Zastosuj technikę dziel i zwyciężaj ale bez rekurencji.
- 25.04.2007: kopce d-arne
-
Na ostatniej lekcji był omawiany kopiec binarny włożony do tablicy.
Uogólnij pojęcie kopca na kopiec d-arny dla dowolnego d≥2.
Jak taki kopiec włożyć do tablicy i jak potem wyliczać indeksy ojca
i każdego spośród d synów dla zadanego elementu.
Zilustruj działanie twoich metod na przykładzie kopców 3-arnych i 4-arnych.
Wskazówka! Użyj tablicy indeksowanej od 0.
Uwaga! Przygotuj rozwiązanie w formie pisemnej (wzory z uzasadnieniem).
- 9.05.2007: sortowanie z wykorzystaniem kopca
-
Danych jest k<1 posortowanych ciągów A1, ...,
Ak o długościach odpowiednio n1, ...,
nk.
Elementy ze wszystkich ciągów należy wypisać w kolejności od najmniejszego
do największego (elementów tych jest n = n1n1 +
... + nk).
Uwaga! Dane do programu wczytaj ze standardowego wejścia cin a wyniki zapisz na standardowym wyjściu cout. Dane wejściowe mają następującą postać:k n1 A1[1] ... A1[n1] n2 A2[1] ... A2[n2] ... nk Ak[1] ... Ak[nk]
Odpowiedzią powinien być ciąg liczb wypisanych w porządku niemalejącym.
Wskazówka! Użyj kopca, którego elementy będą posortowanymi listami (kluczem powinien być pierwszy, czyli najmniejszy, element na liście). Na szczycie takiego kopca powinien się znajdować element minimalny.
- 16.05.2007: wydajność różnych algorytmów mnożenia długich liczb
-
Dane są dwie długie liczby naturalne A i B o takich samych
długościach n zapisane w systemie dziesiętnym, gdzie n jest
naturalną potęgą 2.
Zadanie polega na pomnożeniu ich metodą pisemną oraz za pomocą
algorytmu "dziel i zwyciężaj", porównaniu czy wyniki
procedur są zgodne i zmierzeniu czasów działania obu funkcji.
Uwaga! Dane do programu wczytaj ze standardowego wejścia cin a wyniki zapisz na standardowym wyjściu cout. Dane wejściowe mają następującą postać:n an-1an-2...a1a0 bn-1bn-2...b1b0
Odpowiedzią powinny być dwie (2n)-cyfrowe liczby będące iloczynem liczb wejściowych (pierwsza z nich pochodzi z mnożenia pisemnego a druga z algorytmu "dziel i zwyciężaj").
Wskazówka! Przekształć dane w taki sposób, aby liczba była pamiętana od najmniej znaczącej cyfry (liczba jedności powinna się zatem znaleźć w pierwszej komórce tablicy [0]). Dodatkowo, aby ułatwić sobie mnożenie, pojedyncze cyfry pamiętaj binarnie (znak '0' przekształć na znak o kodzie 0, itd).
- 30.05.2007: najdłuższy podciąg rosnący
-
Dany jest ciąg n liczb naturalnych A = (a0,
a1,,,, an-1).
Zadanie polega na znalezieniu długości najdłuższego podciągu rosnącego
w ciągu A (w wersji trudniejszej oprócz długości należy wypisać jeden
z takich ciągów).
Uwaga! Dane do programu wczytaj ze standardowego wejścia cin a wyniki zapisz na standardowym wyjściu cout. Dane wejściowe mają następującą postać:n a0 a1 ... an-1
Odpowiedzią powinna być długość najdłuższego podciągu rosnącego w ciągu A (w wersji trudniejszej należy jeszcze wypisać jeden z takich ciągów).
- 6.06.2007: spójne składowe w grafie
-
Dany jest graf G=(V,E).
Zadanie polega na wyznaczeniu spójnych składowych w tym grafie.
Uwaga! Skorzystaj z operacji na zbiorach rozłącznych.
Notatki
Pomiar czasu wykonania fragmentu kodu programu w języku C
// będziemy korzystać z funkcji zadeklarowanych w <ctime> # include <ctime>
// pomiar czasu działania clock_t start = clock(); // odczytujemy czas na początku /* tu jest fragment kodu, którego czas działania należy zmierzyć */ clock_t stop = clock(); // odczytujemy czas na końcu double dt = (double)(stop-start)/CLOCKS_PER_SEC; // wyznaczamy upływ czasu w sekundach
Drzewa BST
Węzeł drzewa BST to obiekt, który pamięta jakąś informację (pole info) oraz wsakźniki do lewego i prawego poddrzewa (pola left i right). Pole info może być prostą wartością albo mieć skomplikowaną strukturę, jednak jego najważniejszą cechą jest możliwość porównywania z innymi obiektami tego samego typu. W naszym przykładzie używamy pola całkowitoliczbowego int.
// struktura pojedynczego węzła w drzewie BST struct Node { int info; Node *left, *right; // konstruktor do inicjalizacji nowego węzła Node (int val) { info = val; left = right = NULL; } };
Wstawianie do drzewa BST (operacja insert) polega na przejściu od korzenia aż do pierwszego wolnego miejsca za liściem - tam umieszcza się nowy węzeł z kolejnym elementem pamiętanego zbioru. Są różne sposoby realizacji takiej procedury; ta zaprezentowana poniżej jest rekurencyjna (jej rezultatem jest wskaźnik do nowego węzła lub do zmodyfikowanego drzewa).
// funkcja wstawiająca nowy węzeł do drzewa BST Node * insert (Node *node, int val) { if (!node) return new Node(val); if (val<node->info) node->left = insert(node->left,val); if (node->info<val) node->right = insert(node->right,val); return node; }
Wygodnie jest zobaczyć jak wygląda struktura drzewa BST po wykonaniu na niej określonej operacji (wstawienie lub usunięcie). Poniższa procedura "rysuje w trybie tekstowym" obrócone i odbite drzewo binarne. Można tej procedury używać do testowania własnych funkcji działających na drzewach BST.
// drukowanie struktury drzewa BST void print (Node *node, int level=0, int patern=0, bool dir=false) { if (!node) return; print(node->left,level+1,patern|(level&&dir?(1<<level):0),false); for (int l=level, p=patern; l-->0; p>>=1) cout<<(p&1?"| ":" "); cout<<"+--("<<node->info<<")"<<endl; print(node->right,level+1,patern|(level&!dir?(1<<level):0),true); }
Kopce binarne
Kopiec binarny jest binarnym drzewem zupełnym, w którego węzłach są
pamiętane elementy w porządku kopcowym.
Drzewo binarne o wysokości h>0 jest zupełne, gdy: (i) wszystkie jego
liście leżą na głębokości h lub h-1; (ii) wszystkie liście
z poziomu h-1 leżą na prawo od wszystkich węzłów wewnętrznych z tego
poziomu; (iii) wszystkie węzły wewnętrzne mają po dwóch synów za wyjątkiem
położonego najbardziej na prawo węzła wewnętrznego na poziomie h-1,
który może mieć jednego lewego syna.
W drzewie binarnym jest zachowany porządek kopcowy, gdy element w każdym węźle
wewnętrznym jest nie mniejszy od kluczy w jego synach i dalszych potomkach.
Kopiec n-elementowy można efektywnie pamiętać w n-elementowej
tablicy H[1…n].
Korzeń kopca jest pamiętany w H[1]; węzły z poziomu k-tego
pamiętane sa kolejno od lewej do prawej strony na pozycjach
H[2k…2k+1-1].
Ojciec węzła pamiętanego w H[i] znajduje się na pozycji H[i/2]
a jego lewy i prawy syn odpowiednio na pozycjach H[2i] i H[2i+1].
// indeksy ojca i synów inline int parent (int i) { return i>>1; } inline int left (int i) { return i<<1; } inline int right (int i) { return (i<<1)&1; }
Elementy pamiętane w kopcu są poukładane w taki sposób, że przechodząc dowolną
ścieżką od korzenia do liścia będziemy odwiedzali je w porządku nie malejącym.
Załóżmy, że mamy zbudowany w tablicy kopiec n-elementowy, oraz że na
i-tej pozycji zmieniamy pamiętaną tam wartość x na mniejszą lub
większą x'.
Wówczas porządek kopcowy może zostać zaburzony i trzeba go będzie przywrócić
poprzez przesiewanie elementu w górę kopca (gdy wartość zostanie zwiększona)
lub w dół kopca (gdy wartość zostanie zmniejszona).
Oto obiektowa definicja kopca z ostatnich zajęć:
// Heap jest kopcem o określonej na początku pojemności i zadanej funkcji porównującej class Heap { private: int max; // maksymalna liczba elementów w kopcu int n; // bieżąca liczba elementów w kopcu TYPE *heap; // wskaźnik do tablicy z kopcem bool (*cmp)(const TYPE &x, const TYPE &y); // funkcja porównująca elementy private: int left (int i) { return i<<1; } int right (int i) { return i<<1|1; } int parent (int i) { return i>>1; } public: // konstruktor Heap (int max, bool (*cmp)(const TYPE &x, const TYPE &y)) { if (max<=0) throw exception(); this->max = max; n = 0; heap = new TYPE[max+1]; this->cmp = cmp; } // destruktor ~Heap () { delete[] heap; } private: // zamiana elementów w kopcu void exchange (int i, int j) { TYPE x = heap[i]; heap[i] = heap[j]; heap[j] = x; } // przesiewanie w górę void sift_up (int i) { int p=parent(i); if (p==0) return; if (cmp(heap[p],heap[i])) return; exchange(p,i); sift_up(p); } // przesiewanie w dół void sift_down (int i) { int l=left(i), r=right(i), c; if (l>n) return; if (l<n) c = cmp(heap[l],heap[r])?l:r; else c = l; if (cmp(heap[i],heap[c])) return; exchange(i,c); sift_down(c); } public: // stawienie nowego elementu do kopca void insert (TYPE x) { if (n==max) throw exception(); heap[++n] = x; sift_up(n); } // pobranie wartości ze szczytu kopca TYPE top () { if (n==0) throw exception(); return heap[1]; } // usunięcie elementu ze szczytu kopca TYPE extract_top () { if (n==0) throw exception(); TYPE x=heap[1]; heap[1] = heap[n--]; sift_down(1); return x; } public: // pojemność kopca int capacity () { return max; } // liczba elementów w kopcu int size () { return n; } // wartość i-tego elementu kopca umieszczonego w tablicy TYPE operator[] (int i) { if (i<1||i>n) throw exception(); return heap[i]; } };
Ogłoszenia
- 29.03.2007
- Proszę wszystkich uczniów o nadesłanie zaległych zadań domowych!!!