Wykład 10 typ zbiorowy rekurencja
Typ zbiorowy type nazwa_typu = set of typ_porządkowy ; Typ zbiorowy to zbiór potęgowy danego typu porządkowego, czyli zbiór wszystkich podzbiorów tego typu. Zmienna tego typu może zatem zawierać zbiór pusty, jedno- lub wieloelementowy. Definicja typu zbiorowego: type nazwa_typu = set of typ_porządkowy ; typ zbiorowy typ bazowy Liczba elementów nie może przekraczać 256 – czyli typ bazowy może być: typem Byte, okrojonym całkowitym, znakowym (w tym okrojonym) wyliczeniowym logicznym Zmienna typu zbiorowego zawierać może dowolny podzbiór elementów typu bazowego, od zbioru pustego do zbioru zawierającego wszystkie elementy.
Przykłady definicji typu zbiorowego: type dni = set of (pon,wto,sro,czw,pia,sob,nie) ; znaki = set of 'a'..'z' ; miesiac = (sty,lut,mar,kwi,maj,cze,lip,sie,wrz,paz,lis,gru) ; zbior_miesiecy = set of miesiac ; var nazwa_miesiaca : miesiac ;//zmienna typu wyliczeniowego zbior_nazw : zbior_miesiecy ; //zmienna typu zbiorowego UWAGA: nazwa_miesiaca może przyjąć wartość tylko jednej z nazw – typ wyliczeniowy; zbior_nazw może przyjąć wartość dowolnego podzbioru z nazw bazowych – typ zbiorowy
Operacje logiczne wykonywane na zbiorach to relacje (porównania): Zmiennych typu zbiorowego nie wolno używać w instrukcjach czytania i wyprowadzania wyników, używa się ich jedynie w operacjach wykonawczych, testujących itp. Operacje logiczne wykonywane na zbiorach to relacje (porównania): a = b równość zbiorów, te same elementy w obu zbiorach, a < > b różność zbiorów, różne elementy w obu zbiorach (chociaż niektóre mogą się powtarzać) a <= b zawieranie zbioru a w zbiorze b (true jeśli każdy element zbioru a jest w zbiorze b) a >= b zawieranie zbioru b w zbiorze a (true jeśli każdy element zbioru b jest w zbiorze a) c in a czy element c jest w zbiorze a
Stałe typu zbiorowego [lista wartości podzbioru] np. [1, 5, 7], Wartości stałych typu zbiorowego zapisujemy w nawiasach kwadratowych w postaciach: [lista wartości podzbioru] np. [1, 5, 7], [okrojenie ze zbioru] np. [1..3], lub łącznie: np. [1..3, 5, 7],
Przykłady: type miesiace = set of 1..12 ; var v, x, y, z: miesiace ; lit: char ; begin x :=[1..12] ; {cały rok} y := [1..6] ; {pierwsze półrocze} z := [1, 3, 5 , 7 , 8, 10, 12] ; {miesiące posiadające 31 dni} lit := 'a' ; if x<>y then Edit1.Text:='tak' else Edit1.Text:='nie'; {tak} if x<=y then Edit1.Text:='tak' else Edit1.Text:='nie'; {nie} if x>=y then Edit1.Text:='tak' else Edit1.Text:='nie' ; {tak} if x = y then Edit1.Text:='tak' else Edit1.Text:='nie'; {nie} if 1 in x then Edit1.Text:='tak' else Edit1.Text:='nie'; {tak} if 9 in z then Edit1.Text:='tak' else Edit1.Text:='nie' ; {nie} if lit in ['a'..'z'] then Edit1.Text:='tak' else Edit1.Text:='nie';{tak} end ; type x=(alfa, beta, gamma, delta) ; {typ wyliczeniowy} var z : set of x ; begin z := [alfa, beta] ; {lista - wybór podzbioru alfa, beta} z := [alfa..gamma] ; {okrojenie - wybór podzbioru alfa, beta, gamma} end;
iloczyn zbiorów (część wspólna zbiorów) Operatory działań na zmiennych typu zbiorowego (znaczenie jak w teorii mnogości): + suma zbiorów – różnica zbiorów a i b - zbiór złożony z tych elementów zbioru a, które nie należą do b iloczyn zbiorów (część wspólna zbiorów) Przykład: type zbiorowy = set of 1..6 ; var x , y, v : zbiorowy ; begin x :=[2, 3, 4] + [4, 5, 6] ; {wynik [2,3,4,5,6] } y := [2, 3, 4] - [4, 5, 6] ; {wynik [2,3] } v := [2, 3, 4] * [4, 5, 6] ; {wynik [4] (część wspólna) } y := v * x ; { przeanalizować wynik} end .
xn = Algorytmy rekurencyjne Wiele problemów obliczeniowych można zdefiniować rekurencyjnie. Rekurencja oznacza takie zdefiniowanie zagadnienia, gdzie w trakcie formułowania definicji odwołujemy się do niej samej. Przykładem definicji rekurencyjnej może być zapis całkowitej, nieujemnej potęgi rzędu n liczby rzeczywistej x: xn-1*x dla n > 0 (tu użycie definiowanej potęgi) xn = 1 dla n = 0
Rekurencja w językach programowania jest realizowana za pomocą podprogramów wywołujących kolejno same siebie ze zmienianymi parametrami wywołania. Aby podprogramy rekurencyjne działały poprawnie powinny zawierać warunek zakończenia rekurencji, aby wywołanie wykonywane było skończoną liczbę razy. Rekurencja daje proste programy lecz ma także wadę: każde wywołanie podprogramu wymaga wykonania przez procesor dodatkowych czynności, co spowalnia działanie programu oraz powoduje odłożenie na stos systemowy dużej liczby danych.
function potega_n (x:real ; n:integer):real ; begin { funkcja wyznacza n-tą potęgę n dla liczby x } begin if n=0 then result := 1 else result := potega_n (x, n – 1)*x ; {w definicji funkcji wykorzystanie tejże funkcji} end ; var x:real; begin {program główny} x:= potega_n (2,10) ; {obliczenie 210}
function silnia_x (x: integer): longint ; function silnia_x (x: integer): longint ; {zastosowano typ longint ze względu na duże wartości funkcji silnia} begin if x = 1 then result := 1 else result := silnia_x(x-1)*x ; end ; //przykładowe użycie var alfa : integer ; alfa:=StrToInt(Edit1.Text); Memo1.Lines.Add( 'Silnia wynosi:'); Memo1.Lines.Add( IntToStr(silnia_x(alfa))); end;