Увод PASCAL Динамичке структуре података Статичка алокација меморије: Величина података ињихова адреса умеморији (релативнa уодносу на почетак програма) морају бити познати за време превођења програма Унапред се мора предвидети максималан капацитет неког низа Било каква измена капацитета захтева поновно превођење програма Углавном се алоцира више меморије него што је то је то најчешће потребно Ограничена примена уз низ недостатака Програмирање 1, ЕТФ 2011 1/33 Програмирање 1, ЕТФ 2011 2/33 Увод Динамичка алокација меморије Величина појединачних података идаље мора бити позната за време превођења Адресе појединачних података, као ињихов број не морају бити познати унапред Меморија се алоцира по потреби, амаксимално колико дозвољава оперативни систем Манипулација динамичком алокацијом меморије захтева већи напор програмера уодносу на статичку програмер је одговоран за захтевање (алоцирање) меморије програмер је одговоран за ослобађање алоциране меморије Показивачи Програмер помоћу посебних инструкција тражи да му се додели меморијски простор Адресе додељеног меморијског простора се памте упосебним променљивим које се називају показивачи Показивачи су променљиве чија вредност представља адресу неког податка умеморији Могу се дефинисати показивачи на било које типове података На пример, показивач на integer: TYPE pokint = ^integer; Програмирање 1, ЕТФ 2011 3/33 Програмирање 1, ЕТФ 2011 4/33
Показивачи Пример коришћења показивача Показивачи Шта се дешава умеморији у време извршавања програма? a pa 5 1B3Ch? PROGRAM primer(input, output); TYPE VAR END. pokint = ^integer; a : integer; pa : pokint; new(pa); { vrsi alokaciju memorije } readln(input, a); pa^ := a; { pristup memoriji na koju pokazuje pa } writeln(output, pa^); dispose(pa); { oslobadja alociranu memoriju } new(pa); readln(a); pa^ := a; dispose(pa); систем додељује меморију (величине једног integer) прочита се нека вредност (на пример 5). оно на шта показује ра добија вредност а. систему се враћа меморија тако да систем може да је додели неком другом. Од овог тренутка ра не сме да се користи!!! за индиректно адресирање (док се не промени његова вредност) 1B3Ch 5 Програмирање 1, ЕТФ 2011 5/33 Програмирање 1, ЕТФ 2011 6/33 Уланчане листе Уланчане листе Уланчане листе представљају једноставну структуру података која омогућава формирање низа елемената произвољне дужине Почетак листе (показивач) подаци Показивач на следећи елемент подаци Показивач на следећи елемент подаци Показивач на следећи елемент произвољан број пута... подаци Показивач на следећи елемент nil За реализацију листе је неопходно знати адресу првог елемента листе. Она се памти упоказивачу који се обично зове глава или почетак листе За ефикасну реализацију разних операција над листом, пожељно је памтити показивач на последњи елемент листе ( реп листе) Операције над листом Пролазак кроз листу Додавање елемента листи (на почетку, у средини, на крају) Избацивање елемента из листе (са почетка, из средине, са краја) Брисање листе (своди се на претходни случај) Програмирање 1, ЕТФ 2011 7/33 Програмирање 1, ЕТФ 2011 8/33
Задатак 1 Саставити потпрограм на програмском језику Pascal којим се из низа целих бројева, који је представљен уоблику линеарне једноструко уланчане листе, изоставе сви елементи који имају неку задату вредност. Program NizBrojeva(input,output); Type Var pokaz = ^elem; elem = Record broj: integer; eci: pokaz lista,prvi: pokaz; k: integer; broj broj broj Програмирање 1, ЕТФ 2011 9/33 Задатак 1 Procedure izostavi(var niz:pokaz; k:integer); Var preth,tekuci,stari:pokaz; tekuci:=niz; preth:=nil; While tekuci<>nil Do If tekuci^.broj=k Then stari:=tekuci; tekuci:=tekuci^.eci;? stari? If preth=nil Then niz:=tekuci dispose(stari) preth:=tekuci; tekuci:=tekuci^.eci broj broj broj broj preth^.eci:=tekuci; Програмирање 1, ЕТФ 2011 10/33 niz? tekuci preth Задатак 1 Procedure citaj(var niz:pokaz); (*ucitava niz i pravi listu*) Var posl,novi:pokaz; niz:=nil; posl:=nil; While not eoln(input) Do new(novi); read(input, novi^.broj); novi^.eci:=nil; If posl=nil Then niz:=novi posl^.eci:=novi; posl:=novi readln(input) Задатак 1 Procedure pisi(niz:pokaz); (*ispisuje listu u jednom redu*) Var prvi:pokaz; prvi:=niz; While prvi<>nil Do write(output, prvi^.broj:1,' '); prvi:=prvi^.eci writeln(output) Програмирање 1, ЕТФ 2011 11/33 Програмирање 1, ЕТФ 2011 12/33
Задатак 1 Procedure brisi(var niz:pokaz); (* oslobađanje memorije *) Var stari:pokaz; stari:=niz; While stari<>nil do niz:=stari^.eci; dispose(stari); stari:=niz niz broj broj broj broj Задатак 1 (* glavni program *) While not eoln(input) Do (*ponavlja korake dok se unosi neprazan niz *). citaj(lista); write(output, 'ucitani niz je: '); pisi(lista); readln(input, k); writeln(output, 'izostavlja se = ',k:1); izost(lista,k); write(output, 'novi niz je: '); pisi(lista); brisi(lista) stari Програмирање 1, ЕТФ 2011 13/33 Програмирање 1, ЕТФ 2011 14/33 Задатак 2 Саставити програм на програмском језику Pascal који учитава низ целих бројева из произвољног броја редова ипосле их исписује по супротном редоследу. Крај низа се обележава празним редом. Користити динамичке структуре података. Program NizBrojeva(input,output); Const DuzinaReda=10; (*broj podataka za ispis u jednom redu*) BrojKolona=7; (*broj kolona za ispis jednog podatka*) Type pokazivac=^elementliste; ElementListe=Record broj: integer; eci: pokazivac Задатак 2 Var ponji: pokazivac; (*ponji ucitani podatak*) novi: pokazivac; (*novi element u dinamickoj memoriji*) prvi: pokazivac;(*prvi podatak za ispisivanje*) prazan_red: boolean; (*indikator praznog reda*) broj_podataka: integer; (*broj podataka zaprelazak u novi red*) ponji:=nil; Repeat prazan_red:=true; Write(output, 'Unesite eci broj:'); While not Eoln(input) Do new(novi); Read(input, novi^.broj); novi^.eci:=ponji; ponji:=novi; prazan_red:=false Readln(input) Until prazan_red; Програмирање 1, ЕТФ 2011 15/33 Програмирање 1, ЕТФ 2011 16/33
Задатак 2 broj_podataka:=0; prvi:=ponji; While prvi<>nil Do write(output, prvi^.broj:brojkolona); prvi:=prvi^.eci; broj_podataka := broj_podataka+1; If (broj_podataka mod DuzinaReda)=0 Then writeln(output) (*prelazak u novi red ako ponji nije ceo*) If (broj_podataka mod DuzinaReda)<>0 Then writeln(output); (*oslobađanje memorije*) prvi:=ponji; While prvi<>nil Do ponji:=prvi^.eci; dispose(prvi); prvi:=ponji. Задатак 3 Квадратна матрица се представља помоћу уланчане структуре укојој за сваки елемент матрице постоји један чвор који садржи вредност елемената (broj), показивач на наредни елемент у истој колони (dole) и показивач на наредни елемент у истој врсти (desno). Програмирање 1, ЕТФ 2011 17/33 Програмирање 1, ЕТФ 2011 18/33 Задатак 3 Program matrica(input,output); Type ukaz=^matr; matr=record broj: real; dole,desno: ukaz Function XYZ(prvi:ukaz):real; If prvi<>nil Then If prvi^.desno<>nil Then XYZ:=prvi^.broj+XYZ(prvi^.desno^.dole) XYZ:=prvi^.broj XYZ:=0.0. Приложена функција на програмском језику Pascal одређује збир: A) свих елемената матрице B) елемената прве врсте матрице C) елемената на главној дијагонали матрице Задатак 4 Нека је дата виртуелна раван. У равни се налазе кругови који су дефинисани координатама центра ( и y) и полупречником. Написати програм на програмском језику Pascal који открива постојање пресека кругова. Програм треба да са стандардног улаза учита број кругова, а затим координате центра и полупречник сваког круга. За сваки могући пар кругова треба проверити постојање пресека (пресеком се сматра случај када су центри два круга удаљени мање од збира полупречника та два круга), и уколико пресек постоји, исписати поруку отоме, уз навођење података о та два круга (координате центра и полупречник). Сматрати да су све величине реални бројеви. Податке округовима уравни чувати уоблику једноструко уланчане листе. Програмирање 1, ЕТФ 2011 19/33 Програмирање 1, ЕТФ 2011 20/33
Задатак 4 program p1sep04z2(input, output); type pok = ^cvor; cvor = record, y, r: real; : pok end; var novi, prvi, tek1, tek2: pok; n, i: integer; begin write(output, 'unesite broj krugova: '); readln(n); prvi := nil; for i := 1 to n do begin new(novi); write(output, 'unesite koordinate i poluprecnik ', i, '. kruga: '); readln(input, novi^., novi^.y, novi^.r); novi^. := prvi; prvi := novi end; Задатак 4 tek1 := prvi; while (tek1<>nil) do begin tek2 := tek1^.; while (tek2<>nil) do begin if (tek1^.r + tek2^.r) > sqrt(sqr(tek1^. - tek2^.) + sqr(tek1^.y-tek2^.y)) then writeln(output, 'krugovi(', tek1^.:5:3, ', ', tek1^.y:5:3, ', ', tek1^.r:5:3,') i (', tek2^.:5:3, ', ', tek2^.y:5:3, ', ', tek2^.r:5:3, ') se seku'); tek2 := tek2^. end; tek1 := tek1^. end end. Програмирање 1, ЕТФ 2011 21/33 Програмирање 1, ЕТФ 2011 22/33 Задатак 5 Задатак 5 Који од наведених програмских сегмената на програмском језику Pascal на исправан начин у двоструко уланчану листу иза елемента на који указујепоказивач pok, аиспред наредногелемента убацује елемент на који указује показивач pom? Претпоставити да су pok, pom и pok^. различити од nil. Поље указује на претходни, а поље на следећи елемент листе. B) pok^. := pom; pom^. := pok; pom^. := pok^.; pom^.^. := pom; pok pom prvi posl Програмирање 1, ЕТФ 2011 23/33 Програмирање 1, ЕТФ 2011 24/33
Задатак 5 Задатак 5 C) pom^. := pok; pom^. := pok^.; pok^.^. := pom; pok^. := pom; pom A) pom^. := pok; pom^. := pok^.; pok^. := pom; pom^.^. := pom; pom pok pok Програмирање 1, ЕТФ 2011 25/33 Програмирање 1, ЕТФ 2011 26/33 Задатак 6 Дата је бинарна датотека vlasnici.dat која је формирана на основу информација овласницима кућних љубимаца. Сваки запис удатотеци садржи име ипрезиме власника (максимално 30 карактера), име кућног љубимца (максимално 20 карактера) и идентификациони запис. Идентификациони запис садржи шифру љубимца (цео број) иједан карактер који означава врсту љубимца ('P' за псе, 'М' за мачке и'о' за остале врсте). Написати програм на програмском језику Pascal који на основу садржаја наведене датотеке формира листу само оних записа који се односе на псе. Програм затим, са стандардног улаза чита шифре изгубљених паса све док се не унесе негативна вредност. За сваку учитану шифру изгубљеног пса, потребно је исписати информације овласнику на стандардном излазу. Подразумева се да датотека vlasnici.dat већ постоји. Задатак 6 (1/6) PROGRAM JUN05(Input, Output, ulaz); TYPE ZAPIS = RECORD IMEVL:ARRAY[1..30] OF CHAR; IME:ARRAY[1..20] OF CHAR; ID: RECORD SIFRA:INTEGER; VRSTA:CHAR; LISTPOK = ^LISTZAPIS; LISTZAPIS = RECORD zap:zapis; : LISTPOK; VAR glava, pok:listpok; sifra:integer; Програмирање 1, ЕТФ 2011 27/33 Програмирање 1, ЕТФ 2011 28/33
Задатак 6 (2/6) PROCEDURE FORMIRAJ_LISTU(var glava: LISTPOK); var novi, posl:listpok; podat : LISTZAPIS; ulaz :FILE OF ZAPIS; begin assign(ulaz, 'vlasnici.dat'); reset(ulaz); posl:=nil; glava:=nil; Задатак 6 (3/6) WHILE NOT eof(ulaz) DO read(ulaz, podat); IF podat.zap.id.vrsta = 'p' THEN new(novi); novi^. = nil; novi^.zap = podat.zap; IF glava = nil THEN glava := novi ELSE posl^. := novi; posl := novi END close(ulaz) Програмирање 1, ЕТФ 2011 29/33 Програмирање 1, ЕТФ 2011 30/33 Задатак 6 (4/6) Задатак 6 (5/6) PROCEDURE OBRISI_LISTU(var glava: LISTPOK); VAR tek: LISTPOK; WHILE glava <> nil DO tek := glava; glava := glava^.; dispose(tek) END FUNCTION NADJI_SIFRU(glava: LISTPOK, sifra: INTEGER): LISTPOK; VAR nasao: boolean; nasao:= false; NADJI_SIFRU:= nil; WHILE NOT nasao and glava <> nil DO IF glava^.zap.id.sifra = sifra THEN nasao:=true ELSE glava:= glava^.; NADJI_SIFRU := glava Програмирање 1, ЕТФ 2011 31/33 Програмирање 1, ЕТФ 2011 32/33
Задатак 6 (6/6) FORMIRAJ_LISTU(glava); IF glava <> nil THEN sifra := 1; WHILE sifra > 0 DO read(input, sifra); IF sifra > 0 DO pok:=nadji_sifru(glava, sifra); IF pok <> nil THEN writeln(pok^.zap.imevl) END OBRISI_LISTU(glava) END END. Програмирање 1, ЕТФ 2011 33/33