You are on page 1of 96

Duomen struktros ir algoritmai

Vilniaus Universitetas

Algimantas Juozapaviius

DUOMEN STRUKTROS IR ALGORITMAI


mokomoji priemon

Vilniaus universiteto leidykla 1997

Duomen struktros ir algoritmai

Mokomoji priemon i dalies apima dstomas kurs Duomen struktros, "Inforrmacins sistemos, Efektyvs algoritmai ir duomen struktr sintez temas. ie kursai numatyti Matematikos fakulteto informatikos specialybs student bakalauro ir magistro studij programose.

Apsvarst ir rekomendavo spausdinti Matematikos fakulteto taryba (1996.09.17,-protokolo Nr. 8).

Recenzavo dst. V. Diinas

Mokomj priemon ileisti padjo TEMPUS S_JEP-09752-95 programa.

Algimantas Juozapaviius, 1997

Duomen struktros ir algoritmai

Turinys.
vadas. 1. 1.1. 1.2. 1.3. 1.4. 1.5. 1.6. 1.7. 1.8. 1.9. 1.10. Pagrindiniai duomen struktr objektai Masyvas (array) Stekas (stack) Eils (queue) Dekas (dequeue) Tiesiniai sraai (linked lists) Mediai (trees) Medi dstymas kompiuteri atmintyje Rekursija Algoritm analiz Algoritm diegimas

2. Riavimo metodai 2.1. Elementars riavimo algoritmai 2.1.1. Irinkimo (selection) algoritmas 2.1.2. terpimo algoritmas 2.1.3. Burbulo algoritmas 2.1.4. Kevalo (shellsort) algoritmas 2.1.5. Pasiskirstymo skaiiavimas 2.2. Greito riavimo algoritmas 2.2.1. Greito riavimo algoritmo taikymas elementams irinkti 2.2.2. Greito riavimo algoritmo sudtingumas 2.3. Skaitmeninis riavimas (radix sort) 2.4. Prioritetins eils (priority queues) 2.4.1. Duomen struktra heap 2.4.2. Operacijos su heap struktra 2.4.3. Heapsort algoritmas 2.4.4. Netiesiogin heap duomen struktra 2.4.5. Aibs duomen struktra 2.4.6. Aibinis heapsort algoritmas 2.5. Slajos riavimas (mergesort) 2.6. Iorinis riavimas (external sorting) 2.6.1. Subalansuota daugybin slaja (balanced multiway merging) 2.6.2. Pakeitimo irinkimas (replacement selection) 3. Paiekos metodai 3.1. Elementars paiekos metodai 3.1.1. Nuosekli paieka 3.1.2. Dvejetain paieka 3.1.3. Dvejetainio medio paieka 3.1.4. Operacija delete 3.1.5. Netiesioginiai dvejetains paiekos mediai 3.2. Subalansuoti mediai 3.2.1. 2-3-4 ir 2-3-mediai
3

Duomen struktros ir algoritmai

3.2.2. terpimo operacija 2-3-mediuose 3.2.3. Imetimo operacija 2-3-mediuose 3.2.4. Duomen struktros 2-3-mediams 3.2.5. Raudoni-juodi mediai 3.3. Dstymo lentels 3.3.1. Idstymo funkcijos 3.3.2. Atskirti sraai 3.3.3. Atviro adresavimo dstymo metodai 3.4. Skaitmenin paieka 3.4.1. Skaitmeniniai paiekos mediai 3.4.2. Skaitmeniniai paiekos indeksai 3.4.3. Daugybiniai skaitmeniniai paiekos indeksai 3.4.4. Patricia algoritmas 3.5. Iorin paieka 3.5.1. Indeksin-nuosekli paieka 3.5.2. B-mediai 3.5.3. Iplstinis dstymas 4. Sek apdorojimas ir kompresija 4.1. Sek paieka 4.2. Tiesmukikas (brutalios jgos) algoritmas 4.3. Knuth-Morris-Pratto algoritmas 4.4. Boyer-Mooreo algoritmas 4.5. Rabin-Karpo algoritmas 4.6. Dviej sek bendras ilgiausias posekis 4.7. Sek ir fail kompresijos metodai 4.7.1. Vienod simboli sek kodavimas 4.7.2. Kintamo ilgio kodavimas 5. Daugiamai duomen struktros ir algoritmai. 5.1. Vidins atminties struktros 5.1.1. K-D-mediai 5.1.2. BSP-mediai 5.1.3. Ketvirtainiai mediai 5.2. Antrins atminties struktros 5.2.1. Daugiamaiai iplstinio dstymo metodai 5.2.2. Daugiamaiai hierarchiniai metodai 5.2.3. Erdviniai kreipties metodai 6. 6.1. 6.2. 6.3. 6.4. 7. Udaviniai ir pratimai Pirmoji udavini grup Antroji udavini grup Treioji udavini grup Pratimai tiriamajam darbui Literatra

Duomen struktros ir algoritmai

vadas
Mokomosios priemons tikslas - supaindinti su duomen struktr ir algoritm teorija ir praktika. Duomen struktros ir algoritmai - tai sritis, formalizuojanti plat spektr svarbi ir vis labiau plintani procedr, kompiuteriu sprendiant simbolini skaiiavim, ininerijos, kompiuterins grafikos, duomen bazi, telekomunikacij ir kit srii udavinius. Ji jungia vairius matematins logikos, kombinatorikos, diskreiosios matematikos, programavimo, kompiuterins technikos konstravimo, geometrijos ir algebros metodus. Sukaupt rezultat gausa ir kokyb jau apie 20 met iskiria j kaip atskir mokslo tyrim disciplin ir trumpai apibria kaip duomen dstymo kompiuterio atmintyje metod visum. algoritmus monija atkreip dmes jau labai seniai. Daniausiai yra pateikiamas EUKLIDO algoritmas dviej sveik skaii didiausiam bendram dalikliui skaiiuoti (greatest common divisor - gcd), kaip tematikos senumo ir fundamentalumo pavyzdys: program euclid (input, output); var x,y: integer; function gcd (u,v: integer): integer; var t: integer; begin repeat if u<v then begin t := u; u := v; v := t end; u := u-v; until u = 0; gcd := v end; begin while not eof do begin readln (x, y); if (x>0) and (y>0) then writeln (x, y, gcd (x, y)) end; end. Taikymuose algoritmai remiasi sudtingais duomen organizavimo ir manipuliavimo metodais. ie metodai kartu su duomen aibmis vadinami duomen struktromis ir yra vieni i pagrindini informatikos objekt. Jie neatskiriami nuo algoritm (kaip veiksm). Taiau ryis tarp j nevienareikmis. Kartais paprasti algoritmai gali naudoti sudtingas duomen struktras, o sudtingi - paprastas. Vienas i pagrindini ypatum, apibriani algoritm veiksmingum, yra juose naudojamos duomen struktros. ioje mokomojoje priemonje pagrindinis dmesys skiriamas duomen struktroms (kaip veiksm sudtinei daliai) ir nagrinjami su tuo susij algoritmai. Algoritmai ir duomen struktros yra neatsiejami nuo taikym. Duomenys taikymuose gyja turin ir form (t.y. sintaks ir semantik). Tai daro tak operacijoms su duomenimis ir kaip pasekmei - j kompiuterinei realizacijai. Tas pats algoritmas skirtingiems duomenims gali bti visikai skirtingai realizuotas. Kokia realizacija kokiems duomenims yra efektyvi - tai irgi vienas i pagrindini duomen struktr tyrimo objekt. Papildomas darbo su duomen struktromis aspektas, galima sakyti "visuomeninis" - nors ir paprastas algoritmas, bet turintis sudting
5

Duomen struktros ir algoritmai

programin realizacij, gali bti daugelio klaid altinis. Todl reikia nagrinti ir patikimus duomen struktr programavimo bdus. Visi ie aspektai tik pabria duomen struktr teorijos ir praktikos svarb. Apibrimas. Duomen struktra (DS) - tai duomen aib, kuriai apibrtos tam tikros operacijos ir loginiai ryiai tarp j. Literatroje naudojamas ir kitas pavadinimas (danai suprantamas kaip sinonimas) - abstrakts duomen tipai (ADT). Kadangi apibrime dalyvauja operacijos svoka, duomen struktros neatskiriamos nuo algoritm. is apibrimas labiau panaus matematin, nes yra abstraktus. Kompiuteri teorijoje ir praktikoje duomen struktr nagrinjimas neatskiriamas nuo j diegimo (realizavimo). Formaliai vienodai apibrtos duomen struktros diegimas kompiuterio atmintyje gali bti toks skirtingas, kad i struktra bus minima vairiais pavadinimais. Realizacijos skirtumai kartais labai pakeiia tam tikro algoritmo sandar. Taiau duomen struktros esm informatikos poiriu yra tokia: apibrti vietos iskyrimo duomenims talpinti kompiuterio atmintyje metod; apibrti duomen reikmi raymo i viet metod.

Literatroje yra nusistovjs tam tikras termin "abstrakts duomen tipai" ir "duomen struktros" vartojimo santykis. Kalbant apie abstrakt duomen tip, paprastai atsiribojama nuo realizacijos, jos ypatum, pabriami tik duomenys (tam tikra tvarka dstomi), ir algoritmai (tam tikra tvarka atliekamos operacijos). Pagrindin ADT svokos vedimo prieastis - tai noras abstrahuotis nuo konkreios realizacijos. is noras ypa bna svarbus projektuojant dideles ir sudtingas programas. Tuo tarpu terminas "duomen struktros" labiau vartojamas tada, kai norima paminti ir konkret algoritmo realizavim. Be to, danai algoritm formalizuojant reikia nurodyti esmines detales, kurios ikyla realizacijos metu, ir jas traukti algoritm. Abiej termin vartojimo atvejais yra ir tam tikr kolizij, kurias ne visada skiria netgi programuotojai. Taigi stekai ir eils yra abstrakts duomen tipai, kai kalbama apie manipuliacijas su elementais, einaniais i duomen aib ir turiniais gan sudting vidin struktr. Taiau tai yra duomen struktros, kai stekai ir eils realizuoti sveikiems dvejetainiams skaiiams dauginti ar tvarkyti atmint, esant procesoriaus darbo pertrauktims. Duomen struktros masyvai ar jungtiniai sraai yra abstraktaus duomen tipo - tiesinio srao - detalizacijos Paskalio (ar panaioje) programavimo kalboje. ios detalizacijos priklauso nuo algoritmo ir gali bti esmins. ADT vartojimo ar apibrimo atvejai kartais gali bti labai vairs. Daug algoritm yra formuluojami remiantis tiesiniais sraais, pavyzdiui, riavimo ar paiekos algoritmai. Taiau jiems efektyviai realizuoti reikia daniausiai sudting duomen struktr. Tarp vairi abstraki duomen tip ar duomen struktr yra susiklost vairs, kartais gan sudtingi santykiai. Vien ADT (ar DS) galime apibrti kita. Stekai ir eils gali bti apibriami kaip tiesiniai sraai, o Paskalio kalbos rodykls ir rao tipai gali bti skmingai naudojami tiesiniams sraams apibrti. ADT svoka svarbi naudojant skirtingus abstrakcij lygius, konstruojant dideles sistemas. Knygos turin sudaro kelios grups tem: pagrindiniai objektai ir metodai (baziniai objektai, elementarios duomen struktros, mediai, rekursija, algoritm analizs metodai, algoritm realizavimas); riavimo metodai (elementars riavimo metodai, greitas riavimas, skaitmeninis riavimas, prioritetins eils, riavimo-slajos algoritmai, iorinis riavimas); paiekos metodai (elementars paiekos metodai, subalansuoti mediai, dstymo lentels, skaitmenin paieka, iorin paieka);
6

Duomen struktros ir algoritmai

sek apdorojimas (sek fragment paieka, fragment tapatinimas, bendrj poseki paieka ir tapatinimas, fail kompresija); vaizd apdorojimo ir kompiuterins grafikos algoritmai, manipuliacij su duomenimis labai didelse duomen bazse algoritmai.

Mokomosios priemons turin (taiau ne visas temas) labiausiai atitinka [1] vadovlis. Jame aprayti algoritmai yra pritaikyti programavimo Paskaliu metodikai, panaiai kaip ir ioje knygoje, todl i jos perimta ir nemaas kiekis program tekst pavyzdi. Programavimo kalbos C++ metodikai pritaikyti pagrindiniai algoritmai yra idstyti [2] knygoje. i knyga irgi yra labai geras duomen struktr ir algoritm teorijos vadovlis. Knyga [3] yra tikra algoritm, dstom studentams, enciklopedija. Joje dstomi algoritmai ir duomen struktros yra formalizuoti, pateikiama isami algoritm efektyvumo analiz. Kitos - [5 - 10, 12, 13] knygos yra VU Matematikos fakulteto skaitykloje ir gali bti naudojamos vienai ar kitai temai nagrinti. Mokomojoje priemonje pateikiami udaviniai skirstomi keturias grupes. Pirmosios grups udavini tikslas - gyti pradini algoritm analizs gdi. Tai nesudtingi udaviniai, kuriems reikia parinkti ekonomikiausi algoritm ir algoritm vertinti. Antrosios grups udaviniai skirti tiesioginiam duomen struktr realizavimui programavimo kalba. Treios grups udaviniai - tai savarankikos problemos, kurias galima efektyviai sprsti, parenkant tinkamas duomen struktras. Kompleksinei duomen struktr ir algoritm analizei skirti ketvirtos grups udaviniai.

Duomen struktros ir algoritmai

1. Pagrindiniai duomen struktr objektai


Pagrindiniai duomen struktr objektai: duomen ir algoritm apraymo (ir uraymo) kalba; baziniai duomen tipai ir elementarios duomen struktros; duomen struktr ir atitinkam algoritm analizs ir diegimo metodai.

Algoritm ir duomen struktr apibrimui ir uraymui naudojama kalba neturi ymiai skirtis nuo realizavimo kalbos, ir, be to, turi bti suderinama su duomen ir algoritm analizs metodais. Esant dabartinei situacijai informatikoje, geriausia tam tikslui naudoti daugiau ar maiau formalizuot programavimo kalb. ioje knygoje pasirinkome Paskalio programavimo kalb (atitinkani standart, idstyt [4]). Pagrindins prieastys - ji dstoma pirmame kurse ir todl gerai pastama studentams, be to, yra pakankamai struktrizuota ir patogi algoritmams urayti bei duomen struktroms apibrti. Jos pagrindins operacijos suderinamos su algoritm analizje naudojamais metodais. J vartojant realizuota daug populiari algoritm. Paskalio neigiama ypatyb - daugeliui taikym i kalba nra pakankamai detali, ir automatikai negalina ireikti algoritm su visomis detalmis. Todl dabartiniu metu literatroje algoritmai vis daniau apraomi C arba C++ programavimo kalba. Baziniai duomen tipai - tai duomen struktros, diegtos programavimo kalboje. Paskalyje kalboje tai yra: sveikas (integer), realus (real), loginis (boolean), simbolinis (character), masyvas (array), aib (set), rodykls tipas (pointer), rao tipas (record). Uraydami visas kitas duomen struktras ar algoritmus konkreioje realizacijoje (programoje), turime jas ireikti baziniais tipais ir tam tikromis operacijomis su jais. Elementarios duomen struktros - struktros, labai paplit ir nesudtingai apibriamos. Jos gali bti realizuotos vairiais lygiais: techniniu lygiu (operacij vykdymas diegtas elektroninje schemoje ar kitoje techninje kompiuterio dalyje), programavimo kalba (realizuotos kalboje baziniais tipais), algoritmu (duomen struktros operacijos ireikiamos algoritmikai baziniais tipais). Toliau dstomos pagrindins elementarios duomen struktros.

1.1 Masyvas (array)


Masyvas - tai vieno tipo tolydiai idstyt kintamj aib, kai kintamj skaiius i anksto inomas, o kiekvien kintamj galima irinkti tiesiogiai (naudojant indeks ar indeksus). itoks apibrimas pateikia masyv kaip bazin tip (pvz., Paskalio kalboje). Duomen struktros atveju masyvas apibriamas kaip fiksuotas kiekis duomen, kurie atmintyje laikomi nuosekliai, o irenkami naudojant indeks ar indeksus, be to, kiekvieno duomens reikms formuojamos unifikuotai. Masyvai panaudojami beveik kiekvienoje programoje. ia pateikiamas pavyzdys, kaip masyvas naudojamas programuojant Eratosteno rt - metod pirminiams skaiiams rasti, pasilyt treiame imtmetyje B.C.: program primes (input, output); const N=1000; var a: array[1..N] of boolean; i, j: integer; begin a[1]:= false; for i:= 2 to N do a[i]:= true; for i:= 2 to N div 2 do for j:= 2 to N div i do a[i*j]:= false;
8

Duomen struktros ir algoritmai

for i:= 1 to N do if a[i] then write (i:4); end. Masyvo naudojimas algoritme galina: efektyviai taikyti tiesiogin duomen irinkim; suvienodinti kiekvieno duomens irinkimo laik.

Masyvas yra statin duomen struktra - jo dydis turi bti inomas i anksto. Masyvo paplitim slygoja ir tai, kad faktikai bet kurio kompiuterio atmint galima interpretuoti kaip masyv - indeks vaidmen vaidina adresai. Duomenims irinkti masyve gali bti naudojama ir daugiau kaip vienas indeksas - tada kalbama apie dvimaius, trimaius ir t. t. masyvus. Irinkimo laikas masyve bet kuriam duomeniui yra fiksuotas. Jis priklauso tik nuo masyvo matavim skaiiaus, t.y. nuo formuls, kuria naudojantis pagal keli indeks reikmes skaiiuojamas duomens saugojimo atmintyje adresas.

1.2 Stekas (stack)


Duomen struktra stekas - tai duomen aib, kuriai apibrtos tokios operacijos: inicializuoti stek (iskirti viet stekui kompiuterio atmintyje); terpti element x stek (operacija push(x)); paalinti element i steko (operacija pop); skaityti stek; panaikinti stek (panaikinti viet stekui kompiuterio atmintyje).

Duomenims steke taikomi loginiai apribojimai - operacijos pop metu i steko bus paalintas elementas, terptas paskutiniu (taip vadinamas LIFO (Last-In-First-Out) principas). Todl stekas yra viena i riboto irinkimo klass struktr. Lietuvikai stek siloma vadinti dklu, taiau pastarasis terminas per daug netiksliai atskleidia steko esm. Steko struktra naudojama vairiausiose srityse: kompiuterio aparatroje, programose, operacini sistem architektroje, kompiliatoriuose, logini ir simbolini skaiiavim algoritmuose, kitur. Labai paplits pavyzdys, iliustruojantis steko privalumus, yra algebrini reikini reikmi skaiiavimas arba i reikini teisingo uraymo tikrinimas, pvz., ar teisingai idstyti skliausteliai reikinyje. Skaiiuojant aritmetinio reikinio 9*(((5+8)+(8*7))+3) reikm, steko operacij seka gali bti tokia: push(9); push(5); push(8); push(pop+pop); push(8); push(7); push(pop*pop); push(pop+pop);
9

Duomen struktros ir algoritmai

push(3); push(pop+pop); push(pop*pop); writeln(pop). Steko turinio kitim atspindi 1 pav. 7 8 8 8 56 3 5 13 13 13 13 69 69 72 9 9 9 9 9 9 9 9 648 nil

5 9

1 pav. Steko turinio kitimas, skaiiuojant reikin 9*(((5+8)+(8*7))+3). Programuojant steko operacijas Paskaliu, reikia naudoti kok nors bazin - rodykls arba masyvo tip. Steko operacijos, ireiktos baziniu rodykls tipu: type link=^node; node=record key:integer; next:link; end; var head,z:link; procedure stackinit; begin new(head); new(z); head^.next:=z; z^.next:=z end; procedure push(v:integer); var t:link; begin new(t); t^.key:=v; t^.next:=head^.next; head^.next:=t end; function pop:integer; var t:link; begin t:=head^.next; pop:=t^.key; head^.next:=t^.next; dispose(t) end; function stackempty:boolean; begin stackempty:=(head^.next=z) end. Steko operacijos, programuojamos masyvo baziniu tipu: const maxP=100; var stack: array[0..maxP]of integer; p:integer; procedure push(v:integer); begin stack[p]:=v; p:=p+1 end;
10

Duomen struktros ir algoritmai

function pop:integer; begin p:=p-1; pop:=stack[p] end; procedure stackinit; begin p:=0 end; function stackempty:boolean; begin stackempty:=(p=<0) end. Algebrinio reikinio reikms skaiiavimas naudojant stek: stackinit; repeat repeat read(c) until c<>''; if c=')' then write(chr(pop)); if c='+' then push(ord(c)); if c='*' then push(ord(c)); while (c=>'0') and (c=<'9') do begin write(c); read(c) end; if c<>'(' then write(''); until eoln;

1.3 Eils (queues)


Duomen struktra eil - tai duomen aib, kuriai apibrtos tokios operacijos: inicializuoti eil (iskirti viet eilei kompiuterio atmintyje); terpti tam tikr element x eil (operacija put(x)); paalinti element i eils (operacija get); skaityti eil; panaikinti eil (panaikinti viet eilei kompiuterio atmintyje).

Duomenims eilje taikomi loginiai apribojimai - operacijos get metu i eils bus paalintas elementas, terptas pirmasis (vadinamasis FIFO (First-In-First-Out) principas). Todl eil, kaip ir stekas, yra viena i riboto irinkimo klass struktr. Eils struktra taikoma vairiose srityse: algoritmams realizuoti, program loginms schemoms, operacini ir taikomj sistem architektroje, kompiliatoriams, logini ir simbolini skaiiavim algoritmams, matematinio modeliavimo udaviniams ir pan. Programuojant eils (kaip ir stekui) operacijas Paskaliu, reikia naudoti kok nors bazin rodykls arba masyvo tip. Eils operacijos, ireiktos baziniu rodykls tipu: type link=^node; node=record key:integer; next:link; end; var head,tail,z:link; procedure queueinit; begin new(head); new(z); head^.next:=z; tail^.next=z; z^.next:=z end; procedure put(v:integer); var t:link;
11

Duomen struktros ir algoritmai

begin new(t); t^.key:=v; t^.next:=tail^.next; tail^.next:=t end; function get:integer; var t:link; begin t:=head^.next; get:=t^.key; head^.next:=t^.next; dispose(t) end; function queueempty:boolean; begin queueempty:=(head^.next=z;tail^.next=z) end. Eils operacijos, ireiktos baziniu masyvo tipu: const max=100; var quene:array[0..max] of integer; head,tail:integer; procedure put(v:integer); begin queue[tail]:=v; tail:=tail+1; if tail>max then tail:=0 end; function get: integer; begin get:=queue[head]; head:=head+1; if head>max then head:=0 end; procedure queueinitialize; begin head:=0; tail:=0 end; function queueempty:boolean; begin queueempty:=(head=tail) end. Programuojant eil masyvu (kaip pateikta), jo pradi ir pabaig tikslinga "suklijuoti", t.y. kintamj head ir tail, rodani eils pradi ir pabaig, reikmes reikia skaiiuoti mod Max pagrindu (aiku, su reikalingais tikrinimais). terpiant ar imetant elementus i eils, ji turi savyb "liauti" per masyv. Tam, kad efektyviai inaudotume vis masyv eilei saugoti, reikia leisti eils pabaigai uimti ir masyvo pradios elementus (jei jie laisvi). Btent tokia programa ir pateikta iame skyriuje. "Suklijuotas" masyvas eilei saugoti parodytas 2 pav. 21 20 19 18 head 1 2 3 4 17 16 15 14
12

Duomen struktros ir algoritmai

5 6 7 8 9 10 11

13 12 tail

2 pav. Eils dstymas suklijuotame masyve.

1.4 Dekas (dequeue)


Duomen struktra dekas - tai duomen aib, kuriai apibrtos tokios operacijos: inicializuoti dek (iskirti viet dekui kompiuterio atmintyje); terpti tam tikr element x deko pradi; terpti tam tikr element x deko pabaig; paalinti element i deko pradios; paalinti element i deko pabaigos; skaityti deko pradi; skaityti deko pabaig; panaikinti dek (panaikinti viet dekui kompiuterio atmintyje).

Duomenims deke taikomi loginiai apribojimai - operacijos paalinimo i deko pradios ar pabaigos metu bus imestas elementas, terptas vliausiai atitinkamai pradi ar pabaig. Todl dekas, kaip ir eil ar stekas, yra viena i riboto irinkimo klass struktr. Dekas dar vadinamas abipusiu steku (ar abipuse eile). Jo programavimas naudojant bazin masyvo ar rodykls tip panaus steko ar eils programavim, tik reikalauja sudtingesns realizacijos.

1.5 Tiesiniai sraai (linked lists)


Duomen struktra tiesinis sraas - tai duomen aib, kurios kiekvienas elementas susideda i dviej dali - informacins dalies ir rodykls - ir kuriai taikomos tokios operacijos: inicializuoti sra; terpti element x srao tam tikr viet; terpti element x sra, tenkinant nurodytas slygas (pvz., didjimo tvarka); imesti i srao element, esant tam tikroje vietoje; imesti element x i srao, tenkinant nurodytas slygas; panaikinti sra. Sraai, kaip prasta juos pateikti programavimo literatroje, pavaizduoti 3 pav.

tiesinis sraas

dviej krypi sraas

13

Duomen struktros ir algoritmai

ciklinis sraas

3 pav. Sara pavyzdiai Loginiai apribojimai gali bti taikomi tik srao elementams, bet ne visam sraui. Elementams reikia nurodyti j tip (programavimo procese). Sraas yra dinamin duomen struktra, t.y. jo tris vykdymo metu gali keistis, t.y. jam iskiriama tiek atminties, kiek element yra srae. Programuojant sra, reikia remtis rodykls ar masyvo baziniais tipais. Naudojant bazin rodykls tip, sraas programuojamas taip: type link=^node; node=record key:integer; next:link end; var head.z.t:link; procedure listinitialize; begin new (head); new (z); head^.next:=z; z^.next:=z end; procedure deletenext (t:link); begin t^.next:=t^.next^.next; end; procedure insertafter (v:integer; t:link); var x:link; begin new (x); x^.key:=v; x^.next:=t^.next; t^.next:=x end; Srao programavimas, naudojant bazin masyvo tip: var key,next: array[0..N]of integer; x,head,z: integer; procedure listinitialize; begin head:=0; z:=1; x:=1; next[head]:=z; next[z]:=z; end; procedure deletenext(t:integer); begin next[t]:=next[next[t]] end; procedure insertafter(v:integer; t:integer); begin x:=x+1; key[x]:=v; next[x]:=next[t]; next[t]:=x
14

Duomen struktros ir algoritmai

end. Skirtingai nuo steko, eils ar deko, sraas galina irinkti bet kur element, taiau irinkimo metodas yra tiesinis, t.y. tam tikr element pasiekiame nuosekliai eidami nuo vieno elemento prie kito. Jei reikia "gudresni" irinkimo metod, sraas gali bti apibriamas su keliomis rodyklmis (kuri apibrimas ir naudojimas priklauso nuo duomen turinio). Programuojant sraus, (pvz., procedras insertafter ar deletenext), patogu ir svarbu apibrti signalin ymen (sentinel). Signalinis ymuo - tai menamas objektas, kuris suprastina srao pirmo ir paskutinio element atskyrim (identifikavim): signaliniu srao L ymeniu bt objektas nil(L), kurio reikm yra nil, bet kuris turi vis kit srao element struktr. Jis gali bti kintamj head ir tail pakaitalas. Viena i galimybi, kaip naudoti signalin ymen, pavaizduota 4 pav. Ji galina atsisakyti kintamojo head, nes srao pradi galima pasiekti per next(nil(L)). nil(L)
tuias sraas (signalinis ymuo)

nil(L)

nil(L)

25

insert(25)

nil(L)

25

delete(9)

4 pav. Sraas, naudojantis signalin ymen. Gal bt labiausiai paplits sra taikymas - duomen dstymas diskinje atmintyje. Tai tiesiogiai susij su diskini rengini konstrukcija. Maiausio adresuojamo informacinio vieneto diske (vadinsime j toliau puslapiu - anglikai page) tris yra keli arba kelios deimtys kilobait. Kai failas raomas diskin atmint, jis uima danai ne vien puslap. ie puslapiai gali bti idstyti diske nebtinai nuosekliai. Todl btina formuoti nuorodas i vieno puslapio kit. J taip pat reikia identifikuojant laisv diskin atmint, t.y. tuos puslapius, kurie dar nepriklauso jokiam failui. Skirtingos operacins sistemos formuoja puslapi nuorodas skirtingai. Pavyzdiui, MS-DOS operacin sistema nuorodas failo (t.y. tiesinio srao) pradi rao ROOT srityje, nuorodas puslapius (vadinamuosius klasterius - anglikai cluster) FAT srityje, o pat fail dsto DATA srityje. Login tokio dstymo schema pateikta 5 pav.
failo vardas, kiti atributai failo puslapiai puslapi numeriai

failo puslapiai ROOT FAT DATA

5 pav. Login disko struktra.


15

Duomen struktros ir algoritmai

1.6 Mediai (trees)


Iki iol nagrintos duomen struktros buvo vienmats - vienas duomuo sek po kito. Tokias DS gan paprasta programuoti ir naudoti, taiau taikymams jos gali bti neefektyvios, t.y. algoritmas, veikiantis j pagrindu, gali bti per ltas. Todl verta nagrinti sudtingesnes dvimates, trimates ir pan. duomen struktras. Viena i toki yra medio duomen struktra. Medis - tai duomen aib, kuriai apibrtos duomen incidentumo ir eilikumo operacijos: medio (ymime T) elementai yra dvi aibs: virni aib V ir briaun aib E; tarp V ir E apibrtas incidentumo santykis: viena briauna (elementas i E) atitinka dvi ir tik dvi virnes (element i V por, element tvarka poroje yra fiksuota); viena virn medyje yra iskiriama ir vadinama aknimi; bet kurias dvi virnes jungia vienas ir tik vienas kelias (kelias yra briaun seka, kurioje kiekvienos dvi gretimos briaunos turi bendr virn). Manipuliavimo su duomenimis operacijos tokios: inicializuoti med (iskirti viet bsimai medio struktrai kompiuterio atmintyje); terpti element med (terpti nauj virn); imesti element i medio (paalinti virn); sujungti du medius; iskaidyti med du medius; sutvarkyti med (idstyti medio virnes taip, kad pagal tam tikr virni perrinkimo tvark, j reikms atitikt norimas slygas); panaikinti med (ilaisvinti mediui skirt kompiuterio atmintyje viet).

is medio apibrimas yra pritaikytas duomen struktroms ir orientuotas algoritm teorij ir j programavim. Literatroje galima rasti ir kitoki medio apibrim, danai bendresni ir turini teorini ypatum (gan retai pasitaikani praktikoje). Todl ia pateikiami apibrimai ir svokos yra btiniausi ir kartais intuityvs. Virn medyje daniausiai yra struktrizuota (atitinka formuojamas algoritme reikmes ar slygas, danai gan sudtingas). Ji gali turti vard ir prie jos papildom informacij, taip pat tip ar netgi duomen struktr. Briauna irgi gali identifikuoti papildom informacij (pvz. svor), gali turti tip. Kelias i aknies kuri nors virn yra vadinamas aka. Medis yra braiomas akomis emyn, akn dstant viruje (6 pav.).
aknis pirmo lygio virns

lapai

6 pav. Medio pavyzdys. Nors briaunos paprastai neturi krypties (medis yra neorientuotas grafas), taiau programuojant briaunos realizuojamos rodyklmis ir intuityviai joms priskiriama kryptis. Jei i kryptis i virns rodo kit virn emyn nuo aknies, tai sakoma, kad virn turi sn.
16

Duomen struktros ir algoritmai

Briaunos kryptis prieing pus (vir) nurodo virnei jos tv. Virn be sn vadinama lapu arba iorine virne. Visos kitos virns vadinamos vidinmis. Vieno tvo sns vadinami broliais (siblings). Jei kiekvienas tvas turi ne daugiau kaip fiksuot skaii sn (tarkime, n), jis vadinamas n-ariniu mediu. Algoritm teorijoje ypa svarbs yra dvejetainiai mediai. Medis, prasidedantis kurioje nors virnje, vadinamas pomediu. Mikas yra dviej ir daugiau medi aib. Medis turi lygius: aknis yra nulinio lygio, jos sns yra pirmo lygio, i sn sns yra antro lygio ir t.t. Medio aukiu vadinamas lygi maksimumas (arba maksimalios akos ilgis). Viena i svarbi susijusi su algoritmais svok, yra sutvarkytas medis. Medis sutvarkytas, kai jo virnms priskirta tam tikra numeracija (eils tvarka). Medio virns gali bti numeruojamos skirtingais bdais (paprastai nuo j priklauso algoritmo efektyvumas). Medio numeracija gali bti inoma, t.y. nurodyta tvarka, kuria vardijamos (ar spausdinamos, ar peririmos) medio virns. Algoritmuose ar programavime aptinkamos tokios numeracijos (apibrimai rekursyvs ir pateikti dvejetainiam mediui): infiksinis medis (anglikai infix arba inorder) - medio virns vardijamos taip: kairysis pomedis, virn, deinysis pomedis; prefiksinis medis (anglikai prefix arba preorder) - medio virns vardijamos taip: virn, kairysis pomedis, deinysis pomedis; postfiksinis medis (anglikai postfix arba postorder) - medio virns vardijamos taip: kairysis pomedis, deinysis pomedis, virn.

ie apibrimai gali bti lengvai apibendrinti n-ariniams mediams. Jie yra analogiki algebrini ar logini reikini infiksinms, prefiksinms, postfiksinms iraikoms. Infiksin reikinio iraika - tai prastas reikinio uraymas su skliausteliais: (((A + B) * (C - D) + E) * F) Prefiksin iraika raoma (rekursyviai) - operacijos enklas, pirmas operandas, antras operandas: * +*+AB-CDEF Postfiksin iraika raoma (rekursyviai) - pirmas operandas, antras operandas, operacijos enklas: AB+CD-*E+F* i iraik atitinkantis sintaksinis (parse) medis pavaizduotas 7 pav. Prefiksinms ir postfiksinms reikini iraikoms skliausteliai gali bti nenaudojami. Postfiksin iraika dar kitaip vadinama atvirktine lenkika notacija (pagerbiant lenk logikusmatematikus, vedusius tokias iraikas). Vis i iraik atitikmenys gali bti dvejetainiai mediai (infiksiniai, prefiksiniai, postfiksiniai), taiau tik j element numeravimo, o ne skaiiavimo prasme. Dar vienas galimas medi tvarkymo bdas - virni numeracija pagal lygius: nulinio lygio virn (aknis); visos pirmo lygio virns (numeruojamos i kairs dein); visos antro lygio virns (taip pat i kairs dein); ir t.t. * + F
17

Duomen struktros ir algoritmai

* + A B C

7 pav. Reikinio (((A + B) * (C - D) + E) * F) sintaksinis medis. Medio struktra yra i esms rekursyvi. Galima pateikti tok rekursyv medio apibrim: Medis yra arba virn, arba aknin virn, sujungta briaunomis su medi aibe. Elementarios, taiau naudingos medio savybs yra tokios: 1. Medis su N virni turi N-1 briaun; 2. Dvejetainis medis su N vidini virni, turi N+1 iorini virni; 3. Dvejetainio medio su N vidini virni iorinio kelio ilgis yra 2N didesnis u vidinio kelio ilg; 4. Pilno dvejetainio medio auktis n su N vidini virni gali bti vertinamas skaiiumi log2N: n-1 n 2 < N + 1 =< 2 .

1.7. Medi dstymas kompiuterio atmintyje


Vienas i labiausiai paplitusi medi dstymo atmintyje bd - tai virni element raymas raus su nuorodomis. Nuorodos nukreiptos i tvo virns snus. Nuorod skaiius rae turi bti lygus maksimaliam medio virni sn skaiiui. Jei medis dvejetainis, utenka dviej nuorod: left (l) ir right (r). Priklausomai nuo algoritmo kartais reikia turti dviej tip raus: vidinms virnms ir iorinms virnms, nes j panaudojimas algoritmo vykdymo metu gali bti specifinis. Istorikai svarbus ir esminis yra ryys tarp dvejetaini medi (j tvarkymo) ir algebrini reikini. Kaip matome i ankstesnio pavyzdio ir 7 pav., algebriniam reikiniui galima priskirti sintaksin (dvejetain) med ir j naudoti reikiniui analizuoti. Sintaksinis medis (parse tree), atitinkantis algebrin reikin, apibriamas rekursyviai: priskirti operacij akniai, pirmo operando reikin priskirti kairiajam pomediui, antro operando reikin priskirti deiniajam pomediui. Turint postfiksiniu bdu urayt reikin, programa, sukurianti sintaksin med, gali bti tokia: type link=^node; node=record info:char; l,r:link end; var x,z:link; c:char; begin stackinit; new(z); z^.l:=z; z^.r:=r; repeat repeat read(c) until c<>''; new(x); x^.info:=c; if (c='*') or (c='+') then begin x^.r:=pop; x^.l:=pop end else begin x^.r:=z; x^.l:=z end; push(x)
18

Duomen struktros ir algoritmai

until eoln; end. i paprasta programa gali bti lengvai modifikuota sudtingesniems reikiniams. Taiau pasilytas mechanizmas yra labai bendras: j galima taikyti reikini reikmms skaiiuoti, kurti programas reikini reikmms skaiiuoti, rayti sintaksinius analizatorius programavino kalboms ir pan. Kai medis sukurtas, viena i pirmiausia ikylani problem yra medio numeravimas, t.y. kokia tvarka apeiti ar perrinkti (traverse) medio virnes. Skirtingiems taikymams naudotina skirtinga numeracija. Prefiksinei numeracijai yra tinkama tokia programa: procedure traverse(t:link); begin push(t); repeat t:=pop; visit(t); if t<>z then push(t^.r); if t<>z then push(t^.l); until stackempty; end; Kitoms dviems medi numeracijoms - infiksinei ir postfiksinei - programos gali bti paraytos analogikai, tik iek tiek modifikuojant pateiktj. Tuo tarpu medi numeracijai pagal lygius programa gali bti gauta i ankstesns, operacijas su steku programos struktroje pakeitus analogikomis operacijomis su eile: procedure traverse(t:link); begin put(t); repeat t:=get; visit(t); if t<>z then put(t^.l); if t<>z then put(t^.r); until queueempty; end; Antras medio struktros dstymo kompiuterio atmintyje bdas - naudoti raus tik su dviem nuorodomis (bet kuriam n-ariniam mediui) ir ias nuorodas interpretuojant taip: kairioji (left) nuoroda identifikuoja virns kairj sn, tuo tarpu deinioji nuoroda rodo virns dein brol. is dstymo bdas reikalauja vesti tam tikr tvark tarp broli (siblings), kad atskirtume, kuris i broli yra kairje, o kuris - deinje. Tokio dstymo pavyzdys yra 8 pav. 1 2 5 6 3 7 4 8 9 10
19

Duomen struktros ir algoritmai

8 pav. Kairysis smus - deinysis brolis bdu idstytas medis. Abu ie metodai nekelia koki nors reikalavim raams su nuorodomis, daugiausia priklauso nuo taikomojo algoritmo - ar bazin tip tokiems raams parinksime masyv, ar rodykls tip. Reikia tik turti omenyje, kad bazinis tipas irgi daro tak, ir kartais esmin, algoritmo greiiui (apie tai kituose skyriuose). Treias medio struktros dstymo bdas - vadinamieji rekursyvs mediai - gali bti naudojamas tada, kai algoritme daniausiai reikia naudoti nuorodas i sn j tvus. Medio virnes sunumeravus pagal lygius, galima jas rayti vienmat masyv taip, kad io masyvo indeksai atitikt virni numerius, o masyvo element reikms bt nuorodos tvo numer. Toks medio organizavimas galina labai greitai "vaikioti" medio akomis nuo sn prie tv ir nuo vienos virns prie kitos, ir, jei tokios procedros taikomajame udavinyje yra pagrindins, programa dirba labai greitai, jos sudtingumas yra tiesinis. Medio i 8 pav. rekursyvus dstymas pavaizduotas 9 pav. 1 2 0 1 3 1 4 1 5 2 6 2 7 3 8 3 9 10 3 4

9 pav. Medio rekursyvus dstymas.

1.8 Rekursija
Rekursija yra viena i pirmini ir pagrindini matematikos ir informatikos svok. Rekursija matematikoje vadinamas toks funkcij apibrimo metodas, kai funkcijos reikms, atitinkanios bet kokius argumentus, yra apibriamos naudojant tos paios funkcijos reikmes, atitinkanias maesnius argumentus. Analogikai programavime, rekursija yra program (procedr, algoritm) apibrimo (sudarymo) metodas, kai programa kreipiasi pati save, esant maesnms argument (parametr) reikmms. Rekursyviai programai reikia papildomai apibrti t atvej, kai pasiektos maiausios galimos argument reikms (baigms slyga). Rekursyvi program pavyzdiai mediams numeruoti ar virnms perrinkti jau buvo pateikti anksiau. inomi klasikiniai rekursyvi algoritm pavyzdiai - tai faktorialo skaiiavimas ar Fibonaio skaii sekos apibrimas: function factorial (N:integer):integer; begin if N=0 then factorial:=1 else factorial:=N*factorial(N-1); end; function fibonacci(N:integer):integer; begin if N=<1 then fibonacci:=1 else fibonacci:=fibonacci(N-1)+fibonacci(N-2); end;

20

Duomen struktros ir algoritmai

Rekursijos stipryb - ji galina ymiai suprastinti algoritmo formulavim ar programos konstrukcij. Taiau ja naudoti reikia atsargiai. Pavyzdiui, Fibonaio skaii sekos apibrimas naudojant rekursij, kaip k tik pateiktame pavyzdyje, i program daro neefektyvi: skaiiai fibonacci(N-1) ir fibonacci(N-2) gaunami nepriklausomai vienas nuo kito, tuo tarpu juos nesunku gauti vien i kito. Fibonaio algoritmas, formuluojamas be rekursijos, yra efektyvesnis (operacij skaiius proporcingas N): procedure fibonacci; const max=25; var i:integer; F:array[0..max] of integer; begin F[0]:=1; F[1]:=1; for i:=2 to max do F[1]:=F[i-1]+F[i-2] end; Rekursija glaudiai susijusi su tam tikra algoritm konstravimo metodika, vadinamja skaldyk ir valdyk (divide and conquer) paradigma. Pagal toki paradigm sukurtas algoritmas naudoja du rekursyvius programos kvietimus, taiau nesikertanioms argument reikmms. Jos pavyzdys - pateikiama liniuots gradavimo programa: procedure rule(l,r,h:integer); var m:integer; begin if h>0 then begin m:=(l+r)div2; mark(m,h); rule(l,m,h-1); rule(m,r,h-1) end end; Pagal i programa sugraduota liniuot parodyta 10 pav.

10 pav. Graduota liniuot. Liniuots gradavimo nerekursyvus algoritmas gali bti gautas: beveik tiesmukikai i rekursyvaus algoritmo; pakeiiant gradavimo ymi pieimo tvark.

Kita vertus, pateikt infiksinio ir pagal lygius sutvarkyto medi algoritm rekursyvi realizacija ymiai suprastina algoritm programavim. Visa tai gali bti palikta kaip pratimai skaitytojui. "Skaldyk ir valdyk" paradigma apima tris tipinius kiekvieno rekursijos lygio ingsnius:
21

Duomen struktros ir algoritmai

iskaidyti udavin kelis dalinius udavinius; valdyti rekursyviai kiekvieno dalinio udavinio sprendim, jei udavinys tapo paprastas, isprsti j tiesiogiai; sujungti dalini udavini sprendinius ir suformuoti ieities udavinio sprendin.

i paradigma taikoma algoritmams, kaip operacij sekoms, ir duomen struktroms konstruoti. Kiti du plaiai naudojami metodai - tai rekursija ir iteracija. Visos toliau nagrinjamos struktros ar su jomis susij algoritmai bus pagrsti vienu i i metod.

1.9 Algoritm analiz


Algoritm analiz yra btina reikalingiems udavinio realizavimui kompiuterins sistemos resursams vertinti. Resursai - tai udavinio skaiiavimo laikas (daniausiai pats svarbiausias resursas), reikalingos atminties tris, komunikacini sraut dydis, logini vad (port) skaiius ir pan. Prie pradedant algoritmo analiz, reikia sukurti formalj diegimo technologijos model. Nagrinsime algoritmus darbui vieno procesoriaus aplinkoje (nuoseklus algoritm vykdymo bdas). ie algoritmai naudos arba tiesioginio irinkimo atmint (RAM - random access memory), arba diskin atmint (toks naudojimas bus specialiai aptartas), disponuos tam tikru kiekiu (N) pradini duomen (kartais skirstom tam tikras klases). Algoritm analizuosime kaip kompiuterin program, vykdom remiantis tam tikromis bazinmis operacijomis. Toki operacij, j tip ar klasi iskyrimas visada susijs su taikomuoju udaviniu ir yra btinas. Bet kurio net ir paprasiausio algoritmo analiz - tai tam tikra matematin problema, kartais net labai sudtinga. Jai sprsti naudojamos vairios matematins priemons - kombinatorika, elementari tikimybi teorija, mantrios algebrins manipuliacijos, kartais ir kitos sudtingesn, matematins teorijos. Be to, dar reikia daug imons ir intuicijos. 1. Pradiniai duomenys, j kiekio apibrimas priklauso nuo taikym. Riavimo udaviniuose pradiniai duomenys - tai kiekis duomen, kuriuos turime sutvarkyti. Skaii daugybos algoritmuose - tai bit skaiius, reikalingas dauginamiems skaiiams idstyti atmintyje. Duomen bazse - tai ra ar lauk juose kiekis. Telekomunikacijos udaviniuose - maksimalus siuniamo praneimo ilgis, ir t.t. 2. Algoritmo veikimo laikas paprastai yra proprocingas vykdom operacij skaiiui. Kadangi skirtingos operacijos gali bti vykdytos per skirting laik, algoritm analizs atveju naudojamos operacijos yra skirstomos grupes, kiekvienai i j atskirai vertinant operacij kiek. vertinus algoritmo vykdymo laik, svarbu inoti, kaip elgsis algoritmas, jei keisime pradini duomen kiek. Tam nebtina inoti tiksl laik L ireikiani formuli, o tik j asimptotik. Todl algoritm analizs atveju yra labai populiars vertinimai: O(1) - rodo pastov operacijos atlikimo laik; o(K) - rodo, kad laikas visa eile arba keliomis eilmis maesnis u K; O(K) - rodo, kad laikas proporcingas reikiniui K, t.y. egzistuoja konstanta C, kad L<C*K Be to, vertinant algoritm darb danai tikslinga iskirti du atvejus: vidutin algoritmo darbo laik (vidutinis atvejis arba laukiamas atvejis - average-case analysis) ir algoritmo darbo laik tuo atveju, kai jam pateikiami blogiausi duomenys (blogiausias atvejis - worst-case analysis). Praktikai daugiausia dmesio analizje yra skiriama blogiausiam atvejui, nes tam yra tokios prieastys: blogiausio atvejo laikas yra virutin laukiamo atvejo laiko riba, jo vertinimas garantuoja, kad algoritmas niekada nedirbs ilgiau;
22

Duomen struktros ir algoritmai

danai taikymuose blogiausias atvejis pasirodo ne taip jau retai, pvz., iekant tam tikros informacijos duomen bazse, blogiausias atvejis paiekos poiriu ikyla visada, kai tik bazse tokios informacijos nra; danai laukiamas atvejis yra toks pat blogas, kaip ir blogiausias atvejis, t.y. abiem atvejais vertinimai sutampa.

3. Algoritmui veikti reikalingos atminties kiekis irgi yra analizs objektas. itokios analizs ypa reikia algoritmams, formuluojamiems remiantis rekursija arba paradigma "skaldyk ir valdyk", nes j atveju reikia vertinti rekursijos gyl, o kuo gilesn rekursija, tuo daugiau atminties reikia algoritmo vykdymui. Atminties kiekio vertinimai taip pat reikalingi algoritmams, dinamikai apibriantiems duomenims viet atmintyje. ie vertinimai yra sudtingesni negu statini duomen laikymo atmintyje struktr atveju, nes dinamikai adresuojant duomenis algoritmui kartais reikia labai nedaug atminties.

1.10. Algoritm diegimas


Algoritmai retai egzistuoja "vakuume", be ssaj su taikymais, nebent tai bt grynai teoriniai, hipotetiniai algoritmai. Jie paprastai sudaro esmin dal sistemos, kurioje yra diegiami, nors ta dalis gali bti ir nedidel. Algoritm veikimo aplinka bna gan sudtinga, todl ir visos realizavimo procedros nagrinjimas - tai labai komplikuota analiz. ia paminsime tik esminius momentus. 1. Algoritmo parinkimas. Paprastai yra kelios ar keliolika procedr, kurios tinka realizuoti norim taikym. J diapazonas bna gan platus - nuo "brutalios jgos" algoritm iki logikai sudtingos veiksm sekos. Pirmiausia turime atsakyti tokius klausimus, kurie yra svarbs visai vykdymo eigai: kaip danai programa bus naudojama; kokios yra kompiuterins sistemos charakteristikos; ar algoritmas sudaro tik ma dal viso udavinio, ar atvirkiai?

Pagrindin taisykl, kuria vadovaujamasi diegimo metu,- realizuoti pat paprasiausi udavinio sprendimui tinkam algoritm, nuosekliai vertinant atsakymus tik k pateiktus klausimus. Tai turi bti daroma kruopiai. Dvi daniausiai pasikartojanios ioje situacijoje klaidos - tai algoritmo veikimo charakteristik reikms pervertinimas arba nepakankamas vertinimas. Paprastai greitesn algoritm sudtingiau programuoti, bet tam tikram duomen kiekiui jo greiio rodikliai gali bti esminiai. 2. Empirin analiz. Labai gaila, bet daniausiai matematin algoritmo analiz duoda per maai informacijos apie real algoritmo efektyvum, todl reikia tam tikro empirinio tikrinimo. Pirmiausia ia galioja triviali taisykl - jei yra du algoritmai, reikia juos abu imginti kiek galima panaesnmis slygomis. Vadinasi, ne tik kompiuterins sistemos ar duomenys turi bti panas, bet ir dmesys algoritm programavimui ir optimizavimui turi bti tas pats. Po to, greitesnio algoritmo veikimo ar realizavimo slygos turi bti kruopiau analizuojamos. 3. Program optimizavimas. Paprastai is procesas suprantamas kaip kompiliatoriaus priemoni visuma, kai yra automatikai generuojamas optimalus kodas. Taiau ia turimi omenyje btent algoritmo darbo pagerinimai. Pirmiausia, algoritm reikalinga realizuoti paprasiausia galima forma. Antra, reikia minimizuoti bazini operacij skaii, ivengiant bereikaling cikl ar kit pasikartojani veiksm sek. Treia, algoritmo atliekamus veiksmus reikia analizuoti technini ir programini priemoni atvilgiu, t.y. kokia yra naudojamo kompiuterio architektra, kaip dirba
23

Duomen struktros ir algoritmai

kompiliatorius ir pan. Tokia periodikai atliekama empirin analiz gali kartais padti atrasti naujus algoritmo darbo aspektus, ir i esms pagerinti algoritmo darb. 4. Algoritmai ir sistemos. Tas pats algoritmas naudojamas ir maose programose, ir sudtingose sistemose. iomis skirtingomis slygomis jo realizavimas irgi yra skirtingas. Pavyzdiui, riavimo algoritmas priklausomai nuo to, ar jis riuoja natrinius skaiius, ar labai ilgus sudtingos struktros raus, turs bti skirtingai realizuotas. Vlgi, jei algoritmas dirba sistemoje, kuri realizuota lokaliame ar globaliame kompiuteri tinkle, jo veikimo charakteristikos bus kitokios negu algoritmo, dirbanio atskirame kompiuteryje. Danai tokiais atvejais detali algoritmo analiz slygoja ivad, kad algoritmas gali bti "ilygiagretintas", t.y. jis gali bti iskaidytas lygiagreiam darbui skirtingose tinklo kompiuteriuose su skirtingomis duomen aibmis. Visi minti algoritm analizs ir realizavimo aspektai gali bti taikomi ir atskiroms programoms, ir program sistemoms. Taiau sistem atveju yra ir daug skirtum. Dabartiniu metu sistem projektavimo atveju populiaru naudoti objekt orientavimo metodik, pagal kuri programa turi tenkinti klass, kuri ji patenka, duomen, funkcini procedr ir pan. reikalavimus. Programa turi bti jungta sistem kaip atskiras modulis. Visa tai siejasi su algoritmo sudtingumu.

24

Duomen struktros ir algoritmai

2. Riavimo metodai
Riavimas - tai viena i bazini kompiuteri darbo operacij, turini informatikoje toki pat reikm, kaip matematikoje - sudties operacija. ioje knygoje riavimas - tai algoritmas, dstantis duomenis tam tikra tvarka. Tokio algoritmo darb slygoja labai daug aspekt. Duomen tvarkos apibrimas, duomen struktra, riuojam lauk iskyrimas, atminties panaudojimas riavimo operacijai, antrins ar netgi tretins atminties poreikis, duomen pateikimo riavimui vienalaikikumas, eilikumas (nuosekliai ar grupmis), riavimas lygiagreiose sistemose, kiti veiksniai - visa tai turi didel tak riavimo algoritmo darbo efektyvumui. Dstant riavimo algoritmus, pradedama nuo paprasiausi ir klasikini situacij, pereinama prie sudtingesni (taiau ne vis galim).

2.1 Elementars riavimo algoritmai


Riavimo algoritmai priklausomai nuo to, ar naudoja tik vidin kompiuterio atmint, ar jiems reikia ir iorins (antrins) skirstomi vidinio riavimo ir iorinio riavimo algoritmus. Pastarieji naudojami, kai duomenys vienu metu negali bti idstyti atmintyje. Papildomos atminties (vidins) kiekis, reikalingas algoritm darbui, irgi yra svarbus rodiklis. Riavimo algoritmai gali bti skirstomi grupes pagal tai, kiek papildomos atminties naudoja (nenaudoja visikai; naudoja papildomai tik atmint, reikaling rodyklms idstyti; naudoja papildomai tiek pat atminties, kiek yra duomen). Riavimo algoritmai gali bti stabils ir nestabils. Stabils algoritmai nekeiia lygi (lyginimo poiriu) element tvarkos. Nagrindami algoritmus, tarsime, kad duomenys, kuriuos algoritmas turi riuoti - tai paprasti skaiiai, laisvai talpinami kintamj lstelse. Taip galime geriau sukoncentruoti dmes algoritmo darbo specifik. Paprasiausias ir primityviausias riavimo algoritmas (riuojantis tris elementus): program threesort (input , output ); const maxN=100; var a : array [1 .. maxN] of integer; N , i : integer; procedure sort3 ; var t : integer ; begin if a [1] >a [2] then begin t: =a [1] ; a [1] :=a [2] ; a [2] :=t end ; if a[1] >a [3] then begin t :=a [1]; a [1] :=a [3] ; a [3] :=t end ; if a [2] >a [3] then begin t:=a [2] ; a [2] :=a [3] ; a [3] :=t end ; end; begin readln (N) ; for i:=1 to N do read (a [i]) ; if N=3 then sort3; for i:=1 to N do write (a [i]) ; writeln
25

Duomen struktros ir algoritmai

end. 2.1.1. Irinkimo (selection) algoritmas Vienas i paprasiausi riavimo algoritm - irinkimo vadovaujasi principu: minimal element reikia rayti pirm duomen sekos viet. Po to t pat princip reikia taikyti posekiui be pirmojo elemento, ir t.t. Programa, realizuojanti algoritm: procedure selection; var i,j,min, t: integer ; begin for i:=1 to N -1 do begin min :=i ; for j :=i+1 to N do if a [j]<a [min] then min :=j ; t:=a [min]; a [min]:=a [i]:=t end; end; Nors is algoritmas priklauso "brutalios jgos" algoritmams, jis danai naudojamas labai ilgiems raams su trumpais laukais riuoti. T slygoja io algoritmo ypatyb, kad kiekvienas i element bus perkeltas kit viet ne daugiau kaip vien kart. Pagrindins algoritmo darbo operacijos - tai duomen lyginimas ir keitimas vietomis. 2 Vertinant algoritmo efektyvum, nesunku rodyti, kad jis naudoja apytikriai N /2 lyginim ir N keitim. 2.1.2. terpimo algoritmas terpimo algoritmas yra beveik toks pat paprastas kaip ir irinkimo, bet labiau lankstus. Pradedant nuo pirmojo, kiekvienas sekos elementas xi yra lyginamas su prie j esaniu, ir, jei j tvarka netinkama, sukeiiami vietomis. Jei toks keitimas vyko, lyginama pora (xi-1, xi), ir t.t. Lyginim serija nutraukiama, jei kurios nors poros element sukeisti vietomis nereikia. algoritm realizuoja tokia programa: procedure insertion; var i,j,v:integer; begin for i:=2 to N do begin v:=a[i]; j:=i; while a[j-1]>v do begin a[j]:=a[j-1]; j:=j-1 end; a[j]:=v end end; is algoritmas gerai inomas brido aidimo mgjams - taip jie riuoja turimas kortas. Taikomuoju poiriu jis labiau tinkamas situacijai, kai duomen keitimo vietomis operacija yra
26

Duomen struktros ir algoritmai

lengvai vykdoma. Programuojant algoritm, reikia parinkti tinkam bazin duomen struktr (masyvas ia maiau tinka). Naudojant sraus, tikslinga juos vesti ir signalin ymen (sentinel), tai ymiai palengvina programos konstravim. Pagrindins algoritmo operacijos yra tokios pat, kaip ir ankstesnio. terpimo algoritmas 2 2 laukiamu atveju naudoja apytikriai N /4 lyginim ir N /8 keitim vietomis ir dvigubai daugiau operacij blogiausiu atveju. terpimo metodas yra tiesinis beveik suriuotiems duomenims. 2.1.3. Burbulo algoritmas io algoritmo idja - nuosekliai i deins kair perirint gretim element poras ir jei reikia, elementus sukeiiant vietomis, sekos pradi perkelti maesnius elementus. Taip elgiantis, maesni elementai pasislenka duomen sekos pradi, o pirmoje sekos vietoje atsiduria maiausias elementas. Po to galima pritaikyti t pat princip duomen posekiui be pirmojo elemento, ir t.t. Tai panau virimo proces, kai oro burbuliukai kyla paviri - i ia kils algoritmo pavadinimas. Algoritm realizuoja tokia programa: procedure bubble; var i,j,t: integer; begin for i:=N downto 1 do for j:=2 to i do if a[j-1]>a[j] then begin t:=a[j-1]; a[j-1]:=a[j]; a[j]:=t end end; Burbuliuko algoritmas apytikriai naudoja N /2 lyginim ir N /2 keitim vietomis ir laukiamu, ir blogiausiu atvejais. N vienam i trij pateikt algoritm nereikia papildomos arba tarpins atminties. Tolesnis algoritm darbo arba j tinkamumo vienai ar kitai situacijai vertinimas turi apimti lyginimo ir keitimo vietomis operacij "kain" ir j santyk. Operacij vykdymo laikas akivaizdiai priklauso nuo ra ilgio, lauk, pagal kuriuos riuojama, santykio, ra ilgi santykio ir pan. Jei ie faktoriai napalanks, galima keisti algoritm realizacij. Pavyzdiui, riuojant ilgus raus, galima vesti papildom ra nuorod masyv ar sra ir lyginimo atveju manipuliuoti io masyvo reikmmis. Taip galima pasiekti, kad bet kuris i jau nagrint algoritm naudos tik N ra keitim vietomis. Pavyzdiui, terpimo algoritmas iuo atveju bt programuojamas taip: procedure insertion; var i,j,v: integer; begin for i:=1 to N do p[i]:=i; for i:=2 to N do begin v:=p[i]; j:=i; while a[p[j-1]]>a[v] do begin p[j]:=p[j-1]; j:=j-1 end; p[j]:=v end end;
27
2 2

Duomen struktros ir algoritmai

Po to, kai nuorod masyvas suriuotas, reikia sprsti ra keitimo vietomis problem. Optimaliai tai galima daryti fiksuojant vietas, kur koks raas turi bti: procedure insitu; var i,j,k,t: integer; begin for i:=1 to N do if p[i]<>i then begin t:=a[i]; k:=i; repeat j:=k; a[j]:=a[p[j]]; k:=p[j]; p[j]:=j; until k=i; a[j]:=t end; end. 2.1.4. Kevalo (shellsort) algoritmas Ivardyti algoritmai yra universals ta prasme, kad nekreipia dmesio duomen sekos ypatumus. Taiau jei ie ypatumai yra inomi, algoritmus galima pertvarkyti taip, kad jie dirbt efektyviau. Kevalo algoritmas yra nesudtinga terpimo metodo modifikacija. Duomen seka interpretuojama kaip h suriuota, t.y. imant nuo bet kurios vietos kiekvien h-j element gaunamas suriuotas posekis. Skaii h keiiant pagal kok nors dsn, pvz., h:= 3*h + 1, kevalo algoritmas visikai apibrtas, jo realizavimas pateikiamas programoje: procedure shellsort; label 0; var i,j,h,v: integer; begin h:=1; repeat h:=3*h+1 until h>N; repeat h:=h div 3; for i:=h+1 to N do begin v:=a[i]; j:=i; while a[j-h]>v do begin a[j]:=a[j-h]; j:=j-h; if j =< h then goto 0 end; 0:a[j]:=v end until h=1; end; io algoritmo darbo efektyvumas priklauso nuo skaiiaus h kitimo dsnio parinkimo ir nuo duomen sekos. Algoritmo sudtingum atskleidia toks teiginys, kur sunku matematikai rodyti: 3/2 Kevalo algoritmas naudoja ne daugiau kaip N lyginim (esant h kitimo dsniui 1, 4, 13, 40, 121, ...).
28

Duomen struktros ir algoritmai

Kitas geras io metodo ypatumas - j lengva programuoti netgi sudtingesniems duomenims. Todl jis danai aptinkamas vairiuose taikymuose. 2.1.5. Pasiskirstymo skaiiavimas Labai paprasta riuoti specifinje situacijoje, kai skaiiai keiiasi nuo 1 iki N, belieka duomenis perkelti vietas, kuri numeriai lygs j reikmms: for i:= 1 to N do t[a[i]]:= a[i]; Jei turima N skaii, kurie yra intervale nuo 1 iki M, riuoti galima irgi panaiu bdu, tik reikia inoti, kiek kart kiekvienas skaiius sekoje pasikartoja. Kai M nra labai didelis, sek galima pereiti du kartus, pirm kart apskaiiuojant element pasikartojimus sekoje, o antr kart perkeliant tuos elementus jiems priklausanias vietas. itok algoritm realizuoja programa: for j:=0 to M-1 do count[j]:=0; for i:=1 to N do count[a[i]]:=count[a[i]]+1; for j:=1 to M-1 do count[j]:=count[j-1]+count[j]; for i:=N downto 1 do begin b[count[a[i]]]:=a[i]; count[a[i]]:=count[a[i]]-1 end; for i:=1 to N do a[i]:=b[i];

2.2 Greito riavimo algoritmas


is metodas, anglikai vadinamas quicksort, pasilytas C. A. R. Hoare 1962-ais metais. Jis yra labai paplits ir aptinkamas daugelyje taikym. Algoritmo realizavimo paprastumas ir efektyvus atminties naudojimas slygojo jo populiarum. Algoritmo teigiamos savybs: papildoma atmintis beveik nenaudojama; algoritmo sudtingumas yra O(NlogN) laukiamu atveju; algoritmo realizavime gali bti apibrti labai trumpi vidiniai ciklai. Algoritmo neigiamos savybs: algoritmas rekursyvus, todl diegimas komplikuotas, kai nra rekursijos mechanizmo; algoritmo sudtingumas yra O(N2) blogiausiu atveju; algoritmas labai jautrus programavimo klaidoms.

Quicksort remiasi paradigma "skaldyk ir valdyk". Pagrindin idja - iskaidius duomen sek dvi dalis taip, kad vienoje i j visi elementai bt maesni u kitos dalies elementus, toliau ias dvi dalis galima riuoti nepriklausomai viena nuo kitos. Todl parinkus element, kuris galima sakyti, jau yra savo vietoje ir naudotinas kaip slenkstis, galima toliau skaidyti sek dvi dalis tokio elemento atvilgiu. Tai daro partition procedra ioje scheminje programoje:
29

Duomen struktros ir algoritmai

procedure quicksort(j,r:integer); var i; begin if r>l then begin i:=partition(l,r) quicksort(l,i-1); quicksort(i+1,r); end end; Parametrai l ir r rodo, kuri sekos dalis iuo metu yra riuojama, parametras i rodo slenkstinio elemento numer. Kruopiai ianalizavus reikalingus veiksmus, algoritm, galima vykdyti gan tobulai, pvz., suradus kairje sekos pusje element, kuris didesnis u slenkst ir kur reikia perkelti dein pus, galima prie tai dar surasti element deinje, kuris maesnis u slenkst, ir tik tada abu iuos elementus sukeisti vietomis - taip yra taupomi veiksmai ir atmintis. Realizavus partition procedr ir tik k aprayt princip, algoritmo tekstas bt toks: procedure quicksort (l,r: integer); var v,t,i,j: integer; begin if r>l then begin v:=a[r]; i:=l-1; j:=r; repeat repeat i:=i+1 until a[i]=>v; repeat j:=j-1 until a[j]=<v; t:=a[i]; a[i]:=a[j]; a[j]:=t; until j=<i; a[j]:=a[i]; a[i]:=a[r]; a[r]:=t; quicksort (l,i-1); quicksort (i+1,r) end end; Aiku, is algoritmas yra nestabilus, jis gali ne tik keisti lygi element tvark, bet ir juos dstyti skirtingose vietose. Jis taip pat nestabilus partition procedros atvilgiu. Algoritmo efektyvumo ypatumus slygoja tokie faktoriai: rekursijos eliminavimas (reikia turti omenyje, kad btina kruopiai valdyti algoritmo vykdymo eig ir i anksto numatyti nepalanki arba isigimusi sek atvejus):

procedure quicksort; var t,i,l,r: integer; begin l:=1; r:=N; stackinit; push(l); push(r); repeat if r>l then
30

Duomen struktros ir algoritmai

begin i:=partition(l,r); if (i-l)>(r-i) then begin push(l); push(i-1); l:=i+1 end else begin push(i+1); push(r); r:=i-1 end; end else begin r:=pop; l:=pop end; until stackempty; end; trumpi posekiai - kai reikia riuoti trump posek, tarkime, tok, kad r - l =< M, tikslinga naudoti kok nors tiesiogin metod, pvz., terpim, ribin skaii M parenkant tok, kokio reikia; slenksio parinkimas - i problema irgi svarbi greito riavimo algoritme; daniausiai ia naudojamas arba didesnio i pirmj dviej nesutampani sekos element principas, kaip aprayta anksiau, arba vadinamasis medianos i trij element principas. 2.2.1. Greito riavimo algoritmo taikymas elementams irinkti Pagrindin algoritmo idja gali bti panaudota ne vien duomenims riuoti. Labai danas toks udavinys: i skaii sekos irinkti k maiausi. Kitas pavyzdys - medianos apskaiiavimas. itokius ir panaius udavinius (danai minimus rangins statistikos vardu), aiku, galima sprsti riuojant turim skaii sek. Taiau tai yra neefektyvu. Kitoks galimas sprendimo bdas parinkti tinkam element ir pritaikius partition procedr, suskaidyti sek dvi dalis, i kuri vienoje yra k maesni u parinkt element, o kitoje yra (N-k) didesni. Atitinkama programa bt tokia: procedure select(l,r,k: integer); var i; begin if r>l then begin i:=partition(l,r); if i>l+k-1 then select(l,i-1,k); if i<l+k-1 then select(i+1,r,k-1); end end; Kadangi i procedra ikvieia save tik vien kart, ji i esms nra rekursyvi ir eliminuoti rekursij nra sudtinga. Tam nebtina naudoti netgi steko, nes procedra, grdama vl savo pradi, atnaujina parametr reikmes. Be to, galime sumainti skaiiavim kiek, jei parinkdami slenkst naudosime skaii k: procedure select(k: integer); var v,t,i,j,l,r: integer; begin l:=1; r:=N; while r>l do begin
31

Duomen struktros ir algoritmai

v:=a[r]; i:=l-1; j:=r; repeat repeat i:=i+1 until a[i]=>v; repeat j:=j-1 until a[j]=<v; t:=a[i]; a[i]:=a[j]; a[j]:=t; until j=<i; a[j]:=a[i]; a[i]:=a[r]; a[r]:=t; if i=>k then r :=i-1; if i=<k then l:=i+1; end; end; 2.2.2. Greito riavimo algoritmo sudtingumas Intuityviai aiku, kad efektyviausiai Quicksort algoritmas veikia, kai slenksiai skaido duomenis dvi dalis po lygiai. iuo atveju labai paprasta teigti, kad algoritmo sudtingumas yra O(NlogN), o lyginimo operacij yra naudojama apie 2Nlog2N. Galima teigti, nors rodyti yra sudtingiau, kad ir laukiamu atveju galioja tokie vertinimai [3]. trumpus posekius, rekursijos eliminavim ir slenksio parinkim dmesys buvo atkreiptas ne veltui, nes i ypatybi tinkamas realizavimas gali pagreitinti Quicksort laik apie 25 - 30%. Element irinkimo sudtingumas taikant Quicksort metod laukiamu atveju yra tiesinis [3].

2.3. Skaitmeninis riavimas (radixsort)


Riuojami duomenys danai yra sudtingi, pvz., raai duomen bazse, ar telefon sraai, ar bibliotekiniai katalogai. Apie i ra lauk reikmes nieko apibrto negalima pasakyti. Tada galima tik iskirti dvi pagrindines operacijas - lyginimo ir keitimo vietomis - ir j atvilgiu vertinti vien ar kit riavimo algoritm. Taip buvo elgiamasi iki iol. Jei apie ra ar lauk reikmes galima pasakyti k nors papildomo, i informacij tikslinga panaudoti riavimo procedroms. iame skyriuje bus nagrinjami algoritmai, kai duomen reikms yra skaitmenins ir priklauso kokiam nors skaitiniam intervalui ar isiskiria panaiomis savybmis. Skaitmeninio riavimo algoritmuose duomen reikms interpretuojamos kaip skaiiai Mainje skaiiavimo sistemoje. Priklausomai nuo reikmi i-oje pozicijoje skaiiai gali bti suskirstyti M grupi, po to kiekviena i i grupi gali bti lygiai taip pat suskirstyta M pogrupi, priklausomai nuo reikmi j-oje pozicijoje, ir t.t.. vedus vienok ar kitok pozicij parinkimo dsn, gaunami isamiai apibrti skaitmeninio riavimo algoritmai. ia bus nagrinjami algoritmai esant M = 2 (turint omenyje kompiuterin realizacij), o pozicijos keisis pereinant nuo i prie i+1 arba i-1 arba jas grupuojant po dvi ir pan. ioje situacijoje, programuojant skaitmeninio riavimo algoritmus, tikslinga turti funkcijas tiesioginiam darbui su bitais. Standartinis Paskalis toki galimybi neturi, nors daugelio dabartini Paskalio realizacij darbo su bitais funkcijos vienaip ar kitaip yra realizuotos. Uraant algoritmus, programavimo kalbos tekste bus naudojama funkcija: function bits (x, k, j: integer): integer. Ji apibria dvejetain skaii, kur sudaro j bit, paimt i skaiiaus x dvejetains iraikos, praleidus k bit i deins. i funkcija ekvivalenti tokiai Paskalio instrukcijai: x (div 2k) mod 2j. Reikia pastebti, kad taikant skaitmenin riavim skaiiai turi bti ne tokie jau mai. Jei skaiiai nedideli ir kiekvien j sudaro ne daugiau kaip b bit, naudojant pasiskirstymo skaiiavimo algoritm duomenis galima riuoti taip, kad riavimo laikas tiesikai priklausyt nuo duomen kiekio. Belieka tik atmintyje iskirti 2b dydio lentel, kad b bit ilgio skaiiais galima bt laisvai disponuoti.
32

Duomen struktros ir algoritmai

Daniausiai naudojamos dvi skaitmeninio riavimo procedros: skaitmeninio keitimo (radix exchange sort) ir tiesioginio skaitmeninio riavimo (straight radix sort), besiskirianios apdorojam bit tvarka. Pirmasis metodas pagrstas leksikografine tvarka ir bit pozicijas numeruoja i kairs dein. Tai reikia, kad skaiiai, prasidedantys dvejetainiu nuliu, riuojamoje sekoje pasirodys anksiau negu skaiiai, prasidedantys dvejetainiu vienetu. Kai reikia dvejetaines pozicijas analizuoti ir skaiius keisti vietomis, procedr galima taikyti, panaiai kaip Quicksort algoritme: procedure radixexchange(l,r,b: integer); var t,i,j: integer; begin if (r>l) and (b=>0) then begin i:=l; j:=r; repeat while (bits(a[i],b,1)=0) and (i<j) do i:=i+1; while (bits(a[i],b,1)=1) and (i<j) do j:=j -1; t:=a[i]; a[i]:=a[j]; a[j]:=t; until j=i; if bits(a[r],b,1)=0 then j:=j+1; radixexchange(l,j-1,b-1); radixexchange(l,r,b-1); end end; Tiesioginio skaitmeninio riavimo metodas, skirtingai nuo skaitmeninio keitimo algoritmo, analizuoja bitus i deins kair. Jis i pradi riuoja duomenis pagal deiniausi pozicij, po to pagal prie tai esani pozicij, po to dar prie tai ir t.t. Elementams, kuri bitai j-1 pozicijoje sutampa, is metodas nekeiia tarpusavio tvarkos, t.y. jis yra stabilus. Labai panaiai elgdavosi senos skaiiavimo mainos, riuodamos perfokortas: procedure straightradix; var i,j,pass:integer; count:array[0..M]of integer; begin for pass:=0 to (w div m)-1 do begin for j:=0 to M-1 do count[j]:=0; for i:=1 to N do count[bits(a[i],pass*m,m)]:=count[bits(a[i],pass*m,m)]+1; for j:=1 to M-1 do count[j]:=count[j-1]+count[j]; for i:=N downto 1 do begin b[count[bits(a[i],pass*m,m)]]:=a[i]; count[bits(a[i],pass*m,m)]:=count[bits(a[i],pass*m,m)]-1; end; for i:=1 to N do a[i]:=b[i]; end; end;
33

Duomen struktros ir algoritmai

Abiej skaitmeninio riavimo algoritm savybs: 1. Radixexchange metodas naudoja apie NlgN bit lyginim. 2. Abu skaitmeniniai metodai, riuodami N skaii, kuri kiekvienas yra b bit ilgio naudoja maiau negu Nb bit lyginim. 3. Tiesioginis metodas riuoja N skaii, kuri kiekvienas b bit ilgio, kartodamas algoritm b/m kart (jei iskiriama papildoma atmintis 2m skaitliuki saugoti, o taip pat buferis pertvarkyti fail).

2.4 Prioritetins eils (priority queues)


Daugelio taikym duomenis tenka riuoti tik i dalies, nes pilnas riavimas nra btinas, arba kartais tenka riuoti tik duomen poaibius. Pavyzdiui, duomen bazse danai tenka sukaupti tam tikr kiek duomen, i j irinkti didiausi (maiausi), po to vl papildomai kaupti aib duomen, i j vl irinkti didiausi, ir t.t. ias operacijas atitinkaniai duomen struktrai netinka naudoti eils ar steko, ar kitos iki iol nagrintos duomen struktros. emiau nagrinjama duomen struktra yra geriau pritaikyta tokiai situacijai. Duomen struktra, vadinama prioritetine eile, pritaikyta operacijoms: inicializuoti aib i N element; konstruoti i aibs prioritetin eil (construct); terpti nauj element (insert); imesti didiausi element (remove); pakeisti didiausi element nauju, jei is nra didiausias (replace); pakeisti elemento prioritet (change); imesti bet kur nurodyt element (delete); sujungti dvi prioritetines eiles vien (join).

ios operacijos nra tiksliai apibrtos. Formalizuojant situacij, reikia jas patikslinti. Pirmiausia, jei aibje yra kelios didiausios reikms, imama bet kuri i j. Antra, operacija "pakeisti didiausi element nauju" yra beveik ekvivalenti operacijoms "terpti" ir "imesti", o skirtumas tarp j yra toks: naudojant dvi operacijas, prioritetin eil laikinai padidja vienu elementu. Treia, operacija "sujungti" kelia tam tikrus reikalavimus duomen saugojimo atmintyje struktrai. Taikymuose panaiai reikia analizuoti ir kitas duomen struktros operacijas. Reikia turti omenyje, kad prioritetinms eilms, nors ir turinioms detal formalizuot apraym, skirtingos DS realizacijos slygoja skirtingus algoritm darbo rezultatus. Taiau is realizacijos faktorius yra vienintelis, dalyvaujantis duomen struktros apibrimo kontekste. Prioritetini eili struktros nagrinjimas pradedamas nuo elementarios realizacijos (nesutvarkyto srao), kai programuojamos pagrindins operacijos naudojant masyv: procedure insert(v:integer); begin N:=N+1; a[N]:=v; end; function remove:integer; var j,max: integer; begin max:=1;
34

Duomen struktros ir algoritmai

for j:=2 to N do if a[j]>a[max] then max:=j; remove:=a[max]; a[max]:=a[N]; N:=N-1; end; itaip programuojant, skirting operacij vykdymo laikas gali labai skirtis, operacija insert visada vykdom per fiksuot laik, o operacijos remove ar delete savo ruotu gali pareikalauti perrinkti visus masyvo elementus. Kai prioritetin eil programuojama naudojant sutvarkyt sra, operacij atlikimo laikas i esms keiiasi - dabar jau operacijoms insert ar delete reikia laiko, proporcingo logN, o operacijai remove - fiksuoto laiko. Kai programuojant prioritetin eil masyvas keiiamas tiesiniu srau, operacij vykdymo laikas i esms nesikeiia, nepriklauso nuo to, ar tiesin sra interpretuosime kaip sutvarkyt ar nesutvarkyt sra, operacij sudtingumo analiz bus tokia pat. Pastebsime tik, kad operacijos delete ir join atliekamos per pastov laik. 2.4.1. Duomen struktra heap Viena i tinkam duomen struktr, garantuojani efektyv prioritetins eils operacij vykdym, yra vadinamoji heap struktra (kartais vadinama piramids metodu). Heap struktra tai pilnas dvejetainis medis, realizuotas naudojant masyv, kuriame nuorodos nukreiptos i tvo virns snus. Medis turi bti sutvarkytas pagal lygius, t.y. kiekvienai virnei patenkinama "heap" slyga: tvo reikms turi bti didesns u jo vaik reikmes. I ia iplaukia, kad didiausias aibs elementas turi bti medio aknyje. Kadangi medis pilnas, nesunku apskaiiuoti tv ar sn vietas masyve: jei tvas yra j-oje masyvo vietoje, jo sns bus 2j-oje ir (2j+1)-oje masyvo vietose. Todl nereikia naudoti joki speciali nuorod, o pereinant nuo tvo prie snaus ar atvirkiai, pakanka padauginti atitinkam indeks i 2 (ir gal bt pridti 1) arba atitinkamai atlikti div 2 operacij. Realizuojant prioritetins eils operacijas ioje struktroje, reiks vaikioti medio akomis. ak didiausias ilgis yra logN, todl visos prioritetins eils operacijos, iskyrus join, bus logN sudtingumo. Pavadinimo heap sinonimas masyvas, turintis dalinai sutvarkyto medio savyb. 2.4.2. Operacijos su heap struktra Visos prioritetins eils operacijos, realizuojamos heap struktroje, paprastai atliekamos taip: masyve apibriama vieta, nuo kurios pradedama operacija, pvz., naujas elementas visada terpiamas fiksuot (daniausiai paskutin) viet masyve; terptas elementas (ar elementas, esantis parinktoje vietoje) automatikai interpretuojamas kaip tam tikros virns snus; akoje nuo terpto elemento iki aknies yra tikrinama heap savyb; jei element reikms neatitinka heap slygos, jie keiiami vietomis.

35

Duomen struktros ir algoritmai

Programuojant heap struktr, atmintyje reikia apibrti masyv ir dar vien kintamj, kuriame bus fiksuojama operacijos pradios vieta ( kintamj ymsime raide N). Pavyzdiui, operacija insert bus realizuojama taip: nauj element terpiame masyve N+1 viet, o po to akoje tarp ios vietos ir aknies (t.y. masyvo pirmo elemento) tikriname heap savyb, ir, jei reikia, elementus keiiame vietomis. itokioje aplinkoje pastoviai bus naudojama operacija, kuri iekos tvo virns, ir kuri tikslinga programuoti kaip atskir procedr: procedure upheap(k:integer); var v:integer; begin v:=a[k]; a[0]:=maxint; while a[k div 2]=<v do begin a[k]:=a[k div 2]; k:=k div 2 end; a[k]:=v end; terpimo operacijos programa atrodys taip: procedure insert(v:integer); begin N:=N+1; a[N]:=v; upheap(N) end; Prioritetins eils operacija replace gali bti realizuota taip: nauj element raome medio akn, (pirm element masyve), po to stumiame t element emyn viena ir kita medio aka tol, kol jis atsiduria savo vietoje. ak, kuri reikia parinkti stumiant element emyn, slygoja didesnysis virns snus. Operacija remove atliekama labai panaiai: medio aknies viet raomas N-asis masyvo elementas, po to jis stumiamas emyn, panaiai kaip operacijoje replace tol, kol atsistos savo viet. Abi ios operacijos naudoja virns snaus radimo procedr: procedure downheap(k:integer); label 0; var i,j,v:integer; begin v:=a[k]; while k=<N div 2 do begin j:=k+k; if j<N then if a[j]<a[j+1] then j:=j+1; if v>a[j] then goto 0; a[k]:=a[j]; k:=j; end; 0: a[k]:=v end; Tada operacijos replace ir remove operacijos bus programuojamos taip:
36

Duomen struktros ir algoritmai

function replace(v:integer):integer; begin a[0]:=v; downheap(0); replace:=a[0]; end; function remove:integer; begin remove:=a[1]; a[1]:=a[N]; N:=N-1; downheap(1); end; Vis trij prioritetins eils operacij sudtingumas bus toks: Jei aibje yra N element, ioms operacijoms atlikti reiks maiau negu 2logN lyginim. 2.4.3. Heapsort algoritmas Naudojant ivardytas prioritetins eils operacijas, galima vesti ir realizuoti nauj riavimo algoritm (vadinamj heapsort): duomen aibei sudaryti heap struktr, po to spausdinti element, imetam remove operacijos metu, ir taip elgtis tol, kol aib nebus tuia. Visi imetami elementai isirikiuos majania tvarka. Formaliai uraytas algoritmas bus toks: N:=0; for k:=1 to M do insert (a[k]); for k:= M downto 1 do a[k]:= remove; iam algoritmui nereikia papildomos atminties, jo sudtingumas bus MlogM. Aiku, anksiau paraytos programos tekstas formaliai neatitinka duomen tip taisykli, nes tas pats kintamasis interpretuojamas ir kaip masyvo, ir kaip heap elementas, taiau itoks uraymas labai vaizdus. Realiai programuojant, programos tekst reikia rayti vientis, vengiant procedr bereikaling ikvietim. Truput geriau (logikiau) konstruoti heap struktr i apaios vir. Tada algoritmas bt programuojamas taip: procedure heapsort; var k,t:integer; begin N:=M; for k:=M div 2 downto 1 do downheap(k); repeat t:=a[1]; a[1]:=a[N]; a[N]:=t; N:=N-1; downheap(1) until N=<1; end; Tokio algoritmo realizavimo sudtingumas bus toks:
37

Duomen struktros ir algoritmai

heap struktra bus sudaroma per tiesin laik; heapsort algoritmui reiks maiau negu 2MlgM lyginim. 2.4.4. Netiesiogin heap duomen struktra

Daugelyje taikomj udavini nepageidautina raus kilnoti i vienos vietos kit, taiau juos riuoti vis tiek reikia. Heapsort algoritmas gali bti efektyviai pritaikytas ir tokiai aplinkai. Vietoje riuojam masyvo a ra galima operuoti su jo indeks masyvu p, apibriant j taip, kad elementas a[p[k]] nurodo heap struktros k-j element. Dl pilnumo reikia vesti kit masyv q, kuriame bt laikomos nuorodos viet, kuri heap struktroje uima k-asis masyvo a elementas. Naudojant iuos masyvus, heap struktr galima sudaryti taip: procedure pqconstruct; var k:integer; begin N:=M; for k:=1 to N do begin p[k]:=k; q[k]:=k end; for k:=M div 2 downto 1 do pqdownheap(k); end; Programuojant netiesiogin heap algoritm, reikia modifikuoti tik tas ankstesns programos vietas, kur kreipiamasi masyvo q elementus, pakeiiant juos atitinkamomis masyvo p reikmmis: procedure pqdownheap(k:integer); label 0; var j,v:integer; begin v:=p[k]; while k=<N div 2 do begin j:=k+k; if j<N then if a[p[j]]<a[p[j+1]] then j:=j+1; if a[v]=>a[p[j]] then goto 0; p[k]:=p[j]; q[p[j]]:=k; k:=j; end; 0: p[k]:=v; q[v]:=k end; Kitos netiesiogins heap duomen struktros operacijos - pqinsert, pqremove, ir t.t., - gali bti panaiai apraytos. Jei masyvo p reikms yra nuorodos atskirai saugomus raus, o ne masyvo a elementus, kaip k tik nagrintoje situacijoje, programuojant didesnis dmesys turi bti kreipiamas masyvo q sudarym ir manipuliavim jo elementais. ia nagrintos prioritetini eili realizacijos neapm operacijos join. Heap struktra yra per daug nelanksti ir per grieta, kad leist realizuoti operacij join logaritminiame laike kaip kitas prioritetini eili operacijas. Tam sukurtos kitos detalesns ir lankstesns struktros, tinkamos visoms prioritetini eili operacijoms. Jos gali bti naudojamos ne vien tik operacijos join, bet ir kitais atvejais, pvz., kai duomenis reikia laikyti ne viename vientisame masyve, bet keliuose
38

Duomen struktros ir algoritmai

atskiruose, logikai susietuose vien aib. Tokios struktros taip pat padeda laikytis principo, kad visas operacijas turime atlikti pagal viening metodik ir jos turi bti vienodo sudtingumo (pvz., logaritminis laikas). 2.4.5. Aibs duomen struktra Su k tik nagrinta duomen struktra heap yra susijusi aibs duomen struktra, t.y. duomenys, kuriems bdingos tokios operacijos: inicializuoti aib S (iskirti viet atmintyje ir parinkti dstymo metod joje); memberof (x, S) - funkcija, kuri patikrina ar elementas x priklauso aibei S; insert (x, S) - terpti element x aib S; delete (x, S) - paalinti element x i aibs S; join (S1, S2, S3) - sujungti dvi aibes S1 ir S2 vien S3; find (x) - rasti aib, kurioje yra elementas x; disjoin (x, S) - aib S iskaidyti dvi aibes, i kuri vienoje yra visi elementai, maesni ar lygs x, o kitoje - didesni u x (aib S tiesikai sutvarkyta); min (S) - rasti minimal aibs S element.

Operacijoms su aibmis taip pat priklauso aibi sjunga, aibi sankirta, aibi skirtumas ir aibi simetrinis skirtumas (operacijos, gerai inomos matematikoje). Jos nagrinjamos reiau. Dvi aibs yra atskirtos (disjoined), jei jos neturi bendr element. Daugel praktikoje aptinkam udavini galima suformuluoti taip, kad jie bt sprendiami vykdant vienoki ar kitoki operacij su aibmis sekas. Ypa tai pasakytina apie atskirtas aibes. vairiose operacijose su jomis kiekvienai i atskirt aibi gali atstovauti vienas elementas, pvz., minimalus (jei aib sutvarkyta), o tai danai bna paranku kompiuteriniam algoritmui, nes maina reikalingos atminties kiek ir operacij atlikimo sudtingum. Aibi elementai kompiuterio atmintyje dstomi vairiais bdais. Vienas i j - kiekvienai aibei iskirti po tiesin sra. Kiti galimi bdai - dstyti masyvuose ar mediuose. Kiekvienas i j turi sav privalum ir trkum. Toliau skyrelyje heapsort algoritmas bus pateiktas ir realizuotas, naudojant aibs duomen struktros operacijas. 2.4.6. Aibinis heapsort algoritmas Turime aib S, kurios elementus reikia sutvarkyti didjania tvarka. Aibs S elementams rayti kompiuterio atmintyje naudosime tiesin sra L. Tada heapsort algoritmas gali bti suformuluotas taip: for x on list L do insert (x,S); while not empty(S) do begin y:=min (S); writeln(y); delete (y,S) end Kad bt patogiau manipuliuoti tiesinio srao elementais, tarkime, kad jis idstytas masyve A. Tada heap savybs tikrinamos taip:
39

Duomen struktros ir algoritmai

procedure pushdown (first, last: integer); var r: integer; begin r:=first; while r=<last div 2 do if r=last div 2 then begin if A[r].key>A[2*r].key then swap(A[r],A[2*r]); r:=last end else if A[r].key>A[2*r].key and A[2*r].key=<A[2*r+1].key then begin swap(A[r],A[2*r]); r:=2*r end else if A[r].key>A[2*r+1].key and A[2*r+1].key<A[2*r].key then begin swap(A[r],A[2*r+1]); r:=2*r+1 end else r:=last end; Pilna heapsort programa bt tokia: procedure heapsort; var i: integer; begin for i:=n div 2 downto 1 do pushdown(i,n); for i:=n downto 2 begin swap(A[1],A[i]); pushdown(1,i-1) end end;

2.5 Slajos riavimas (mergesort)


Labai danai apdorojant duomenis reikia gan didel suriuot fail terpti tam tikr kiek nauj duomen, po to j vl suriuoti. Galima elgtis dvejopai: i pradi duomenis terpti fail, o po to riuoti, arba atvirkiai, i pradi duomenis suriuoti, o po to abu failus sulieti. Btent pastarj metod ir nagrinsime. Slajos (merge) procesas sujungia dvi arba kelias duomen aibes vien ir tam tikra prasme yra prieingas irinkimo (selection) operacijai. iame skyriuje nagrinsime algoritmus, kai liejami du failai. Jei jie jau suriuoti, nesunku sugalvoti procedr, kuri per tiesin laik, t.y. po vien kart nuskaitydama kiekvien abiej fail element, sukurt nauj suriuot fail: procedure merge (a, b); var a,b,c: array [1..M + N)] of integer; begin i:=1; j:=1; a[M+1]:=maxint; b[N+1]:=maxint;
40

Duomen struktros ir algoritmai

for k:=1 to M+N do if a[i]<b[j] then begin c[k]:=a[i]; i:=i+1 end else begin c[k]:=b[j]; j:=j+1 end; end; i programa yra maksimaliai suprastinta, joje netgi panaudoti signaliniai ymenys (kintamasis maxint), kuri reikms didesns u bet kokias galimas masyv a ir b element reikmes. Be to, akivaizdu, kad masyvas c sujungia masyvus a ir b ir jam reikia papildomos atminties. i programa naudoja M+N lyginim. J galima tobulinti, stengiantis daugiausia sumainti naudojamos atminties tr, taikant terpimo metod duomen vedimo metu ir pan. Taiau tokie patobulinimai kelia daug slyg realizacijai ir j komplikuoja. Merge procedra tinkama manipuliacijoms su tiesiniais sraais. Papildoma atmintis tokiu atveju naudojama tik vienai nuorodai rayti, o programa atrodo taip: type link=^node; node=record key: integer; next: link end; var t,z:link; N: integer; function merge(a,b:link):link; var c:link; begin c:=z; repeat if a^.key=<b^.key then begin c^.next:=a; c:=a; a:=a^.next end else begin c^.next:=b; c:=b; b:=b^.next end until c^.key=maxint; merge:=z^.next; z^.next:=z; end; Slajos procedr galima taikyti riavimui, sukurti keli riavimo algoritmai. Vienas i j paprastas pateiktas iame skyrelyje. Idja yra paprasta: duomenis skaidome dvi dalis, kiekvien i j riuojame, po to suliejame. Tam, kad suriuoti kiekvien i suskaidyt dali, rekursyviai taikome joms t pai procedr. Pateikiamoje programoje masyvas a[1..r] skirtas ieities duomenims saugoti, o masyvas b[1..r] yra pagalbinis: procedure mergesort(l,r: integer); var i,j,k,m: integer; begin if r-l>0 then begin m:=(r+l) div 2; mergesort(l,m); mergesort(m+1,r); for i:=m downto l do b[i]:=a[i]; for j:=m+1 to r do b[r+m+1-j]:=a[j]; for k:=l to r do if b[i]<b[j] then begin a[k]:=b[i]; i:=i+1 end else begin a[k]:=b[j]; j:=j-1 end; end; end;

41

Duomen struktros ir algoritmai

Slajos algoritmas, realizuotas naudojant tiesin sra, riuoja duomenis nekeldamas juos i vienos vietos kit ar keisdamas vietomis, bet keisdamas nuorod reikmes. Be to kiekvienas sraas, atstovaujantis duomen dalims, kurios formuojamos programoje, baigiasi nuoroda t pat unifikuot element. Programa pateikiama kaip funkcija, kurios argumentas yra nuoroda nesuriuot fail, o reikm yra nuoroda suriuot fail: function mergesort(c:link):link; var a,b:link; begin if c^.next=z then mergesort:=c else begin a:=c; b:=c^.next; b:=b^.next; b:=b^.next; while b<>z do begin c:=c^.next; b:=b^.next; b:=b^.next end; b:=c^.next; c^.next:=z; mergesort:=merge(mergesort(a),mergesort(b)); end; end; Kaip ir bet kurio kito, io algoritmo rekursyvi realizacij galime pakeisti nerekursyvia. Slajos riavimo atveju tam reikia keisti duomen grupavimo tvark ir naudoti vadinamj i apaios vir (bottom-up) metod: imami atskiri elementai ir interpretuojami kaip vienetinio ilgio duomen rinkiniai, po to jie suliejami, gaunant suriuotus 2 ilgio rinkinius, po to ie rinkiniai suliejami, gaunant 4 ilgio duomen rinkinius, ir t.t.: function mergesort(c:link):link; var a,b,head,todo,t:link; i,N: integer; begin N:=1; new(head); head^.next:=c; repeat todo:=head^.next; c:=head; repeat t:=todo; a:=t; for i:=1 to N-1 do t:=t^.next; b:=t^.next; t^.next:=z; t:=b; for i:=1 to N-1 do t:=t^.next; todo:=t^.next; t^.next:=z; c^.next:=merge(a,b); for i:=1 to N+N do c:=c^.next until todo=z; N:=N+N; until a=head^.next; mergesort:=head^.next end; Slajos riavimo algoritmo sudtingumas ir savybs yra tokios: nepriklausomai nuo duomen, naudoja apytikriai NlogN lyginim; naudoja papildom atmint, kurios tris proporcingas duomen kiekiui N; algoritmas yra stabilus;
42

Duomen struktros ir algoritmai

algoritmo darbas nepriklauso nuo duomen tvarkos; darb galima pagerinti, kombinuojant j su kitais riavimo metodais.

2.6. Iorinis riavimas (external sorting)


Apdoruojant informacij labai danai pasitaiko atvej, kai disponuojama labai dideliais duomen failais ar rinkiniais, kurie yra riuojami ir netelpa kompiuterio vidinje atmintyje. Tuo atveju anksiau nagrinti algoritmai netinka, vietoj j yra naudojami vadinamieji ioriniai riavimo metodai. Du pagrindiniai faktoriai i esms skiria vidinio ir iorinio riavimo algoritmus: kadangi dauguma duomen saugomi antrinje (diskinje) ar netgi tretinje atmintyje, elemento irinkimas i iorins atminties trunka kur kas ilgiau, negu tkstaniai lyginimo ar keitimo vietomis operacij ar kitoki skaiiavim vidinje atmintyje; duomen failai, saugomi iorinje atmintyje, turi savus duomen irinkimo ar paiekos metodus, kuri negalima atsisakyti ar pakeisti (pvz., magnetinje juostoje duomenis galima irinkti tik nuosekliai).

Todl iorinio riavimo atveju, kuriant ar taikant vienok ar kitok algoritm, reikia atsivelgti visus duomen apdorojimo veiksnius ir etapus. Pilnos duomen apdorojimo sistemos svoka ia lygiai tokia pat svarbi kaip ir algoritmo. Dauguma iorinio riavimo metod naudoja toki strategij: jie periri fail ir suskaido j blokus, tinkamus rayti vidinje atmintyje; kiekvien i i blok suriuoja; suriuotus blokus sulieja vis didesnius, procesas tsiamas tol, kol gaunamas vienas suriuotas failas. itokia strategija veria program daug kart kreiptis iorin rengin, skaitant fail ar raant j. Todl norint parinkti efektyv iorinio riavimo algoritm, reikia kreipti dmes ne tik lyginimo ar keitimo vietomis operacij skaii, kaip bucvo daroma anksiau, bet ir mainti vedimo ar ivedimo operacij skaii ir j vykdymo laik. Iorinio riavimo metodai, sukurti, kai duomenys dar buvo saugomi perfokortose ir popierinse perfojuostose, naudojami ir dabar riuoti diskuose ir magnetinse juostose, jie bus reikalingi ir ateityje, riuojant duomenis domeninje atmintyje (bubble-memory) ir videodiskuose. Verlus technologij vystymasis kelia jiems daug reikalavim, veria juos adaptuoti vis sudtingesnei kompiuterinei aplinkai. Pvz., riavimo metodai dabartinse multimedia sistemose kompiuterin atmint skirsto pirmin, antrin, tretin, i kuri kiekviena turi didels takos riavimo greiiui ir algoritmams. I tikrj situacija yra dar sudtingesn. iuolaikiniuose kompiuteriuose vidin atmintis nra vienar, jos sudtins ar j aptarnaujanios dalys yra ir superoperatyvioji atmintis (cache memory), ir buferin atmintis (buffer memory). Duomen irinkimo greiiai iose dalyse irgi yra skirtingi. Aiku, kad riavimo metodai galingose kompiuterinse sistemose turi gerai inaudoti ir iuos skirtumus. Iorinio riavimo algoritmai ne tik riuoja duomenis failuose, bet ir juos sulieja, todl dar jie vadinami riavimo-slajos algoritmais (sort-merge). 2.6.1. Subalansuota daugybin siaja (balanced multiway merging) Tarkime, reikia suriuoti pakankamai didelio failo raus, o vidinje atmintyje telpa tik trys raai. Sakykime, kad turime neribot kiek magnetini juost (nuoseklaus irinkimo rengini), ir eiliniam suliejimui naudosime bet kurias tris i j. Tada pirmiausia i pirminio failo skaitome nuosekliai po tris raus, juos riuojame ir blokus po tris raus pakaitomis ir nuosekliai raome tris skirtingas juostas. Toliau vykdomos suliejimo procedros. Po vien ra i kiekvienos juostos skaitoma atmint ir maiausias i j raomas nauj juost. Vl kreipiamasi juost, kurioje buvo
43

Duomen struktros ir algoritmai

maiausias raas, ir i jos skaitomas naujas raas, vl maiausias i j raomas juost. Taip tsiama tol, kol nepasibaigs blokas juostoje, i kurios skaitoma, po to ta juosta ignoruojama, o i likusi dviej juost skaitomi ir suliejami likusieji raai. Taip naujoje juostoje suformuojamas blokas i devyni element. Jei dar blok yra, i procedra gali bti tsiama. Po to vl t pai porcedr galima taikyti naujai suformuotoms trims juostoms, kuriose idstyti devyni element ilgio blokai. i aprayta procedra taikoma daugeliui gan efektyviai veikiani riavimo-slajos algoritm, kurie subalansuotai naudoja nuoseklaus irinkimo iorinius renginius. Balansuotumas reikia tolyg iorini atminties rengini darbo paskirstym. 2.6.2. Pakeitimo irinkimas (replacement selection) Riavimo-slajos algoritmams galima natraliai ir efektyviai pritaikyti prioritetines eiles. Pirmiausia slajos metu, kai reikia irinkti i suliejam element minimal, tikslinga naudoti heap struktr ir jos operacij replace, kuri pakeiia i karto ankstesnio algoritmo dvi operacijas minimalaus elemento raym iorin atmint ir naujo elemento terpim. Taip sumainamas atliekam operacij skaiius. Aiku, heap struktr reikia naudoti nuosekliai, t.y. jau pirminiame etape, kai elementai skirstomi blokus ir riuojami, tikslinga juos idstyti heap struktr ir suriuoti tik i dalies. Be to (tai yra dar svarbiau), prioritetini eili struktros panaudojimas galina slajos metu gauti ilgesnius suriuotus blokus, negu jie tilpt vidin atmint. Kai ieities duomenys yra tvarkomi heap struktr ir minimalus elementas yra keiiamas nauju, reikia papildomai naudoti toki taisykl: jei naujas elementas, raomas vietoje minimalaus elemento senoje heap struktroje, yra maesnis u j, reikia nuo io elemento pradti nauj blok ir nauj heap struktr, interpretuojant j esant didiausiu ioje struktroje. Algoritmai, naudojantys ias taisykles, yra vadinami pakeitimo irinkimo vardu. Algoritmai, sukurti naudojant idstytus ir panaius principus, turi tokias j efektyvum vertinanias savybes: riavimo-slajos algoritmai, riuojantys N ra, kai vidin atmintis talpina M ra ir duomenys raomi (P+1)- iorin rengin, perrinks iuos duomenis 1 + logP(N/2M) kart; pakeitimo irinkimo algoritmai, esant atsitiktiniams duomenims, formuoja duomen blokus dvigubai ilgesnius negu naudojama heap struktra.

44

Duomen struktros ir algoritmai

3. Paieka
3.1. Elementars paiekos metodai
Paieka yra viena i fundamentali kompiuteri darbo operacij. Jos esm - dideliame informacijos rinkinyje rasti tam tikr duomen element arba patvirtinti, kad jo ten nra. Remiantis kai kuriais vertinimais, paiekos operacijos uima iki 30% kompiuterio darbo laiko [1]. Duomen vienetai, su kuriais tenka manipuliuoti iose operacijose, daniausiai atitinka raus, susidedanius savo ruotu i lauk. Tokiu atveju paiekos metu reikia rasti raus, kuri tam tikras laukas turi konkrei reikm. i situacija kompiuteri taikymuose pasitaiko daniausiai, todl ji pagrindinai ir bus nagrinjama. rao laukas, kurio reikm naudojama paiekoje, vadinamas raktu (key). Paiekos procese danai pasitaikani duomen struktr pavyzdiai yra odynai ir simboli lentels. Beveik kiekvienas tekst redaktorius suteikia galimyb vartotojui patikslinti odi teising raym (spelling). Tam naudojami angl ar kokios kitos kalbos odynai. Tikslinant rayb, kompiuteriui reikia rasti odyne visus odius, besiskirianius nuo duoto viena ar dviem raidmis, nesvarbu, kurioje pozicijoje. Akivaizdu, kad nor lengva formuluoti, bet jam realizuoti reikia sudtingo algoritmo. Simboli lenteli formavimas ir paieka jose yra kitas labai panaus udavinys, danai sutinkamas programavime. Simboli lentels yra pagrindiniai duomenys kompiliatoriams, program bibliotekoms ir pan. Paieka jose vyksta lygiai taip pat, kaip ir odynuose. Paiekos laukai yra kintamj ar kit program simboli vardai, o raai - informacija, apraanti vardo viet programoje, kiti atributai. Paiekos metu naudojamos tokios operacijos: initialize (iskirti viet kompiuterio atmintyje); search (rast ra, kuriame yra konkreti rakto reikm); insert (terpti nauj ra); delete (imesti tam tikr ra); join (sulieti du odynus vien); sort (riuoti raus arba odyn).

Gana danai vairiuose taikomuosiuose algoritmuose ivardytos operacijos naudojamos ne tik savarankikai ar paskirai, bet ir jungiamos grupes. Taip paaikinama didel paiekos procese dalyvaujani duomen struktr vairov bei j specifika. Didels takos paiekos algoritmams turi raai su pasikartojaniomis rakt reikmmis. Jie yra apdorojami kitokiais algoritmais, negu raai be pasikartojani rakto reikmi. Pagrindins algoritm ir duomen struktr, nagrinjam iame skyriuje, operacijos initialize, search, insert, ir delete. Kartais reiks operacijos sort. Kaip ir prioritetini eili atveju, operacijai join realizuoti reikia sudtingesns procedros, kuri galt bti nagrinjama kituose specialiuose kursuose. Algoritmus, atliekanius paiek rauose be pasikartojani rakto reikmi, galima pritaikyti paiekai ir rauose su pasikartojaniomis reikmmis. Tai galima padaryti keliais bdais. Vienas i j - paiekos operacijos vykdomos raams be pasikartojani rakto reikmi, o raai su ta paia rakto reikme raomi atskir sra su nuorod sra i tam tikro rao. Kitas bdas - visi raai raomi kompiuterio atmintyje naudojant viening duomen struktr, o paiekos metu randamas tik vienas raas i keli galim. is bdas paprastesnis realizuoti, bet gali neatitikti kit keliam paiekai reikalavim. bd tenka papildyti kitais algoritmais, kai reikia rasti visus raus su tam tikru raktu. Treias bdas - kiekvienam raui priskirti unikal identifikatori (kod) ir j naudoti paiekos operacij metu (vietoje paiekos rakto reikms).
45

Duomen struktros ir algoritmai

3.1.1. Nuosekli paieka Paprasiausias paiekos algoritmas yra nuosekli paieka - nuoseklus vieno po kito element perrinkimas. Tariant, kad elementai yra saugomi masyve, paiek lengva apibrti iomis operacijomis: operacija insert - elemento raymas laisv viet masyve; operacija search - nuoseklus masyvo element perrinkimas iki tol, kol bus sutikta reikiama elemento reikm; operacija delete -surasto elemento paalinimas i masyvo. Paiekos algoritm realizuojanti programa bt tokia: type node=record key,info: integer end; var a: array [0..maxN] of node; N: integer; procedure initialize; begin N:=0 end; function seqsearch(v:integer; x:integer):integer; begin a[N+1].key:=v; if x=<N then repeat x:=x+1 until v=a[x].key; seqsearch:=x end; function seqinsert(v:integer):integer; begin N:=N+1; a[N].key:=v; seqinsert:=N; end; Vertinant algoritmo sudtingum, tikslinga inoti lyginim skaii, nes tai pagrindin algoritmo operacija. Jis reikalauja vidutinikai (N + 1)/2 lyginim. Nuosekli paiek galima realizuoti ir naudojant sra. iuo atveju raai turi bti suriuoti, nes tai pagreitina algoritmo darb. Programa, realizuojanti nuosekli paiek, bt tokia: type link=^node; node=record key, info:integer; next :link end; var head,t,z:link; i:integer; procedure initialize; begin new(z); z^.next :=z; new(head); head^.next :=z; end; function listsearch(v:integer; t :link):link; begin z^.key:=v; repeat t :=t^.next until v=<t^.key;
46

Duomen struktros ir algoritmai

if v=t^.key then listsearch:=t else listsearch:=z end; Algoritmas pagreitja todl, kad paiekos atveju suradus rakt, didesn u duot, galima teigti, kad paieka buvo neskminga, ir baigti darb. Tokiu atveju vidutinikai reiks lyginti tik pus ra. Taiau tokios prielaidos atveju reikia, kad operacijos insert ir delete irgi nekeist suriuot element tvarkos. terpimo operacijos programa iuo atveju bt tokia: function listinsert(v:integer; t :link):link; var x:link; begin z^.key:=v; while t^.next^.key<v do t:=t^.next ; new(x); x^.next :=t^.next ; t^.next :=x; x^.key:=v; listinsert:=x; end; Nuosekli paieka naudos N/2 lyginim ir skmingu ir neskmingu atvejais. Jei iekom rakt danumai inomi, tai algoritmo darb gali pagreitinti ra riavimas j danum majimo tvarka. Jei tokie danumai neinomi, efektyvi priemon yra patalpinti pirm kart surast ra srao pradi. 3.1.2. Dvejetain paieka Jei ra, kuriuose iekoma, yra daug, nuoseklios paiekos laikas juose gali bti labai ilgas. Jis gali ymiai sutrumpti, taikant paiekos algoritmams "skaldyk ir valdyk" paradigm. iuo principu yra sudaromi dvejetains paiekos algoritmai, kurie veikia panaiai kaip quicksort. Duomenys yra laikomi suriuotame faile. Paiekos metu jie yra skaidomi dvi lygias dalis (kair ir dein) ir iskiriamas ribinis elementas (maiausias tarp deins dalies ir didiausias tarp kairs dalies element). Iekomas raktas lyginamas su ribiniu elementu, ir jei jis maesnis u ribin, paieka tsiama kairioje dalyje, o jei didesnis - deinje dalyje. Programa, realizuojanti tok algoritm, atrodyt taip: function binarysearch(v: integer): integer; var x,l,r: integer; begin l:=1; r:=N; repeat x:=(l+r) div 2; if v<a[x].key then r:=x-1 else l:=x+1 until (v=a[x].key) or (l>r); if v=a[x].key then binarysearch:=x else binarysearch:=N+1 end; Panaiai kaip algoritmai quicksort ir radix, is metodas naudoja rodykles l ir r, iskiriant analizuojam duomen dal. Dvejetain paieka reikalauja lgN+1 lyginim skmingu ar neskmingu atvejais. Taiau laikas, reikalingas terpimo operacijai, kai programuojama naudojant masyv, yra
47

Duomen struktros ir algoritmai

didelis. Elementus masyve reikia laikyti suriuotus, vadinasi, terpiant nauj element tam tikr viet kitus reikia perkelti toliau - masyvo pabaig. Todl dvejetains paiekos algoritm verta naudoti tada, kada i pradi galima beveik pilnai suformuoti fail (t.y. paiekos metu beveik nepasitaikys terpimo operacij), o po to naudoti tik paiek (daug kart). algoritm sunkiau programuoti, kai yra pasikartojantys raktai, nes ribinis elementas gali atsidurti tarp keli lygi. Tokiu atveju bus sunku sprsti, kuri dal - kair ar dein - toliau analizuoti, ypa kai reikia rasti visus raus su tuo paiu raktu. Dvejetains paiekos algoritm galima patobulinti, dalijant duomenis ne dvi lygias dalis, o nustatant ribin element pagal iekomo rakto reikm. Tarkime, telefon knygoje reikia rasti od, prasidedant raide H. Knyg nebtina ir netikslinga versti ties viduriu, ia efektyvu yra vesti interpoliacin paiek. Formaliai tai reikia, kad interval tarp l ir r reikia dalyti dvi dalis ne per pus, bet interpoliacins formuls l+(v-a[l].key)*(r-l) div (a[r].key - a[l].key) rekomenduojamu santykiu. ia rakto v reikm yra spjama vieta tarp rakt a[l] ir a[r] reikmi. Tokio modifikuoto algoritmo sudtingumas bus apie lglgN+1 lyginim. Taiau is metodas gali bti efektyviai taikomas tik kai rakt reikms yra pasiskirst tolygiai. Be to, maoms N reikmms funkcijos lg ir lglg nedaug skiriasi. Kita vertus, interpoliacij tikslinga naudoti, kai duomen failai dideli, ra ar rakt lyginimai reikalauja daug laiko snaud arba duomenys laikomi iorinje atmintyje ir j irinkimas (t.y. perklimas vidin atmint) yra labai ilgas. 3.1.3. Dvejetainio medio paieka Dvejetainio medio paiekos algoritmas naudoja dvejetains paiekos ir interpoliacins paiekos principus, juos pritaikydamas visoms operacijoms (terpimo, imetimo, ir t.t.). Tai paprastas, efektyvus dinaminis metodas, jis yra vienas i fundamentali algoritm informatikoje aibs. Duomenims dstyti algoritmas naudoja dvejetain med, o terpimo ar imetimo operacijoms toki taisykl: visos virns, maesns u duot, turi bti talpinamos kairiajame pomedyje, o visos didesns ar lygios - deiniajame. Paiekos operacija iame algoritme - tai tik jimas tam tikra medio aka. Dvejetain paieka skiriasi nuo dvejetainio medio paiekos ne tik tuo, kaip dalijami elementai dalis, bet ir tuo, kad pastaruoju atveju yra formuojama duomen struktra. Programa, realizuojanti algoritm, bt tokia: type link=^node; node = record key, info: integer; l,r: link end; var t,head,z:link; function treesearch(v:integer; x:link):link; begin z^.key:=v; repeat if v<x^.key then x:=x^.l else x:=x^.r until v=x^.key; treesearch:=x end; Algoritm programuojant, verta apibrti kintamj head, kurio dein nuoroda bt nukreipta medio akn, kair nuoroda bt nil, o reikm bt maesn u vis kit virni
48

Duomen struktros ir algoritmai

reikmes. Norint isaugoti kintamj vienarikum, vis kit virni nuorodas, kai jos laisvos, reikia nukreipti vien (dummy) virn z. Kitas galimas atvejis - reikia iskirti du virni (ir ra) tipus: vidines ir iorines virnes. Tuio medio inicializacijos programa bt tokia: procedure treeinitialize; begin new(z); z^.l:=z; z^.r:=z; new(head); head^.key:=0; head^.r:=z; end; Norint terpti virn med, reikia atlikti neskming paiek ir nauj virn terpti kaip sn prie tos virns, kur paieka usibaig: function treeinsert(v:integer; x: link): link; var p:link; begin repeat p:=x; if v<x^.key then x:=x^.l else x:=x^.r until x=z; new(x); x^.key:=v; x^.l:=z; x^.r:=z; if v<p^.key then p^.l:=x else p^.r:=x; treeinsert:=x end; Norint terpti nauj ra tuo atveju, kai jau toks dvejetainiame paiekos medyje yra, reikia j terpti kaip dein sn tos virns, kuri jam lygi. Jei reika suriuoti duomenis, belieka tik esam med atspausdinti, perenkant visas jo virnes i kairs dein, ignoruojant jas jungianius ryius. procedure treeprint(x: link); begin if x<>z then begin treeprint(x^.l); printnode(x); treeprint(x^.r) end end; is riavimo metodas labai panaus quicksort algoritm, skirtumas tik toks, kad pastarasis medio riavimas naudoja gan daug papildomos atminties ryiams tarp virni isaugoti, tuo tarpu quicksort algoritmas tokiems ryiams atminties naudoja labai maai. Algoritmo efektyvumas labai priklauso nuo dvejetainio medio formos, teisingiau nuo jo subalansuotumo. Jei dvejetainis paiekos medis yra subalansuotas, algoritmas naudos 2lnN lyginim. Blogiausiu atveju algoritmas naudos N lyginim. 3.1.4. Operacija delete
49

Duomen struktros ir algoritmai

terpimo, paiekos ir riavimo operacijos dvejetainiame paiekos medyje yra realizuojamos gan paprastai ir tiesmukikai. Taiau elemento imetimo (delete) operacija yra ymiai sudtingesn programuoti, j verta nagrinti kaip rekurentins procedros paiekos algoritmuose pavyzd. Paalinti virn i medio yra nesudtinga, kai ji neturi sn arba turi tik vien sn. Taiau paalinant virn, turini du snus, reikia virni vietas medyje pertvarkyti. Dvejetainiams paiekos mediams iuo atveju naudojamas toks principas - imetamos virns viet reikia terpti virn, kit pagal didum. Aiku, kad is principas yra optimalus paiekai, bet jo realizavimas gali kartais priversti i pagrind pakeisti medio struktr. Toki situacij verta iliustruoti pavyzdiais: procedure treedelete(t,x: link); var p,c:link; begin repeat p:=x; if t^.key<x^.key then x:=x^.l else x:=x^.r until x=t; if t^.r=z then x:=x^.l else if t^.r^.l=z then begin x:=x^.r; x^.l:=t^.l end else begin c:=x^.r; while c^.l^.l<>z do c:=c^.l; x:=c^.l; c^.l:=x^.r; x^.l:=t^.l; x^.r:=t^.r end; if t^.key<p^.key then p^.l:=x else p^.r:=x; end; Programuojant algoritm, reikia perrinkti ne tik daug atvej, bet ir naudoti vairius programavimo triukus. Pavyzdiui, tikslinga iekoti kitos dar prie imetant tam tikr virn, o ne po to. Algoritmas taip, kaip ia pateiktas, atrodo asimetrinis - visada irenkamas pirmiausia deinys snus, nors kartais duomenys yra taip isidst, kad tikslingiau bt irinkti kairj sn. Toki programos patobulinim gali bti daug. 3.1.5. Netiesioginiai dvejetains paiekos mediai Daniausiai reikiai tik ra paiekos, o ne terpimo, imetimo ar kit tiesioginio manipuliavimo su raais operacij. Tokio taikymo pavyzdys - bibliotekins informacins sistemos. Jose raai bna suformuoti i anksto arba tai daroma iskirtiniu laiko momentu, o informacini sistem funkcionavimo metu vykdomos tik paiekos operacijos. Norint pagreitinti tokios sistemos darb, kartais reikia sukurti papildomas rodykles, kurios padt lengvai rasti rao viet dokument rinkinyje. Taigi, reikia sukurti indeks, nurodant masyvo elementus. Dvejetains paiekos medius taikyti tokiai situacijai galima keliais bdais. Vienas i j virni informacin dal naudoti ne rakt reikmms saugoti, o rao viet masyve nuorodoms. Antras bdas - virni informacinse dalyse sudaryti rakt reikmi kopijas. Treias - rakt reikmes kopijuoti atskir masyv, o virnse saugoti io naujo masyvo element nuorodas. Taikant visus iuos ar kitus netiesioginio paiekos medio realizavimo bdus, turimus ryius, t.y. nuorodas, galima realizuoti naudojant rodykls tip arba masyv. Jei ryiai realizuojami naudojant masyv, bet kuri nuoroda yra raoma masyvo elementuose. Tada nra btinybs kurti
50

Duomen struktros ir algoritmai

naujus raus (procedra new). itoks bdas naudojamas daugelyje taikomj program, ypa kai dirbama su dideliais duomen kiekiais (taiau j skaiius taiau i anksto gali bti vertintas). Dvejetaini paiekos medi snus nuorodoms realizuoti galima naudoti ir kelis lygiagreius masyvus, vienas i j gali rodyti kairiuosius snus, kitas deiniuosius, ir t.t. Dar kiti masyvai gali bti naudojami atskiroms medi akoms ar -pan. iskirti. Tokios programos dirba labai greitai, yra lanksios, jas nesudtinga papildyti, nors jos ir netaupo atminties.

3.2 Subalansuoti mediai.


Algoritmai, naudojantys dvejetainius medius, gali dirbti labai greitai, bet gali ir labai ltai, j efektyvumas labai svyruoja (daniausiai priklausomai nuo duomen). Ypa j efektyvumas krinta blogiausiu atveju. Nepalanks atvejai yra, kai duomenys pilnai suriuoti, arba idstyti atvirktine tvarka, arba paeiliui didelis keiia ma, arba idstyti vienas po kito kokia nors kitokia reguliaria tvarka. itokia ypatyb buvo aptikta ir anksiau, kituose algoritmuose. Pavyzdiui, quicksort algoritmo atveju prie riuojant duomenis rekomenduotina atsitiktinai sumaiyti arba bent jau atsitiktiniu bdu rinkti dalijant element. Tokios rekomendacijos nors ir maina blogiausio atvejo tikimyb, taiau turi tik statistin pobd ir negarantuoja, kad jo galima ivengti. Dvejetaini medi atveju yra geriau, jiems galima apibrti reguliarias struktras, valdanias algoritm efektyvum ir galinanias i viso ivengti blogiausi atvej. Pagrindins ir labiausiai paplitusios tokios struktros yra subalansuoti mediai. Jie remiasi vadinamaisiais balansavimo metodais - paradigma, panaia skaldyk ir valdyk. Taiau balansavimo metodai, gerinantys algoritm efektyvum, turi vien bendr blog savyb - juos lengviau formuluoti, negu realizuoti. 3.2.1. 2-3-4 ir 2-3-mediai Blogiausias dvejetaini medi algoritm atvejis yra, kai dauguma virni turi tik po vien sn, ir todl struktra yra beveik tiesin. Balansavimo principas draudia toki bsen, t.y. kiekviena virn turi turti daugiau negu vien sn. Kita vertus, struktra turi bti pakankamai lanksti, kad leist aprayti daugel reali situacij. Todl subalansuotiems mediams leidiama turti ne tik 2, bet ir daugiau sn. 2-3-4-mediuose kiekvienai virnei leidiama turti ne maiau kaip 2 ir ne daugiau kaip 4 snus. Tokio medio virns vadinamos 2-virne (atitinkamai 3virne, 4-virne), jei ji turi 2 snus (atitinkamai 3 snus, 4 snus). Be to, kiekvienai virnei yra priskiriami raai: 2-virnei - vienas raas; 3-virnei - du raai; 4-virnei - trys raai. J reikms skirtos pomedi minimalioms reikmms saugoti. Vieninteliame 2-virns rae bus saugoma minimali reikm, kuri galima rasti deinio snaus pomedyje. Viename 3-virns rae bus saugoma minimali reikm, kuri galima rasti vidurinio snaus pomedyje, o kitame rae minimali reikm, kuri galima rasti deinio snaus pomedyje. Viename 4-virns rae bus saugoma minimali reikm, kuri galima rasti antro snaus pomedyje, kitame rae bus saugoma minimali reikm, kuri galima rasti treio snaus pomedyje, o treiame rae - minimali reikm, kuri galima rasti deinio snaus pomedyje. Taip suformuoti raai virnje leidia automatikai nustatyti minimal ir maksimal elementus, esanius kiekviename pomedyje, ir tokiu bdu paiekos operacij atlikti per logaritmin laik. Kad paieka bt i tikrj vienar, apibriant subalansuot med dar reikalaujama, kad visos akos bt vienodo ilgio. Paieka pradedama nuo medio aknies, ir toliau tsiama tame pomedyje, kurio reikmi intervale yra iekoma rakto reikm. Ji visada ubaigiama akos lape. 2-3-4-medio pavyzdys parodytas 11 pav.

51

Duomen struktros ir algoritmai

S DM AAB EIL NO SSS T UU

A A A B D E I L M N O S S S S T U U 11 pav. Sakinio SUBALANSUOTAS MEDIS 2-3-4-medis terpimo procedra 2-3-4-medyje vykdoma taip: atliekame neskming paiek ir nustatome viet, kur nauja virn turi bti terpta. Jei tai 2- ar 3-virn, tai prijungdami nauj sn j pertvarkome 3- ar 4-virn. Jei tai 4-virn, j skaidome dvi 2-virnes ir prie vienos i j prijungiame nauj. Jei virn, kurios snus buvo pastaroji 4-virn, yra 2- arba 3-virn, terpimo procedra baigta. Jei i virn savo ruotu buvo 4-virn, j irgi reikia skaidyti dvi virnes. is procesas kartojamas tol, kol naujai pertvarkoma virn yra 4-virn. terpimo operacijos metu 4-virns yra skaidomos dvi virnes. Jei skaidoma taip, kaip k tik aprayta, medi pertvarkymas vyksta i apaios vir, ir jie vadinami bottom-up 2-3-4mediais. Taiau 4-virnes galima skaidyti paiekos metu, kai tik jos aptinkamos einant medio akomis i viraus apai. Tada mediai vadinami top-down 2-3-4-mediais. Teiginys: Paiekos metu 2-3-4-medyje, turiniame N virni, visada aptinkama ne daugiau lgN+1 virni. terpimo metu tokiame medyje yra skaidoma ne daugiau kaip lgN+1 virn blogiausiu atveju, ir tiktina (t teigia statistiniai testai), kad skaidoma maiau negu 1 virn vidutinikai. Panaiai 2-3-4-mediuose galima apibrti ir imetimo operacij, tik vietoje virns skaidymo dvi, ia dvi virns i kuri viena turi tik vien sn, bus jungiamos vien. ios operacijos sudtingum vertins toks pat analogikas teiginys. Nors algoritmai 2-3-4-mediams yra pilnai apibrti ir teoriniai j vertinimai geresni negu dvejetaini medi, bet j programavimas yra sudtingas, o programos, realizuotos tiesiogiai perraant algoritmus, gali bti labai ltos, netgi ltesns negu dvejetainiams mediams. Todl taikomosiose programose tikr 2-3-4-medi pasitaiko ne taip danai. Vietoj j naudojami arba 2-3-mediai, arba raudoni-juodi mediai. 2-3-mediai turi tokias savybes: kiekviena vidin virn turi du arba tris snus; kiekviena aka nuo aknies iki lapo yra vienodo ilgio (arba gali skirtis tik vienu lygmeniu). raai 2-3-medyje, kaip ir 2-3-4-medyje, yra suriuoti ir talpinami lapuose. Lygiai taip, kaip ir anksiau, apibriamos 2-virns ir 3-virns, ir joms priskiriami raai. 2-3-medis, kurio akos k-1 k-1 yra ilgio k, turi ne maiau kaip 2 ir ne daugiau kaip 3 lap. Toks medis i N element turs ne maiau kaip 1+log3N lygi ir ne daugiau kaip 1+log2N lygi. 3.2.2. terpimo operacija 2-3-mediuose iame skyrelyje pateikiamos programos yra daugiau apraomojo pobdio, bet jos gerai iliustruoja manipuliavimo su medio virnmis operacijas. Algoritmas, terpiantis nauj sn vienai virnei, bt toks: procedure insert1 (node:^twothreenode);
52

Duomen struktros ir algoritmai

x:elementtype; { x is to be inserted into the subtree of node } var pnew:^twothreenode; { pointer to new node created to right of node } var low:real); { smallest element in the subtree pointed to by pnew } begin pnew:=nil; if node is a leaf then begin if x is not the element at node then begin create new node pointed to by pnew; put x at the new node; low:=x.key end end else begin { node is an interior node } let w be the child of node to whose subtree x belongs; insert1 (w,x,pback,lowback); if pback<>nil then begin insert pointer pback among the children of node just to the right of w; if node has four children then begin create new node pointed to by pnew; give the new node the third and the fourth children of node; adjust lowofsecond and lowofthird in node and the new node; set low to be the lowest key among the children of the new node end end end end; { insert1 } Ta pati programa, perrayta vietoje komentar terpiant Paskalio operatorius, atrodyt taip: procedure insert1 (node:^twothreenode); x: elementtype; var pnew:^twothreenode; var low:real); var pback:^twothreenode; lowback:real; child:1..3; { indicates which child of node is followed in recursive call } w:^twothreenode; { pointer to the child } begin pnew:=nil; if node^.kind=leaf then begin if node^.element.key<>x then begin new(pnew,leaf); pnew^.element:=x; low:=x.key end end else begin { node is an interior node } if x.key<node^.lowofsecond then begin child:=1; w:=node^.firstchild end else if (node^.thirdchild=nil) or (x.key<node^.lowofthird) then begin child:=2; w:=node^.secondchild end else begin { x is in third subtree } child:=3; w:=node^.thirdchild end;
53

Duomen struktros ir algoritmai

insert1 (w,x,pback,lowback); if pback <>nil then if node^.thirdchild=nil then begin if child=2 then begin node^.thirdchild:=pback; node^.lowofthird:=lowback end else begin { child=1 } node^.thirdchild:=node^.secondchild; node^.lowofthird:=node^.lowofsecond; node^.secondchild:=pback; node^.lowofsecond:=lowback end else begin { node already had three children } new (pnew,interior); if child=3 then begin pnew^.firstchild:=node^.thirdchild; pnew^.secondchild:=pback; pnew^.thirdchild::=nil; pnew^.lowofsecond:=lowback; low:=node^.lowofthird; node^.thirdchild:=nil end else begin { child=<2; move third child of node to pnew } pnew^.secondchild:=node^.thirdchild; pnew^.lowofsecond:=node^.lowofthird; pnew^.thirdchild:=nil; node^.thirdchild:=nil end if child=2 then begin pnew^.firstchild:=pback; low:=lowback end if child=1 then begin pnew^.firstchild:=node^.secondchild; low:=node^.lowofsecond; node^.secondchild:=pback; node^.lowofsecond:=lowback end end end end; { insert1 } Visa naujo elemento terpimo 2-3-med programa atrodyt taip: procedure insert (x:elementtype; var S: set); var pback:^twothreenode; { pointer to new node returned by insert1 } lowback:real; { low value in subtree of pback } saveS: set; { place to store a temporary copy of the pointer S } begin { checks for S being empty or a single node should occur here, and an appropriate insertion procedure should be included }
54

Duomen struktros ir algoritmai

insert1 (S,x,pback,lowback); if pback<> nil then begin { create new root; its children are now pointed to by S and pback } saveS:=S; new(S); S^.firstchild:=saveS; S^.secondchild:=pback; S^.lowofsecond:=lowback; S^.thirdchild:=nil; end end; { insert } 3.2.3. Imetimo operacija 2-3-mediuose Neformaliai urayta programa, realizuojanti elemento imetim i vienos 2-3-medio virns, bt tokia: function delete1 (node:^twothreenode; x:elementtype):boolean; var onlyone:boolean; { to hold the value returned by a call to delete1 } begin delete:=false; if the children of node are leaves then begin if x is among those leaves then begin remove x; shift children of node to the right of x one position left; if node now has one child then delete1:=true end end else begin { node is at level two or higher } determine which child of node could have x as a descendant; onlyone:=delete1 (w,x); { w stands for node^.firstchild, node^.secondchild, or node^.thirdchild, as appropriate } if onlyone then begin { fix children of node } if w is the first child of node then if y, the second child of node, has three children then make the first child of y be the second child of w else begin { y has two children } make the child of w be the first child of y; remove w from among the children of node; if node now has one child then delete1:=true end if w is the second child of node then if y is the first child of node, has three children then make the third child of y be the first child of w else { y has two children } if z, the third child of node, exists and has three children then make first of z be the second child of w else begin { no other child of node has three children } make the child of w be the third child of y; remove w from among the children of node;
55

Duomen struktros ir algoritmai

if node now has one child then delete1:=true end; if w is the third child of node then if y, the second child of node, has three children then make thr third child of y be the second child of w else begin { y has two children } make the child of w be the third child of y; remove w from among the children of node end { note node surely has two children left in this case } end end end; { delete1 } 3.2.4. Duomen struktros 2-3-mediams Realizuojant algoritmus su mediais, iskiriamos dviej tip medio virns - vidins ir iorins. is iskyrimas yra esminis, nes tokias virnes suvienodinus gaunami visikai kiti algoritmai. Jie bus nagrinjami vliau. Vidinms ir iorinms virnms realizuoti reikia naudoti skirtingas duomen struktras. Paskalio kalboje tai galima daryti naudojant case operatori. Virn galima apibrti taip: type elementtype = record key: real; {other fields as warranted} end; nodetypes = (leaf, interior); twothreenode = record case kind: nodetypes of leaf: (element: elementtype); interior: (firstchild, secondchild, thirdchild: ^twothreenode; lowofsecond, lowofthird: real) end; set = ^twothreenode; Lygiai tokius pat programavimo principus galime taikyti ir 2-3-4-mediams. Vidins virns gali turti nuorodas 2 ar 3 ar 4 snus. Iorins virns yra elementaraus tipo ir nuorod neturi. Aiku, programos, realizuojanios paiek 2-3-4-medyje, bus dar sudtingesns, bet manipuliavimo su j virnmis principai lieka tie patys. 3.2.5. Raudoni - juodi mediai Be 2-3-medi, yra ir kit bd palengvinti algoritm, besiremiani 2-3-4-mediais, realizavim. Vienas i j - naudoti raudonus -juodus medius. I esms tai tie patys aukiau aprayti dvejetainiai mediai, tik kiekvienai j virnei iskiriamas papildomas bitas nuorodos i virns jos snus spalvai, kuri gali bti raudona ar juoda, saugoti. Pagrindin mintis - vaizduoti 2-3-4-medio 3-virnes ir 4-virnes kaip maus dvejetainius medius, sujungtus raudonomis briaunomis, tuo tarpu paties 2-3-4-medio briaunos yra vaizduojamos juoda spalva. 4-virn atitiks trys dvejetains virns, sujungtos raudonomis jungtimis, o 3-virn atitiks dvi dvejetains virns, irgi sujungtos raudonai. J galima iraika parodyta 12 pav. Jame raudona
56

Duomen struktros ir algoritmai

spalva paymta storesne linija. Programuojant kiekvienai virnei iskiriamas papildomas bitas, rodantis jungties spalv.

arba

12 pav. 3-virns iraika raudonu-juodu mediu. 3-virn gali bti ireikta nevienareikmikai, vaizduojant raudon nuorod sn, nukreipt kairn ar deinn. Todl t pat 2-3-4-med galima ireikti skirtingais raudonais-juodais mediais. J ymjimo suvienodinimas priklauso nuo konkrei algoritmo slyg. Raudoniemsjuodiems mediams galima formuluoti tam tikras j struktrines savybes: raudonas-juodas medis neturi dviej greta esani vienoje akoje raudon jungi; visos akos turi vienod kiek juod jungi; skirting ak ilgiai (skaiiuojant ir raudonas jungtis) gali skirtis ne daugiau kaip dvigubai (bet vis j ilgis proporcingos logN). Aiku, kad raudon-juod medi programavimo sudtingumas yra toks pat kaip dvejetaini, ir daug lengvesnis negu 2-3-4-medi. Raudoni-juodi mediai turi ir kit ger savybi. Pavyzdiui., juose nesunku dstyti ir programuoti pasikartojani element reikmes. Aiku, kad bet kuris subalansuoto medio algoritmas turi leisti pasikartojanioms reikmms "kristi" abi puses nuo virns, kurios reikm irgi tokia pati. iuo atveju paiekos procedr reikia neymiai modifikuoti, pritaikant j apeiti vis nagrinjam pomed, kaip tai buvo padaryta anksiau procedroje treeprint. Kita gera i medi savyb yra ta, kad paiekos paprastame dvejetainiame medyje procedros gali bti diegtos, ir beveik be modifikacij. Jungi spalv galima realizuoti, vedant login kintamj, kuris bus "true", kai jungtis raudona, ir "false", kai jungtis juoda. Be to, paiekos metu jungties spalv galima nekreipti dmesio. Papildomos spalvos analizs reikia element terpimo ar imetimo metu. terpimo operacijos "papildomos pastangos" irgi yra nedidels. Jos reikia, kad vidiniame paiekos cikle reikia tikrinti, ar abi nuorodos snus yra raudonos (t.y. ar yra 4-virn), o tam programoje reikia siminti prosenelio (gg), senelio (g) ir tvo (p) nuorodas. terpimo procedros programa bt tokia: function rbtreeinsert(v: integer; x: link): link; var gg,g,p:link; begin p:=x; g:=x; repeat gg:=g; g:=p; p:=x; if v<x^.key then x:=x^.l else x:=x^.r; if x^.l^.red and x^.r^.red then x:=split(v,gg,g,p,x); until x=z; new(x); x^.key:=v; x^.l:=z; x^.r:=z; if v<p^.key then p^.l:=x else p^.r:=x; rbtreeinsert:=x; x:=split(v,gg,g,p,x);
57

Duomen struktros ir algoritmai

end; Nuoroda gg (senelio nuoroda) reikalinga split operacijoje, btent, kai 2-virns vienas i sn yra 4-virn, jos abi ir nauja virn turi bti transformuojamos 3-virn ir du jos snus - 2-virnes; kai 3-virns vienas i sn yra 4-virn, jos abi ir nauja virn transformuojamos 4-virn ir du jos snus - 2-virnes. Raudoniems-juodiems mediams taip ireikta skaidymo operacija reikia, kad reikia pakeisti nuorod spalv - dviej sn raudonas jungtis reikia padaryti juodomis, o j tvo jungt su seneliu padaryti raudona, kaip parodyta 13 pav.

13 pav. Spalv transformacija raudonuose-juoduose mediuose. 13 pav. matome, kad po virni skaidymo raudon-juod medi vienoje akoje gali susidaryti viena po kitos einanios dvi raudonos jungtys - struktriniu poiriu neleistina situacija. Tai reikia, kad reikia papildom veiksm su virnmis. Analiz rodo, kad taip gali atsitikti dl neteisingos sn orientacijos - 4-virn yra kairysis ar vidurinis (o ne deinysis, kaip pirmuose dviejuose pavyzdiuose) snus. Aiku, kad virnes reikia perorientuoti. Raudon-juod medi atveju itok perorientavim galima suformuluoti kaip gan paprastai ireikiam sukimo operacija (rotate). Btent turi bti keiiamos vietomis trys jungtys: tvo kairioji jungtis nukreipiama jo kairiojo snaus dein ank, kairiojo snaus jungtis pertvarko tv dein sn, o senelio deinioji jungtis nukreipiama kairj sn. Be to, dviej jungi spalvos sukeiiamos tarpusavyje. i paprasta sukimo operacija gali bti apibrta ne tik raudonam-juodam, bet ir bet kuriam dvejetainiam mediui. Savo ruotu ji buvo panaudota keliems subalansuot medi algoritmams. Operacija rotate isaugo paiekos medio esm ir lokaliai keiia tik tris virnes. Taiau svarbu paymti, kad i operacija neturi tendencijos gerinti medio balans, nes virns, kuri po sukimo tampa deiniuoju snumi, sns paemja vienu lygiu. Atliekant rotate operacij, modifikuojama medio struktra, todl tai reikia daryti atsargiai. Tinkamas pavyzdys yra pateikiama programa, kai virns v tvas yra virn y: function rotate(v: integer; y: link): link; var c,gc: link; begin if v<y^.key then c:=y^.l else c:=y^.r; if v<c^.key then begin gc:=c^.l; c^.l:=gc^.r; gc^.r:=c end else begin gc:=c^.r; c^.r:=gc^.l; gc^.l:=c end; if v<y^.key then y^.l:=gc else y^.r:=gc; rotate:=gc
58

Duomen struktros ir algoritmai

end; Atskirai verta pateikti procedros split program, kuri taip pat iliustruoja, kaip reikia siminti jungtis: function split(v: integer; gg,g,p,x: link): link; begin x^.red:=true; x^.l^.red:=false; x^.r^.red:=false; if p^.red then begin g^.red:=true; if (v<g^.key)<>(v<p^.key) then p:=rotate(v,g); x:=rotate(v,gg); x^.red:=false end; head^.r^.red:=false; split:=x end; Tai turi takos raudono-juodo medio inicializacijos procedrai: type link=^node; node=record key, info:integer; l,r:link; red: boolean end; var head,z:link; procedure rbtreeinitialize; begin new(z); z^.l:=z; z^.r:=z; z^.red:=false; new(head); head^.key:=0; head^.r:=z; end; Sujungus i program tekstus vientis, gaunamas efektyvus pakankamai paprastas algoritmas, terpiantis virn dvejetain med ir garantuojantis, kad paiekai ir terpimams bus naudojamas logaritminis lyginim kiekis: vienai paiekai raudoname-juodame medyje reikia apie lgN lyginim; vienam terpimui vidutinikai reikia maiau negu vieno sukimo. Raudoni-juodi mediai vertingi ir tuo, kad jie efektyviai dirba ir blogiausiu atveju. Paiekai raudoname-juodame medyje blogiausiu atveju reikia maiau negu 2lgN+2 lyginim, o terpimo operacijai - ketvirtadaliu maiau sukim negu lyginim. Vadinasi, turint apie pus milijono ra, 23-4-medio (arba raudono-juodo medio) auktis bus ne didesnis u 20 lygi.

3.3 Dstymo lentels


Dstymo lentels, dar kartais vadinamos idstymo funkcijomis (anglikai hashing) atstovauja visikai kitokiais principais pagrstiems paiekos algoritmams. Tai metodai, kurie rao raus tiesiogiai lenteles (masyvus), adresus raams skaiiuodami ra reikmi pagrindu (atlikdami su ra reikmmis aritmetines operacijas). Tarkime, jei inoma, kad rakto reikms yra skirtingos ir keiiasi nuo 1 iki N, tai ra, atitinkant rakto reikm i, reikia rayti matricos ar lentels i-j viet, tokiu bdu naudojant tiesioginio irinkimo metod. Idstymo lenteli algoritmai kuriami apibendrinant trivial metod.
59

Duomen struktros ir algoritmai

Paiekos operacijos idstymo lentelse atliekamos paprastai: elementui, kur norima rasti, pagal hash funkcija skaiiuojamas adresas lentelje ir lyginami tuo adresu esantys vienas ar keli elementai. terpimo operacija vykdoma irgi taip pat: elementui, kur reikia terpti, skaiiuojamas adresas ir tuo adresu elementas raomas lentel. Panai ir imetimo operacija. Idstymo lenteli algoritmai paprastai susideda i dviej dali. Pirmas ingsnis - tai adreso lentelje skaiiavimas (hash funkcijos reikms skaiiavimas). Jei tokia funkcija parinkta idealiai, tai kiekvienam raui skaiiuojamas vienintelis galimas adresas, tada kiekvienas raas turi vien ir tik vien viet lentelje, ir algoritm galima tobulinti nebent tik trumpinant funkcijos reikmi skaiiavimo laik. Taiau toki hash funkcij beveik neegzistuoja, todl paprastai reikalingas papildomas ingsnis: kolizij iskyrimas, t.y. kai keliems raams skaiiuojama ta pati vieta lentelje (tas pats adresas), reikia nusprsti, kaip iskirti raus. Tada yra galimos skirtingos kolizij iskyrimo strategijos, t.y. skirtingi algoritmai. Idstymo funkcij algoritmai priklauso informatikos klasikai. Toki funkcij ir algoritm yra pasilyta daug, ir jie detaliai itirti. Idstymo funkcijoms yra inoma daug rekomendacij, kurios galina efektyviai inaudoti norim ar turim laiko ir atminties santyk ir j balansuoti. 3.3.1. Idstymo funkcijos Dstymo lenteli algoritmams pirmiausia reikia funkcijos, kuri transformuot rakto reikmes (simboli sekas, ar skaiius, ar kitokius duomenis) lentels adresus. Galima tarti, kad tai yra skaiiai, isidst intervale [1 ... M]; ia M reikm parenkama praktiniais sumetimais (pvz., kiek turima atminties). Funkcija beveik visad yra aritmetin. Ideali hash funkcija yra tokia, kurios reikmes galima lengvai ir greitai skaiiuoti ir kuri visas galimas reikmes paskirsto tolygiai, t.y. bet kuri gaunama reikm vienodai tiktina. Toki funkcij parinkimo problemos labai panaios atsitiktini skaii generatori sudarym. Skaiiuojant toki funkcij reikmes, pirmiausia reikia ra ar rakt interpretuoti kaip skaii. Daniausiai tokiu atveju rakto dvejetain iraika (dvejetain eil, kai kiekvienas simbolis pakeiiamas atitinkaniu dvejetainiu kodu) yra skaitoma kaip dvejetainis sveikas skaiius be enklo. Po to skaii (jei jis neperdaug ilgas) veriant adresu, yra naudojama (daniausiai) mod funkcija. Adres skaiiuojanti idstymo funkcija uraoma taip: h(k) = k mod M. Norint patenkinti tolydumo reikalavim, M turi bti pirminis skaiius. Kai dvejetain eil ilga, j pateikti kompiuteriui kaip skaii - kintamojo reikm - yra sudtinga. Tokiu atveju naudojami kitokie metodai, pvz., ilga dvejetain seka interpretuojama kaip kokios nors pozicins skaiiavimo sistemos (32-ains) skaiius, o adreso reikmms skaiiuoti taikomas Hornerio metodas: h:=key[1]; for j:=2 to keysize do h:= (h * 32) + key[j]) mod M; Idstymo funkcijos detaliai apraytos D. Knuto [12] knygos 3-me tome. Sudtingesns funkcijos, domios ir matematikos, ne tik informatikos poiriu, apraytos [11] knygoje. 3.3.2. Atskirti sraai. Idstymo funkcijos t pat adres gali priskirti keliems raams. Todl btina isprsti tokio pobdio kolizijas. Atskirt sra algoritmas teigia, kad kiekvien ra, turini t pat adres, grup reikia formuoti kaip atskir tiesin sra. Vadinasi yra M sra, o hash funkcijos adresai yra ne kas kita, kaip nuorodos kakurio srao pradi. Kartais srao elementus naudinga laikyti
60

Duomen struktros ir algoritmai

suriuotus. Programuojant algoritm, reikia naudoti nuorod masyv. Programa iam metodui atrodyt taip: type link= ^node; node= record key.info: integer; next: link end; var heads: array[0..M] of link; t,z:link; procedure initialize; var i:integer; begin new(z); z^.next:=z; for i:=0 to M-1 do begin new(heads[1]); heads[i]^.next:=z end; end; Algoritmo savybs. Naudojam lyginim skaiius yra lygus nuoseklios paiekos lyginim skaiiui, padalytam i M. Kompiuteris naudoja papildom atmint M nuorodoms saugoti. Nuorod masyvo galima bt ivengti, jei funkcija nuorodas formuot tiesiogiai pirm reikiamo srao element. Taiau tai komplikuoja algoritmo programavim. 3.3.3. Atviro adresavimo dstymo metodai Dstymo metodus naudoja kompiliatoriai, ypa sudarydami simboli lenteles. iuo atveju atminties yra pakankamai, todl lenteli dydis didesnis u element kiek. Dstymo metodai tokiu atveju vadinami atviro adresavimo metodais. Taiau hash funkcij skaiiuojami adresai skirtingiems raams vis dlto gali sutapti, todl algoritmai turi nagrinti ir kolizij atvejus. ia bus idstyti du tokie algoritmai: tiesinio dstymo (linear probing) ir dvigubo dstymo (double hashing). Tiesinis dstymas. Tiesinio dstymo algoritmas, paskaiiavs elemento adres, tikrina, ar jau tokiu adresu nurodyta vieta yra uimta, ir jei taip - nuosekliai vien po kitos tikrina kitas pozicijas tol, kol suranda laisv viet. terpimo operacijos metu naujas elementas raomas i viet, o paiekos operacija ubaigiama. iame algoritme galimi keli skirtingi lyginimai: galima lyginti raktus arba hash funkcijos reikmes raktams (priklausomai nuo taikymo). Programa, realizuojanti algoritmo operacijas, bt tokia: procedure hashinitialize; var i:integer; begin for i:=0 to M do a[1].key:=maxint; end; function hashinsert(v: integer): integer; var x:integer; begin x:=h(v); while a[x].key<>maxint do x:=(x+1) mod M; a[x].key:=v; hashinsert:=x; end;

61

Duomen struktros ir algoritmai

Savyb. Remiantis statistiniais vertinimais, galima teigti, kad tiesinis dstymas naudoja vidutinikai maiau negu penkis nuoseklius perrinkimus, kai lentel upildyta daugiau negu dviem tredaliais. Dvigubas dstymas. Tiesinio dstymo algoritmas gali dirbti labai ltai, jei lentel bna beveik upildyta. Tada vietoje jo tikslinga naudoti kit algoritm. Vienas i toki yra dvigubo dstymo algoritmas. Jame siloma pakeisti viet lentelje perrinkimo strategij - vietoje tiesinio perrinkimo naudoti kintamo ingsnio perrinkim. Kitaip naudojama hash funkcija: po to, kai apskaiiuojamas rakto adresas ir, jei ta vieta uimta, reikia pereiti prie kito elemento, tikslinga naudoti kintam ingsn: x:= (x + u) mod M. Kad algoritmas skmingai veikt, ingsnis u ir skaiius M turi bti tarpusavyje pirminiai. Be to, u gali priklausyti nuo rakto x reikms. Todl daniausiai tokiu atveju apibriama nauja (antra) idstymo funkcija. Pavyzdiui, ji gali bti tokia: h2(k) = (M - 2 - k) mod (M-2). vairiose dvigubo dstymo algoritmo modifikacijose pasilyta ir daugiau toki funkcij [11]. Kaip ir anksiau, skaiiai M ir M-2 turi bti pirminiai. Empirin savyb. Dvigubas dstymas laisvos vietos paiekoje paprastai reikalauja maiau bandym negu tiesinis dstymas. Dstymo algoritm srityje yra atlikta daug tyrim ir pasilyta daug funkcij, kurios daniausiai testuotos ir vertintos empirikai. Matematin toki funkcij analiz ir vertinimai surinkti [13 knygoje, jie yra gan sudtingi.

3.4 Skaitmenin paieka


Paiekos ar koki nors kit operacij tikslams danai galima panaudoti rakt ar ra reikmi dvejetain (skaitmenin) iraik (o ne ra reikmes), kuri ie raai turi kompiuterio atmintyje. ra iraik bitai gali bti analizuojami ar lyginami tarpusavyje, i lyginim pagrindu daromos ivados, tokios pat kaip ir anksiau nagrintais paiekos algoritm atvejais. Tokie algoritmai vadinami skaitmenins paiekos (radix-searching) algoritmais. Juos patogu naudoti tada, kai su dvejetainmis ra iraikomis lengva manipuliuoti, ir kai jos vienokia ar kitokia prasme pakeiia ra reikmes. 3.4.1. Skaitmeniniai paiekos mediai Tai paprasiausias skaitmenins paiekos algoritmas, labai panaus dvejetains paiekos med. J skirtumas tas, kad pereinant i vienos virns kit yra lyginamos ne rakt (virni) reikms, bet i reikmi dvejetaini iraik bitai. Pereinant nuo medio aknies jos snus, lyginamas 1-as bitas, i i sn j snus - 2-as bitas ir t.t., iki tol, kol nebus pasiektas lapas (akos pabaiga). Jei bito reikm lygi nuliui, pereinama kairj sn, jei vienetui - dein sn. Raant io algoritmo program, tikslinga apibrti funkcij, kuri i tam tikr rakt reikmi iskirt reikalingus bitus: bits(x, k, j) - i reikms x ikiria j bit, pradedant nuo k-ojo bito. Algoritmo programos tekstas tada bt toks: function digitalsearch (v: integer; x: link): link; var b:integer; begin z^.key:=v; b:=maxb; repeat if bits(v,b,1)=0 then x:=x^.l else x:=x^.r; b:=b-1; until v=x^.key;
62

Duomen struktros ir algoritmai

digitalsearch:=x end; Duomen struktros, naudojamos iame algoritme, yra tokios pat kaip ir dvejetaini medi. Sutampanios rakt reikms skaitmeninje paiekoje (kaip ir skaitmeniniame riavime) sudaro esmin kliuvin. Todl iame skyriuje bus nagrinjami tik tie atvejai, kai vis rakt reikms yra skirtingos. Skaitmenins paiekos terpimo procedra irgi yra tik lengva dvejetainio paiekos medio modifikacija: function digitalinsert (v: integer; x: link): link; var p: link; b: integer; begin b:=maxb; repeat p:=x; if bits(v,b,1)=0 then x:=x^.l else x:=x^.r; b:=b-1; until x=z; new(x); x^.key:=v; x^.l:=z; x^.r:=z; if bits(v,b+1,1)=0 then p^.l:=x else p^.r:=x; digitalinsert:=x end; Algoritmo sudtingumas: Paiekai ar terpimui skaitmeniniame paiekos medyje, kur sudaro b bit ilgio N virni, reikia vidutinikai apie lgN lyginim (ir b lyginim blogiausiu atveju). 3.4.2. Skaitmeniniai paiekos indeksai Skaitmeniniuose paiekos mediuose element reikms, nors ir dvejetains, yra saugomos (ir lyginamos, ar apdorojamos, t.y. i j iskiriami bitai ar j grups) virnse. Jei ios reikms yra ilgos, jos gali labai sumainti algoritmo efektyvum. iame skyrelyje bus aptariami algoritmai, kurie inaudoja skaitmenini paiekos medi privalumus, bet galina elemento reikm paiekos operacijoje lyginti tik vien kart. Idja paimta i gyvenimo: telefon knygoje puslapi viruje raomos pirmos pavardi raids, bet ne pilnos pavards. Todl paieka joje atliekama iekant pirmos reikalingo odio raids, o tik po to viso odio. Pltojant i idj, 1960-ais metais E. Fredkin pasil tokios paiekos duomen struktr ir algoritm [12]. i struktra inoma "trie" vardu (nuo odi tree ir retrieval). Jos esm yra tokia: M-ariniame medyje skiriamos vidins ir iorins virns, prie kiekvienos vidins virns raomas (M-1)-matis vektorius (skaitmeninis ar simbolinis), kurio reikms indeksuoja jungtis ir nurodo, kuria i j reikia eiti toliau. Element reikms raomos iorinse virnse (kurios yra medio lapai). Dvejetainje trie struktroje vidinse medio virnse yra raomi nuliai ar vienetai (bitai), o virni numeriai atitinka bito pozicij rao dvejetainje iraikoje. Pavyzdiui, norint rasti elementus, kurie treio bito pozicijoje turi reikm, lygi vienetui, reikia i treios virns pereiti dein sn ir taip tsti toliau. i struktra lietuvikai bus vadinama skaitmeniniais paiekos indeksais (iki iol lietuvi kalboje nusistovjusio termino nra). Trie struktros vairios realizacijos, modifikacijos ir analiz pateikta [12] knygoje.
63

Duomen struktros ir algoritmai

Skaitmeniniai paiekos indeksai nepriklauso nuo element terpimo tvarkos - tiems patiems duomenims gaunamas tas pats medis nepriklausomai nuo to, kokia tvarka elementai buvo traukti. terpimo operacijos metu reikia atlikti neskming paiek ir prie vidins virns prijungti iorin, kartu pakeiiant j atitinkant indeks. Trie struktros pavyzdys pateiktas 14 pav.

X A C E G H J M N P R S

14 pav. Trie struktra raidi penki bit kodams. Programuoti trie struktr nra paprasta, nes ji reikalauja speciali operacij su bit ar panai simboli indeksais. Knygose [1, 12] aptarta daug programavimo ir program optimizavimo metod. i struktra yra geras algoritmo, kur verta programuoti emo lygio programavimo kalba, pavyzdys. Algoritm sudtingumas. Skaitmenins paiekos indeks struktra turi vidutinikai apie N/lgN (t.y. apie 1,44N) vidini virni. Viena i trie struktros problem - galimi skirtingi paiekos medio ak ilgiai. Ji gali bti sprendiama arba dvejetain med pertvarkant M-arin, arba trumpinant akas, kuriose yra daug ilg vienod indeks. 3.4.3. Daugybiniai skaitmeniniai paiekos indeksai Struktros, kurios vadinamos daugybiniais skaitmeniniais paiekos indeksais, silo pereinant nuo vienos virns prie kitos naudoti keli bit sekas (pvz., b ilgio) ir sudaryti M-arinius medius (M=2b). is metodas tinkamas tuo atveju, kai yra daug element, kuri dvejetainje iraikoje tam tikros bit sekos kartojasi. M-arinis medis bus iuo atveju labiau subalansuotas ir jo akos trumpesns (ak ilgis bus logMN). Vadinasi ir paieka bus vykdoma greiiau. Tokio daugybinio medio pavyzdys pateiktas 15 pav. X A C E G N P H I L M R S

15 pav. Keturi lygi trie struktra raidi kodams. is metodas labai efektyvus, kai turima daug rakt ir j reikmi - matuojam tkstaniais. Kita vertus, ioje struktroje yra paslpta galimyb uterti atmint, nes gali bti daug neinaudot jungi. 3.4.4. Patricia algoritmas Skaitmenins paiekos mediai turi dvi savybes, kurios potencialiai trukdo efektyviam algoritmo veikimui ir jo realizacijai:
64

Duomen struktros ir algoritmai

potenciali ir danai pasitaikanti galimyb turti daug neinaudot jungi; paiekos medio virns turi bti dviej skirting tip. ios neigiamos savybs yra eliminuotos D. R. Morrison'o pasilytame Patricia algoritme. Jame sudaromas medis i N virni (kiekvienam elementui po virn), o kiekvienai virnei priskiriama informacij leidia naudoti tik vien piln element lyginim per vien paiekos operacij. Neinaudotos jungtys eliminuojamos paprastai - kiekvienai virnei priskiriamas papildomas indeksas - bito numeris, kur reikia lyginti norint nusprsti, kuria aka toliau eiti. Element reikms saugomos virnse, todl inyksta skirtumas tarp vidini ir iorini virni. Kiekviena virn turi dvi jungtis, i kuri kiekviena gali bti nukreipta ne tik snus, bet ir pai virn ar kuri nors auktesnio lygio virn. Kad bt vaizdiau, verta inagrinti pavyzd. Tarkime, turime tokias raides ir j dvejetainius kodus: A E C I G M L 00001 00101 00011 01001 00111 01101 01100 S R H N X P 10011 10010 01000 01110 11000 10000

Nuosekliai, tokia tvarka, kaip idstyti elementai lentelje, terpiant virnes Patricia med gaunama 16 pav. pavaizduota struktra.
4

S
3 3

H
2 2 1

X N P
1 0

E
1 1

C
0

I
0

M L

16 pav. Patricia medis raidi penki bit kodams.

Patricia medyje paieka vykdoma taip: jei reikia rasti, tarkime, element X, yra skaitoma jo dvejetainio kodo pozicija, kuri paymta ties aknine virne, ir tokiu bdu nusprendiama, ar eiti kairj ar deinj sn. i operacija kartojama tol, kol prieinama nuoroda, nukreipta arba t pai virn, arba aukiau esani virn. Tada yra lyginamos iekomo elemento X ir nurodytos virns reikms ir paieka ubaigiama. Jei reikms sutapo, paieka skminga, jei ne neskminga. Reikia pastebti, kad btent Patricia medio konstrukcija atspindi specifinius skirtumus tarp element. Pavyzdiui., elemento S kodas yra toks, kad dvejetainis posekis 10*11
65

Duomen struktros ir algoritmai

tarp kit element nra sutinkamas. is skirtumas ir yra prieastis, kodl i apaios vir nuoroda (i artimiausio elementui S elemento R) buvo nukreipta element S. terpimo operacija yra sudtingesn, jos realizacijoje reikia skirti du atvejus, kai virn terpiama medio akoje (vidin virn) ir kai lape (iorin virn). Tokios paiekos ir terpimo operacij programos galt bti tokios: type link=^node; node = record key. info, b: integer; l,r: link end; var head,z: link; function patriciasearch(v:integer; x:link):link; var p:link; begin repeat p:=x; if bits(v,x^.b,1)=0 then x:=x^.l else x:=x^.r; until p^.b=<x^.b; patriciasearch:=x end; function patriciainsert(v:integer; x: link): link; label 0; var t,p:link; i:integer; begin t:=patriciasearch(v,x); if v=t^.key then goto 0; i:=maxb; while bits(v,i,1)=bits(t^.key,i,1) do i:=i-1; repeat p:=x; if bits(v,x^.b,1)=0 then x:=x^.l else x:=x^.r; until (x^.b=<i) or (p^.b=<x^.b); new(t); t^.key:=v; t^.b:=i; if bits(v,t^.b,1)=0 then begin t^.l:=t; t^.r:=x end else begin t^.r:=t; t^.l:=x end; if bits(v,p^.b,1)=0 then p^.l:=t else p^.r:=t; 0:patriciainsert:=t end; Algoritmo sudtingumas. Patricia medis, sudarytas i atsitiktini b bit ilgio N element, turi N virni ir paiekos operacijai vidutinikai naudoja lgN lyginim.

3.5 Iorin paieka


Praktikai danai reikia iekoti duomen dideliuose failuose, kurie laikomi iorinje atmintyje. Kaip ir iorinio riavimo atveju, tokia paieka vadinama iorine. Nagrinjami algoritmai bus pritaikyti darbui antrinje, t.y. diskinje atmintyje. i atmint galima iek tiek formalizuoti, skirtingai negu tretin atmint, kurioje gausu labai vairi ir skirting technini sprendim, darani tak algoritm darbui.
66

Duomen struktros ir algoritmai

Paieka yra viena i labai dan ir fundamentali operacij su diskiniais renginiais. Nors diskini rengini konstrukcijos skiriasi, visoms joms galima naudoti tam tikr model. T daryti veria ir manipuliacij su duomenimis pobdis - operacij metu reikia pakeisti, terpti, imesti ar rasti kelis bitus ar baitus labai dideliuose failuose. Failai paprastai yra raomi taip, kad inaudot visas technines diskini rengini charakteristikas ir irinkt duomenis kuo greiiau. Todl labai sudtinga rasti objektyvius kriterijus, kurie pagelbt vertinant paiekos metod efektyvum vairiuose taikymuose, nes labai daug kas priklauso nuo technins ir programins rangos. Formalus diskini rengini modelis padeda vaizdiai ir matematikai grietai pateikti iorins paiekos algoritmus. ie, skirtingai nuo iorinio riavimo, nelabai skiriasi nuo vidins paiekos algoritm, tik yra labiau pritaikyti dinaminei duomen dstymo situacijai. Nagrinjami iorins paiekos metodai yra naudojami ir naudingi ne tik failams ar j sistemoms, bet ir duomen bazms. Taiau duomen bazs turi labai didel inercij, t.y. kai koks nors algoritmas jose yra diegtas, vis manipuliavimo su duomenimis struktr labai sunku pakeisti. Paprastai diegti algoritmai gyvuoja tol, kol gyvuoja duomen bazi taikymas. Nauji, dinamiki paiekos metodai diegiami tik kartu su naujomis duomen bazmis. Diskins atminties modelyje atmintis skirstoma atskiras sekcijas, vadinamuosius puslapius. Kiekvienas diskas turi po fiksuot kiek puslapi (nagrinjamuose algoritmuose - po tris). puslap galima rayti fiksuot kiek ra (nagrinjamuose algoritmuose - po keturis), kurie puslapio viduje irenkami nuosekliai. Skaitymo-raymo (input/output - I/O) operacijos reikalauja daug daugiau laiko negu visos kitos kompiuterio operacijos. Skaitymo-raymo operacijos metu visas puslapis perkeliamas vidin atmint (arba atvirkiai). 3.5.1. Indeksin-nuosekli paieka Paprasiausias nuoseklios paiekos algoritmas gali bti pritaikytas ir paiekai diskinje atmintyje. Tokiu atveju raus reikia dstyti nuosekliai didjimo tvarka disko puslapiuose. Tada paieka atliekama kreipiantis kiekvien puslap ir nuskaitant jo turin atmint. Algoritmas dirbs tol, kol bus sutiktas raas, didesnis u iekom, ir jo veikimo laikas bus tiesiogiai proporcingas nuskaityt puslapi skaiiui. Nuoseklios paiekos algoritm galima akivaizdiai patobulinti. Diske esantiems puslapiams galima sukurti rodykl (anglikai index), kurioje nurodoma, kokia rao reikme prasideda ar baigiasi kiekvienas puslapis. Rodyklei skiriamas atskiras puslapis. Paieka ioje struktroje yra daug greitesn: norint rasti reikiam ra, yra nuskaitomas rodykls puslapis ir po to - tas puslapis, kuriame gali bti iekomasis raas. itai paiekai paprastai reikia dviej I/O operacij. Jei yra keli diskai, galima dar kurti rodykli rodykl (master index), kurioje raomi ra reikmi, esani kiekviename diske diapazonai. Paprastai tokia rodykl yra maa ir paiekos metu j galima laikyti vidinje atmintyje. itokia duomen struktra vadinama indeksiniu-nuosekliu failu ar paieka, jos pavyzdys pateiktas 17 pav. Ji labai tinka greitai duomen paiekai, bet jos ra terpimo ar imetimo operacij vykdo labai ilgai, nes gali tokiu atveju prireikti pakeisti vis disko ar disk puslapi turin. 1-as diskas: C E 1 2 AAAC EEEE

2-as diskas: E I N 1 2

EGHI

LLMN

17 pav. Indeksin-nuosekli struktra diskuose.


67

Duomen struktros ir algoritmai

Algoritmo sudtingumas: Paiekos operacija indeksiniame-nuosekliame faile vyksta pastoviu laiku, taiau terpimo ar imetimo operacijos gali pareikalauti pertvarkyti vis fail (t.y. eksponentiniu laiku). 3.5.2. B-mediai Kai duomenys kokioje nors aibje keiiasi dinamikai, t.y. kai paiekos, terpimo ar imetimo operacijos yra vienodai tiktinos, geriausia naudoti vienodo (ir maiausio galimo) sudtingumo struktras. Viena i toki tinkam struktr - subalansuoti mediai. Iorins paiekos atveju mediai paprastai susieja disko ar disk puslapius ir todl I/O operacij atvilgiu turi bti optimizuoti, t.y. jie turi bti gan akoti. Algoritmai, kurie ia naudojami, gali apibendrinti (ar pritaikyti) 2-3-4-medius. Medi virns gali turti priskirtas i tam tikro intervalo (nuo 1 iki M-1) reikmes, t.y. gali turti nuo 2 iki M nuorod. Nuorodos gali bti nukreiptos puslapius, kuriuose rayti tame intervale esantys raai (teisingiau puslap, kuriame prasideda raai). itokia struktra yra vadinama B-mediais, j 1972-ais metais pasil autoriai R. Bayer ir McCreight [2]. Jos pavyzdys pateiktas 18 pav. 1-as diskas: 2 D 2 M 2 0 1 2 A A A B S S S S 3 T 3 0 1 D E I L T U U M N O

2-as diskas: 3-as diskas:

18 pav. Sakinio SUBALANSUOTAS MEDIS (r. 11 pav.) B-medis diske. Paiekos, terpimo ar imetimo operacijos ioje struktroje atliekamos kaip ir 2-3-4mediuose. Formaliai B-mediuose yra dviej tip virns: vidins ir iorins. Taiau j realizacija panaikina skirtum. Jei medis yra maas, jo visos vidins virns gali tilpti vidinje atmintyje ir joms galima taikyti vien i anksiau nagrint struktr. io atveju nuorodos iorines virnes bus disk ir j puslapi adresai. Jei medis didelis ir vidinje atmintyje netelpa, kiekvienai vidinei virnei (iskyrus medio akn) galima priskirti atskir puslap, turint sav struktr (18 pav.). ra adresavimas bus kompleksinis: disko numeris ir puslapio numeris. Saugant diske virnes, joms skirtuose puslapiuose yra saugomi ir visi jungtims reikalingi adresai, taiau puslapiuose, sauganiuose raus, jungi saugoti nereikia. Medio akn verta laikyti vidinje atmintyje, nes pradedant paiek visad reikia formuoti reikalingus adresus. Aiku, B-medio atminties kiekis priklauso nuo puslapi, ra dydio ir nuorod kiekio. B-medi terpimo ir imetimo operacijos, kai vien virn reikia skaidyti dvi ar dvi virnes sujungti vien, formaliai yra tokios pat, kaip ir 2-3-4-mediuose. Taiau skiriasi j realizacija. Pagrindin dmes reikia sutelkti ne struktros element keitim, o tai, kad reikia minimizuoti operacij su puslapiais skaii. Algoritmo sudtingumas. Paiekos, terpimo ar imetimo operacijoms B-medyje, turiniame N element ir M jungi, reikia logM/2N disko I/O operacij. Praktikai, kai skaiius M yra pakankamai didelis, tam reikia pastovaus laiko. Virni skaiius, reikalingas tokiam mediui, gali bti vertintas apytikriai 1,44N/M. B-medis isiskiria dar keliomis savybmis, kurias galima inaudoti algoritmo darbui pagerinti. Viena i j - virnse galima naudoti kintam jungi (ir interval) skaii. Virutiniuose lygiuose galima naudoti daugiau jungi, apatiniuose - maiau, taip galima sutaupyti reikaling mediui saugoti puslapi skaii, kartu I/O operacij skaii. Kita savyb - virni rauose galima saugoti
68

Duomen struktros ir algoritmai

ne ra reikmes, o j kodus ar reikmi prefiksus. Tokia procedra gali sutaupyti laiko ir vietos. Literatroje pasilyta daug toki galim modifikacij (ir daug i j yra realizuota). Apie tai liudija ir aib pavadinim: prefix-B-mediai, B+-mediai, prefix-B+-mediai, K-D-B-mediai ir pan. 3.5.3. Iplstinis dstymas Iplstinis dstymas (extendable hashing) yra tam tikra alternatyva B-mediams. is metodas pritaiko skaitmeninius paiekos metodus iorinei atminiai, pirm kart buvo pasilytas 1978 metais [1], vliau buvo paskelbta daug modifikacij ir taikym. Jo pagrindinis privalumas yra tai, kad tipinse ir labai danai pasitaikaniose duomen dstymo situacijose paiekai reikia tik dviej I/O operacij ir panaiai tiek pat naujeims elementams terpti ar imesti. Iplstinio dstymo atveju, kaip ir B-mediuose, raai ir j indeksai saugomi disko puslapiuose. Indeksai sudaromi naudojant dvejetainius ra kodus. Duomen saugojimo ioje struktroje schema parodyta 19pav.

00001 A 00101 E 00101 E 1-as diskas: 2 2 2 2 0 2 1 1

00 01 10 11

01100 L 01110 N

2-as diskas: 10010 R 10100 T 11000 X

A E E

R T X

L N

19 pav. Iplstinio dstymo struktra diske. Operacijos su indeksais iplstinio dstymo algoritmuose yra dvilyps: indekso struktra disko puslapyje yra vienaip modifikuojama, kai keiiasi analizuojam bit skaiius terpiant ar imetant elementus, ir kitap modifikuojama, kai reikia vieno puslapio turin skaidyti du puslapius arba du puslapius sujungti vien. Duomen struktra, gauta 19 pav. struktr terpus papildomus elementus, pavaizduota 20 pav. 00001 A 00001 A

000 001 010 011 100

00101 E 00101 E 00101 E

1-as diskas: 2 3 2 2 2 2 2 2 0 0 2 2 1 1 1 1

2-as diskas:

A A

R S T X
69

L N

Duomen struktros ir algoritmai

101 110 111

01100 L 01110 N

3-as diskas: 10010 10011 10100 11000 R S T X

E E E

20 pav. Element terpimas iplstinio dstymo struktroje. Puslapio viduje raai saugomi suriuoti. Tai nra esmin algoritmo darbo savyb, nes daugiausia laiko sunaudoja I/O operacijos. Puslapi modifikacija atliekama vadovaujantis tokiais principais: kai puslap reikia skaidyti dvi dalis, ir dal ra perkelti kit puslap, jie turi bti raomi taip, kad viename puslapyje likt raai, prasidedantys 0, o kit patekt prasidedantys 1. it princip reikia taikyti ir toliau, sekoms 00, 01, 10, 11, ir t.t. Kai reikia pereiti prie ilgesni skaitmenini sek, tenka padvigubinti rodykl (indeks). Rodykl naudoja tik puslapi nuorodas todl jai reikia maai vietos. Aiku, kad rodykls skaidymas ir yra ta operacija, kuri gali labai pabloginti algoritmo darb, nes gali tekti skaidyti ar sujungti daug puslapi. Taiau tokia situacija bna ne taip jau danai. Todl algoritmas daniausiai dirba labai efektyviai. Jei rodykl uima daugiau nei vien puslap, vidinje atmintyje galima suformuoti rodykls puslapi nuorodas ir su j pagalba kreiptis tik t puslap, kuriame yra reikiamas rodykls fragmentas. Taiau yra ir neigiam iplstinio dstymo algoritmo savybi. Algoritmas yra jautrus dvejetaini reikmi pasiskirstymui. Jei daugumos ra reikms prasideda tuo paiu dvejetainiu fragmentu, rodykls tris gali nepagrstai isipsti, nes prie dvejetainio fragmento pridedant vien bit, rodykls tris padvigubja. Esant mintam netolygumui, patartina vietoje dvejetainio fragmento naudoti vienoki ar kitoki idstymo funkcij. Kita algoritmo ypatyb - jo priklausomumas nuo puslapio dydio. Teisingiau, io algoritmo darbui yra svarbus ra, puslapi ir idstymo funkcijos reikmi dydi santykis. Tai daro tak ir rodykls dydiui, ir nuorod skaiiui, ir uimamos atminties dydiui. Aiku, toks faktorius yra svarbus, kai duomen pakankamai daug, pvz., konstruojant labai dideles duomen bazi sistemas. Dar viena algoritmo elgsenos ypatyb, kuri reikia kreipti dmes - nuorod perteklius esant dideliam lygi ra kiekiui, t.y. kai vienas raas kartojasi daug kart. ie raai dirbtinai ipuia rodykl, nes atsiranda daug nuorod t pai reikm. i problema panai dvejetaini fragment pasiskirstymo netolydumus ir gali bti sprendiama panaiai. Taiau jei kartojasi tik vienas arba tik keli raai, galima naudoti fiktyvias reikmes, identifikuojanias pasikartojani ra tinkamus poaibius. Algoritmo sudtingumas. Jei diskins atminties puslap telpa M ra, atminties tris, reikalingas saugoti N ra, bus apytikriai lygus 1,44N/M puslapi. Iplstinio dstymo algoritmo rodykl turs apie N1+1/M/M nuorod. Reikia pastebti, kad iplstinis dstymas yra labai panaus virtualios atminties formavimo metodus. Virtuali atmintis, kuri yra ne kas kita, kaip bendros paskirties iorins paiekos metodas, formuoja tiesioginius adresus iorins atminties puslapius ir remiasi prielaida, kad raai, esantys kompiuterio vidinje atmintyje, ir raai, esantys diske, fizikai yra netoli vienas nuo kito ir, be to, susij. Nuorod formavimo principai abiems algoritmams yra tokie patys. Taiau virtualios atminties formavimo metodo, skirtingai negu iplstinio dstymo algoritmo, negalima tiesiogiai pritaikyti duomen bazi valdymo sistemoms. Duomen bazi ar fail sistemoms reikia, kad be
70

Duomen struktros ir algoritmai

joki iankstini susiejim bt galima efetyviai kreiptis i bet kurios duomen vietos bet kuri kit.

71

Duomen struktros ir algoritmai

4. Sek apdorojimas ir kompresija


4.1 Sek paieka
iame skyriuje svoka "seka" bus interpretuojama kaip duomen aib, kuri negali bti iskaidyta logikai nepriklausomus raus taip, kad kiekvienas j turt nesudtingai identifikuojam dal. Sekos - tai dviej skirting kompiuteri program sistem eim pagrindinis objektas: tekst apdorojimo sistem, vadinamj dokument procesori (simboli sekos), ir kompiuterins grafikos sistem (dvejetains sekos). itie du atvejai turi daug skirtum ir panaum. Panaus udavinio formulavimas ir sek apdorojimo procedros. bet skirtingi alfabetai, simboli kiekis, ir t.t. ie faktoriai danai slygoja skirtingus algoritmus. Pagrindins operacijos, atliekamos su sekomis - tai poseki paieka ir sek fragment identifikavimas. Poseki paiekos operacijos labai skiriasi nuo nagrint paiekos algoritm, todl ia bus nagrinjamos atskirai. Sek fragment identifikavimo (pattern matching) udavinys gali bti formuluojamas taip: yra N simboli ilgio seka (N yra didelis), ir M simboli ilgio fragmentas (pattern), reikia rasti visus fragmento pasikartojimus tekste. Pavyzdiui, rasti visas vietas, kur ioje knygoje sutinkamas fragmentas duomen struktra. Toks formulavimas nra paprasta simbolio paieka, ir todl algoritmai gali labai skirtis. Kaip visuomet, svarbi algoritm sudtingumo problema. 1970-ais metais buvo paskelbtas teiginys, kad egzistuoja poseki paiekos algoritmas, ku.rio sudtingumas netgi blogiausiu atveju yra M+N. Vliau per kelerius metus buvo sugalvoti ir diegti konkrets algoritmai, kurie atitiko teorinius rezultatus. ie algoritmai nagrinjami iame skyriuje. Daugelis poseki paiekos algoritm turi domi ir retai pasitaikani savyb - j teoretikai vertinamas sudtingumas paprastai yra blogesnis u praktin. Pavyzdiui, brutalios jgos algoritmo teorinis sudtingumas yra lygus MN, o jo kruoptus realizavimas leidia simainti jo sudtingum iki M+N. domu pastebti, kad keli plaiai naudojami fundamentals ir efektyvs poseki paiekos algoritmai yra labai paprastai formuluojami (ir ia savo savybe vos ne genials), bet buvo pasilyti tik prie kelis metus. Natralu pagalvoti, kodl ie algoritmai nebuvo atrasti anksiau?

4.2. Tiesmukikas (brutalios jgos) algoritmas


Vienas i poseki paiekos metod yra akivaizdus - reikia nuosekliai vien po kito tikrinti kiekvien sekos simbol tol, kol jis sutampa su pirmuoju fragmento simboliu, ir jei taip - lyginti fragmento ir sekos antruosius simbolius, po to treiuosius, ir t.t. Jei bent vienoje vietoje simboliai nesutampa, reikia pereiti prie sekanio sekos simbolio ir tikrinim pradti i naujo. Jei seka ir fragmentas idstyti masyvuose, programa realizuojanti algoritm, bt tokia: function brutesearch: integer; var i, j: integer; begin i:= 1; j:= 1; repeat if a[i] = p[j] then begin i:= i+1; j:= j+1 end else begin i:= i - j +2; j:= 1 end; until ( j > M ) or ( i > N ); if j > M then brutesearch:= i - M else brutesearch:= i end;

72

Duomen struktros ir algoritmai

ia i ir j yra atitinkamai sekos ir fragmento nagrinjam simboli rodykls. Algoritmo efektyvumas labai priklauso nuo konkrei sek ir fragment savybi. Pavyzdiui, tekst apdorojimo metu labai retai pasitaiko, kad vidinis ciklas kartotsi tiek kart, kiek numatyta, daniausiai jis net neinicijuojamas. Be vidinio ciklo algoritmo sudtingumas bt M+N. Kaip jau buvo minta anksiau, algoritmo teorinis sudtingumas reikalauja MN lyginim paiekos metu.

4.3. Knuth-Morris-Pratto algoritmas


Pagrindinis principas, kuriant algoritm, buvo toks: fragmentas yra inomas i anksto ir i informacija turi bti panaudota. Pavyzdiui, jei fragmento pirmasis simbolis toliau nesikartoja, o fragmento ir sekos lyginimo metu sutapo (j-1) simboli, ir j-asis nesutapo, tai faktikai yra inoma daug daugiau - sekoje nuo tos vietos, kur buvo pradta tikrinti, galima praleisti (j-1) simbol ir pereiti prie j-ojo lyginimo, nes n vienas i i praleist simboli tikrai nesutaps su pirmuoju fragmento simboliu. Todl brutalios jgos algoritme rodykls i reikm galima keisti (i+1), o ne (ij+2), kaip anksiau. ios idjos gyvendinimas ir sudaro nagrinjamo algoritmo turin. Be to, remiantis vairiais papildomais pastebjimais galima pasiekti, kad rodykls i reikm niekad nemat. Programuojant algoritm, yra apibriamas naujas masyvas next[1 .. M], kurio element reikms skaiiuojamos taip: next[1]:=0; jei j > 1, tai next[j] reikm yra lygi maksimaliam k < j, kai pirmieji (k-1) fragmento simboli sutampa su paskutiniais (k-1) simboli fragmento sekos, susidedanioje i j-1 element. Funkcija, apskaiiuojanti grimo indeks, bt tokia: function kmpsearch: integer; var i, j: integer; begin i:= 1; j:= 1; initnext; repeat if (j = 0) or (a[i] = p[j]) then begin i:= i+1; j:= j+1 end else begin j:= next[j] end; until (j > M) or (i > N); if j > M then kmpsearch:= i - M else kmpsearch:= i; end; Algoritm realizuojanti rpograma gali bti parayta taip, kad masyvo next[1 .. M] reikmi skaiiavimas bt realizuotas paioje programoje kartu naudojant papildomus programavimo triukus: procedure initnext; var i,j: integer; begin i:= 1; j:= 0; next[1]:= 0; repeat if (j = 0) or (p[i] = p[j]) then begin i:= i+1; j:= j+1; next[i]:= j; end else begin j:= next[j] end; until i > M; end;

73

Duomen struktros ir algoritmai

Jei fragmentas keiiasi retai ir fiksuotas per vis programos vykdymo laik, galima tok masyv sudaryti i anksto ir terpti program. Pateikiamas tokio algoritmo realizavimo pavyzdys (fragmentui 10100111): i:=0; 0: i:= i+1; 1: if a[i] <> '1' then goto 0; i:+ i+1; 2: if a[i] <> '0' then goto 1; i:+ i+1; 3: if a[i] <> '1' then goto 1; i:+ i+1; 4: if a[i] <> '0' then goto 2; i:+ i+1; 5: if a[i] <> '0' then goto 3; i:+ i+1; 6: if a[i] <> '1' then goto 1; i:+ i+1; 7: if a[i] <> '1' then goto 2; i:+ i+1; 8: if a[i] <> '1' then goto 2; i:+ i+1; search:= i - 8; i programa - tai sekos paiekos kompiliatoriaus pavyzdys. Naudojant papildomus pastebjimus, kuriuos galima realizuoti iame algoritme, galima pasiekti tok jo sudtingum: Knuth-Morris-Pratto algoritmas naudoja ne daugiau kaip (M+N) simboli lyginim. Nors lyginim skaiiumi is algoritmas daug efektyvesnis u brutalios jgos algoritm, taiau jo reikm i tikrj ne tokia jau didel. Taikymuose ne taip jau danai pasitaiko pasikartojanio teksto pasikartojani fragment paieka. is metodas turi kit privalum - sekoje simboliai peririmi nuosekliai ir niekada negrtama atgal. Todl tok algoritm yra patogu realizuoti situacijose, kai simboliai vedami vienas po kito, i i simboli yra irenkami reikalingi fragmentai, taiau nereikia naudoti papildomos atminties anksiau buvusiems sekos simboliams siminti.

4.4. Boyer-Mooreo algoritmas


Jeigu sekos analizs metu galima laisvai pereiti nuo vienos pozicijos prie kitos ir grti bet kuri pozicij atgal, taikomas greitesnis posekio paiekos metodas, pat fragment analizuojant i deins kair. i idja gali bti pagrsta tokiu pavyzdiu: jei fragmento 10100111 8-a, 7-a ir 6-a pozicijos sutampa su sekos simboliais, bet 5-a pozicija nesutampa, i karto fragmento analiz perkeliama per 7 pozicijas ir tikrinama nuo 15-os pozicijos. itok sprendim galima pagrsti tuo, kad fragmento 6, 7, 8 pozicijos (t.y. fragmento dalis 111) niekur daugiau fragmente nesikartoja, todl paties fragmento pirmose septyniose sekos pozicijose negali bti. Aiku, nesikartojanios fragmento dalys masyve next turi bti identifikuotos i anksto. is masyvas turi bti modifikuotas skaiiuoti pozicijoms i deins kair. Verta pastebti, kad turbt pagrindinis skiriamasis io algoritmo bruoas yra tai, kad jo veiksmams valdyti yra naudojamas simboli nesutapimo poymis, ne taip kaip anksiau - simboli sutapimo poymis. Programa, realizuojanti algoritm, bt tokia: function mischarsearch: integer; var i, j: integer; begin i:= M; j:= M; initskiip; repeat if a[i] = p[j] then begin i:= i-1; j: j-1 end else begin if M-j+1 > skip[index(a[i])] then i:= i + M - j + 1 else i:= i + skip[index(a[i])]; j:= Mp end;
74

Duomen struktros ir algoritmai

until (j < 1) or (i > N); mischarsearch:= i+1; end; Algoritmo sudtingumas. Boyer-Moore poseki paiekos algoritmas visada naudoja ne daugiau kaip (M+N) simboli lyginim. Jam reikia apie N/M lyginim, jei alfabetas nra labai maas, o fragmentas nra labai ilgas. Pastaroji savyb, aiku, yra euristin. Ji pagrsta pastebjimu, kad jei simboli alfabete yra daug, o fragmentas ne toks jau ilgas, daugelio simboli arba nebus fragmente i viso, arba jie pasikartos ne daugiau kaip vien kart.

4.5. Rabin-Karp'o algoritmas


Poseki paiekos procedroms galima pritaikyti ir idstymo funkcij metodus. Tokiu atveju fragment reikt interpretuoti kaip galim idstymo funkcijos reikm. Jei fragmentas yra trumpas, dstymo algoritmus galima taikyti tiesiogiai, t.y. fragment interpretuoti kaip hashing adres visiems galimiems sekos M ilgio posekiams. Jei fragmentas nra trumpas ir M ilgio poseki analiz atmintyje komplikuota, reikia ir fragmentams, ir posekiams taikyti tinkam idstymo funkcij. Teigiama ios paiekos ypatyb yra ta, kad nereikia atmintyje saugoti paios idstymo lentels, nes domina tik fragmento ir posekio vienkartinis sutapimas. Algoritmas, naudojantis hash funkcij, formuluojamas paprastai: apibriama kokia nors paprastai ir greitai apskaiiuojama hash funkcija, pvz., h(k)=k mod q, ia q yra pirminis skaiius; apskaiiuojama ir saugoma ios funkcijos reikm fragmentui; perrenkant visus galimus sekos M ilgio posekius, pradedant nuo 1-os pozicijos, jiems skaiiuojama hash funkcijos reikm ir lyginama su fragmento reikme; jei abi reikms sutapo, tiesiogiai lyginami fragmentas ir posekis, jei ne - analizuojamas kitas posekis. Algoritmo sudtingumas. Rabin-Karp'o algoritmas, vykusiai parinkus hash funkcij, naudoja apytikriai M+N lyginimo operacij, nors jo teorinis sudtingumas blogiausiu atveju yra O(MN).

4.6. Dviej sek bendras ilgiausias posekis


Problema, nagrinjama iame skyrelyje ir danai pasitaikanti praktikoje, gali bti formuluojama taip: reikia iskirti bendr ilgiausi dviej sek posek (t.y. sek, gaut imetus tam tikr kiek, galbt nulin, element i sekos). is udavinys taip danai ikyla taikomosiose programose, kad, pavyzdiui, UNIX operacinje sistemoje yra net speciali fail lyginimo komanda diff, surandanti didiausi posek, kuris yra bendras dviems failams, jei jie yra nelygs. ioje programoje raai yra interpretuojami kaip sekos elementai. Algoritmas yra formuluojamas aibi duomen struktros terminais, o pagrindins naudojamos operacijos su aibmis yra ios: FIND(r) - suranda aib, kurioje yra elementas r; SPLIT(S, T, U, r) - aib S suskaido dvi aibes T ir U taip, kad aibje T atsiduria elementai, maesni u r, o aibje U - didesni u r ar lygs jam; MERGE(S, T, U) - aibes S ir T sujungia vien ir rao aib U.
75

Duomen struktros ir algoritmai

Udavinio tikslas yra surasti ilgiausi bendr dviej simboli sek A ir B posek. Algoritmo darbas pradedamas nuo to, kad sekai A sudaromas aibi rinkinys: PLACES(a) = {i - numeris| kad simbolis a yra i-oje pozicijoje}. it aibi rinkin galima efektyviai realizuoti, sudarant pozicij sraus kaip tam tikr pozicij nuorod rinkin. Jei simboliai, sudarantys sekas A ir B, yra pakankamai sudtingi, pvz. failo raai (tekstinio failo eiluts), galima iam tikslui naudoti koki nors tinkam idstymo (hash) funkcij. Aibs PLACES sudarymo sudtingumas bt O(n). Sudarius PLACES, toliau jau tiesiogiai galima rasti ilgiausi bendrj posek. ia pateikiamas algoritmas sugebs nustatyti maksimal bendrojo posekio ilg. Lengva algoritmo modifikacija, reikalinga surasti paiam posekiui, paliekama skaitytojui. Algoritmas darb pradeda, nuosekliai analizuodamas vien po kito sekos B elementus. Kiekvienam aibs B elementui bj, 0 < j < m, reikia iskirti ilgiausi bendrj posek, kur turi sekos {a1,...ai} ir {b1,...bj}. Tam tikslui simboli pozicij indeksai i jungiami aibes Sk, kurias sudaro tokios pozicij i reikms, kad aibi {a1,...ai}ir {b1,... bj} ilgiausio bendrojo posekio ilgis yra lygus k (k kinta nuo 0 iki n). Reikia pastebti, kad aib Sk visada susideda i didjimo tvarka isidsiusi skaii, ir skaiiai, esantys aibje Sk+1, yra didesni u skaiius, esanius aibje Sk. Algoritmas dirba iteratyviai. Tariant, kad visos aibs Sk, esant sekos B pozicijai j-1, jau sudarytos, yra nagrinjama pozicija j ir jai sudaromos naujos aibs Sk. Tam tikslui reikia tik modifikuoti jau turimas aibes Sk. Iskiriama aib PLACES(bj). Kiekvienam elementui r i ios aibs reikia nusprsti, ar jis gals pailginti ilgiausi bendrj posek. Jeigu taip, ir, be to, jei abu elementai (r-1) ir r bus vienoje aibje Sk, tada visi elementai s >= r turi priklausyti aibei Sk+1. Toks tikrinimas atliekamas modifikuojant aibes taip: FIND(r) - norint surasti reikaling aib Sk; Jei FIND(r-1) nra lygi aibei Sk, tai naujas elementas bj negali pailginti bendrojo posekio, todl nieko modifikuoti nereikia ir algoritmas etap turi ubaigti; Jei FIND(r-1) = Sk, yra vykdoma operacija SPLIT (Sk, Sk, Sk', r), siekiant i aibs Sk iskirti elementus, didesnius u r; MERGE(Sk', Sk+1, Sk+1) - iskirti elementai turi bti perkelti aib Sk+1. Kai visi aibs B elementai yra perrinkti, ilgiausio bendrojo posekio ilgis yra saugomas aibje Sk, ia k - gautas maksimalus skaiius. Nesunku pastebti, kad algoritmo darb galima padaryti efektyvesn, aibse PLACES(bj) imant analizuojamus skaiius majimo tvarka. Tai gali sumainti operacij skaii. Algoritmo sudtingumas. Operacij skaiius gali bti vertintas asimptotika O(p log n): ia n yra sek ilgi maksimumas, o p - skaiius por pozicij, kur sutampa sek simboliai. Blogiausiu 2 atveju skaiius p yra lygus n .

4.7. Sek ir fail kompresijos metodai


Iki iol nagrintuose algoritmuose daugiausia dmesio buvo sliriama procedr vykdymo greiiui, ir ne visada kreipiamas dmesys papildomos atminties reikalingum ar panaudojim. Duomen kompresija skirta btent taupyti kompiuterio atmint - vidin ar iorin. Daugelis kompiuterini fail yra perteklingi, todl kompresijos metodai galina juos suspausti. iuos
76

Duomen struktros ir algoritmai

metodus tikslingiausia taikyti tekstiniams failams, rastriniams (kompiuterins grafikos) failams, taip pat garso kodavimo failams, kuriuose rayti dani pasikartojimai. Fail kompresijai bdingos tokios charakteristikos: tekstiniai failai sumaja vidutinikai nuo 20 iki 50%, dvejetainiai failai - nuo 50 iki 90%. Taiau kai kuri tip failams kompresija gali nepadti, j tris kartais gali net padidti. Fail ar duomen kompresija yra prietaringas reikinys. Kompiuterin atmintis pastoviai pinga, atsiranda vis naujos technologijos, kai diskin atmintis padidja deimtimis ir imtais kart, danai paprasau saugoti ar naudoti failus nesuspaustus. Kita vertus, kaip tik dl atminties technologijos pasikeitim, irinkimo greiio antrinje ar tretinje atmintyje padidjimo suspaustos informacijos saugojimas tampa vis labiau patogesnis ir efektyvesnis ir plaiau naudotinas. 4.7.1. Vienod simboli sek kodavimas Pertekling simboli sekos, turinios paprasiausi galim struktr ir gan danai pasitaikanios - tai ilgos paeiliui einani vienod simboli sekos. Jas galima keisti skaii ir simboli kombinacijas: pvz., vietoj AAAAAAA galima rayti 7A - seka akivaizdiai sutrumpja. itoks metodas be dideli pakeitim gerai tinka situacijai, kai tekste yra vien tik raids ir jame nra tokio fragmento 7A ar panaaus. Jei tekste yra ir raidi, ir skaii, metod galima ir reikia modifikuoti. metod paprasta ir lengva taikyti dvejetainiams failams - skaiiai 0 ir 1 yra alternuojantys, todl vienod simboli sekas galima tiesiog urayti skaiiais: 0000000111111000111111111 galima keisti skaii seka 7639 itoks kompresijos metodas patogus vadinamiesiems bitmap tipo failams (rastriniams pieiniams, pieiamiems riftams, ir pan.), failo suspaudimo santykis gali bti labai didelis. Neigiama jo ypatyb - metodas tinka tik tam tikriems specializuotiems failams. Kitas elementarus bdas - vadinamj escape (ieities) sek naudojimas. Koduojamos sekos pradioje raomas specialus simbolis, o po jo dvi ar kelios raids, ireikianios sekos turin. Pavyzdiui, simboli sek AAA reikia koduoti seka QCA, kuri turi bti suprantama taip: raid Q yra specialus escape simbolis, raid C atitinka skaii 3, nes tai treia raid alfabete (3 yra koduojamo simbolio pasikartojim skaiius), o raid A - koduojam simbol. Kadangi escape seka visada uima ne maiau kaip 3 pozicijas, verta pradti koduoti sekas, ne trumpesnes kaip 4 simboli. Jei pats escape simbolis yra tekste, jam galima naudoti koduojani kombinacij Q[tarpas], t.y. nulinio ilgio sek. Labai ilgoms vienod simboli sekoms galima naudoti pasikartojanias escape sekas. Reikia pastebti, kad taikymuose escape sekos yra naudojamos ne tik sek ar fail kompresijai realizuoti, bet ir vykdomoms simboli sekoms (t.y. komandoms) nuo informacini simboli atskirti, pvz., failuose, kurie spausdintuv atmint rao riftus ar pan. 4.7.2. Kintamo ilgio kodavimas Sek kompresijai yra taikoma ir daug kitoki metod. Viena i labiausiai paplitusi idj, kurios realizavimas sugeba sutrumpinti sekos ilg ir kurios pagrindu sukurta daug fail kompresijos program, yra tokia: kuo daniau simbolis ar simboliai kartojasi sekoje, tuo trumpesnis turi bti jam(-iems) konstruojamas kodas. Tada galima tiktis, kad ir simboli sekos ilgis bus trumpesnis. vairioms galimybms ir apribojimams apvelgti, verta pateikti detal ir paprast pavyzd. Turint tekstinius failus, simboli alfabetas susideda i 26 lotynik raidi, todl kiekvienam simboliui galima priskirti penki bit ilgio kod. Ukoduotos sekos AAAAABBBCCD ilgis tokiu atveju bus 55 bitai. Jei raidms bt priskirti kodai pagal j danumus: A-0, B-1, C-00, D-01, seka transformuotsi dvejetain sek 00000111000001, kurios ilgis bus tik 14 bit. Nors sek ilgiai
77

Duomen struktros ir algoritmai

labai sutrumpja, taiau iuo atveju ikyla kita - vienareikmio dekodavimo problema. J galima sprsti keliais bdais, i kuri vienas - vedant tarp kod specialius skyriklius. Tarkime, jei skyriklis uims vien bit (paprastai jis yra daug ilgesnis), ukoduota seka pailgs 10 bit, t.y. bus lygi 24 bitams, ir ji vistiek bus trumpesn u pradin sek. Atrodyt, itoks kodavimas yra efektyvus. Taiau analizuojant situacij i esms, ikyla daug problem. itoks kodavimo bdas yra nestabilus, t.y. itaip ukoduotoje sekoje pametus nors vien bit (taip danai atsitinka telekomunikacij kanaluose), bus dekoduotas visikai kitas tekstas. metod sunku realizuoti (ikyla daug technini detali) kompiuteri programose. Silant ieit i tokios situacijos ir vertinant vienareikmio kodavimo svarb, daugelyje algoritm buvo skmingai panaudota vadinamoji prefikso taisykl: koduojama turi bti taip, kad vienas kodas negalt bti kito kodo pradia. Esant tokiam kodavimui, nereiks joki skyrikli, visi koduojanio alfabeto simboliai bus lygiaveriai, o tai ymiai palengvins algoritmo realizavim. Toks principas ir kodavimo bdas buvo pasilyti Huffmano (tariama Hafmen) 1952-ais metais ir yra inomas jo vardu. is algoritmas yra realizuotas labai daugelyje kompiuterini program, program sistem, techninje rangoje (danai tokiose telekomunikacijos prietaisuose, kaip faksas, modemas ar pan.). Toliau bus nagrinjami io algoritmo principai ir jo realizavimo detals. Tarkime, kad simboli sekos susideda i lotynik raidi, kurias reikia perkoduoti dvejetaini simboli sekas. Pirmas algoritmo ingsnis - paskaiiuoti ieities teksto simboli danumus. Programa, realizuojanti i procedr, atrodyt taip: for i:= 0 to 26 do count[i]:= 0; for i:= 1 to M do count [index (a [i] ) ]:= count [index (a [i] ) ] + 1; ioje programoje raidi kodai naudojami kaip masyvo indeksai. inant teksto raidi danumus, galima konstruoti paius dvejetainius kodus. Konceptualiai, taiau nekonstruktyviai tai galima aprayti taip: visas raides reikia suskirstyti dvi grupes taip, kad vienos grups raidi danum suma bt lygi (arba apytikriai lygi) kitos grups raidi danum sumai. Vis vienos grups raidi kodo pradios simbolis turi bti nulis, o kitos grups raidi - vienetas. Po to kiekvien i i grupi reikia vl perskirti dvi grupes ir taikyti t pai procedr kiekvienai i j. proces reikia tsti tol, kol grupje bus bent dvi raids. Programuojant kodavimo proces, reikia turti algoritm, galinant efektyviai skirstyti raides grupes. Pasirodo, kad tai galima pasiekti naudojant skaitmeninje paiekoje idstytos trie struktros principus, kuriais remiantis gaunamas efektyvus tiesinio sudtingumo algoritmas. Raides (kuri yra N) reikia koduoti konstruojant dvejetain med i apaios vir pagal j danumus. Tam tikslui visos raids yra idstomos apaioje, bsimo medio lapuose. Kiekvienai raidei priskiriama virn, alia kurios raomas danumas. Po to irenkamos dvi virns su maiausiais danumais ir joms priskiriama nauja virn, jos paios tampa ios virns kairiuoju ir deiniuoju snumis, o naujai virnei yra priskiriamas suminis jos sn danumas. Toliau turint sek virni i (N-1)-os virns vl atrenkamos dvi virns su maiausiais danumais ir jos padaromos snumis naujos virns, kartu jai priraant jos sn danum sum. Taip turi bti tsiama tol, kol bus gauta tik viena virn. Tokio skaidymo metu kodai kiekvienai i raidi priskiriami automatikai, kai dvi virns tampa naujos virns snumis, tada viena i briaun (kairioji) gauna kod 0, o kita briauna (deinioji) - 1. Raids kodas bus lygus bit sekai, kuri gaunama einant vienintele aka i medio aknies raids lap. Kodo savybs: ukoduoto praneimo ilgis bus lygus vidutiniam pasvertam ak ilgi vidurkiui Huffmano danum medyje;
78

Duomen struktros ir algoritmai

bet kuris kitas danum medis duos kodo ilg didesn, negu kad Huffmano medis.

79

Duomen struktros ir algoritmai

5. Daugiamai duomen struktros ir algoritmai


iame skyriuje pateikiamos duomen struktros ir algoritmai, bdingi geografinms informacinms sistemoms (GIS), kompiuterins grafikos ir kompiuterinio konstravimo sistem (CAD) vaizd analizei, daugiaterpms duomen bazms (multimedia DB) ir labai didelms duomen bazms (VLDB). Jie papildo ir apibendrina ankstesniuose skyriuose nagrintus algoritmus tekstiniams duomenims apdoroti. Daugiamaiai duomenys skirtinguose taikymuose yra skirtingai suvokiami. Sudtingos integroschem kompiuterinio konstravimo sistemos (VLSI CAD) remiasi daugiausia dvimaiais arba isluoksniuotais dvimaiais duomenimis, kuri bazinius elementus sudaro staiakampiai, daugiakampiai, orientuoti pagal koordinai ais. Tipins toki duomen operacijos yra sankirta, sjunga, trasavimas. Kartografins sistemos irgi naudoja dvimaius duomenis, kuri baziniai elementai yra takai, tiess, udaros sritys ploktumoje. Bazines operacijas sudaro erdvin paieka, srii sankirta, atstum skaiiavimas. Mechaninse CAD sistemose duomenys yra trimaiai, jose operuojama su kietais knais erdvje, o duomen dstymo formatai gali bti labai vairs. Danas terminas yra ir vaizd duomen bazs. Jose paprastai laikomi neanalizuoti vaizdiniai duomenys, pvz., rentgeno nuotraukos, palydovins nuotraukos, ir pan., kuri pagrindu vliau bna apskaiiuojamos tam tikros charakteristikos. Kompiuterio atmintyje tokie vaizdiniai yra laikomi rastriniuose failuose. Metodai, analizuojantys vaizdinius duomenis, skmingai taikomi ir kitose srityse, pvz., infraraudoniems sensoriniams signalams arba garsams. Tuo tarpu daugiamai duomen bazs kaupia ir apdoroja detali informacij apie objektus, j savybes, viet erdvje ir pan., o duomenys jose yra laikomi vadinamaisiais vektoriniais formatais. Detaliau apibriant daugiamaius duomenis, galima iskirti tokias j savybes: daugiamaiai duomenys yra sudtingos struktros - j objektai kartais susideda i daugelio tkstani tak, vairiai pasiskirsiusi erdvje, j negalima atvaizduoti vienoje fiksuotos struktros reliacinje lentelje; daugiamaiai duomenys yra dinaminiai - terpimas ar imetimas kaitaliojasi su papildymo operacijomis, ir duomen struktros turi bti pritaikytos tokiems procesams; daugiamai duomen bazs yra didels - paprastai yra operuojama gigabaitiniais atminties triais; daugiamaiai duomenys neturi nusistovjusios standartini algebrini operacij ar specifikacij aibs - manipuliacijos su duomenimis labai priklauso nuo dalykins srities; daug daugiamai duomen operacij nra udaros - j vykdymo metu galima gauti figras, visikai kitokias negu pradins (dviej daugiakampi sankirtoje galima gauti paskirus takus, kelis daugiakampius, kitokias figras); daugiamai duomen bazs yra ltesns negu prastos (j operatoriai paprastai reikalauja daugiau kompiuterio operacij negu reliaciniai ar kitokie operatoriai). Ivardytos vairialyps ir sudtingos duomen savybs neleidia pateikti vieningos toki bazi teorijos. Viena i svarbi grupi, iskiriani manipuliacijas su daugiamaiais duomenimis, yra vadinamieji geometriniai operatoriai. Pagrindiniai i j yra erdviniai paiekos operatoriai, kuri efektyvi realizacija reikalauja speciali fizinio lygio algoritm ir struktr. ie operatoriai paiekai naudoja ne tik skaitinius ar simbolinius, bet ir kitokius atributus, pvz., elemento viet erdviniame objekte. Anksiau nagrint paiekos metod negalima tiesmukikai panaudoti erdvinei paiekai, nebent tik iimtiniais atvejais. Viena i pagrindini klii - erdviniams duomenims nra toki viening tvarkini, kurie isaugot nuotolius tarp objekt. O visi anksiau nagrinti metodai remiasi
80

Duomen struktros ir algoritmai

tokiais tvarkiniais. Todl norint panaudoti tokius metodus erdviniams duomenims, reikt daugiamaius objektus bijektyviai atvaizduoti vienmaius taip, kad atstumai tarp objekt prie atvaizdavim ir po jo likt nepakit. Konkreioje situacijoje rasti tok atvaizdavim ne visada pavyksta. Manipuliuojant su erdviniais duomenimis, kreipties metodai, atitinkantys naudojamas struktras ir algoritmus, turi tenkinti reikalavimus, kylanius i erdvini duomen savybi: 1. Dinamikumas. terpiant ar imetant elementus, kreipties metodai turi padaryti visus su tuo susijusius pakeitimus. 2. Antrins ir tretins atminties valdymas. Erdvini duomen triai tokie dideli, kad j nemanoma laikyti vidinje atmintyje. Kreipties metodai turi laisvai valdyti antrin ir tretin atmint. 3. Plataus operacij spektro palaikymas. Kreipties metodai turi vienodai efektyviai vykdyti visas operacijas (vykdymo sudtingumas visoms operacijoms turi bti tas pats). 4. Nepriklausomyb nuo duomen vedimo. Kreipties metodai turi bti efektyvs ir laukiamu, ir blogiausiu atvejais. 5. Paprastumas. Pains kreipties metodai, turintys daug iskirtini atvej, danai nra pakankamai patikimi, nes j realizacijoje tiktinos klaidos. 6. Invariantikumas. Kreipties metodai turi gerai adaptuotis prie auganio duomen kiekio. 7. Efektyvumas. Kadangi erdvins paiekos operacijos naudoja daug procesoriaus laiko ir daug I/O operacij, kreipties metodai turi minimizuoti ir kreipini antrin atmint skaii, ir procesoriaus naudojimo laik. Daugiamai duomen kreipties metodai, realizuojantys paieka, sudaro didel operacij klas. Verta iskirti takinius (point access methods) ir erdvinius kreipties metodus (spatial access methods). Takiniai metodai skirti erdvinei paiekai takinse duomen bazse, kuriose takai gali bti dviej ar daugiau matavim, bet be erdvini charakteristik. Erdviniai kreipties metodai, be kit, valdo tokius objektus, kaip tiess, daugiakampiai, daugiamaiai briaunainiai ir pan. Papildomai dar galima iskirti nedidel klas metod, kurie pritaikyti erdviniams duomenims, bet nevaldo iorins atminties (vadinamieji vidins atminties metodai). Taiau ie kreipties metodai yra tik vienas ingsnis erdvins paiekos procese. Takini ir erdvini kreipties metod santyk tarp j iliustruoja 21 pav.
Uklausa erdvinis indeksas tak paiekos rezultatai objekt geometrijos krovis tiksli erdvin paieka klaidingi rezultatai kiti rezultatai

paiekos rezultatai

21 pav. Daugiamai duomen paieka

5.1. Vidins atminties struktros


81

Duomen struktros ir algoritmai

Tolesniam ir pilnesniam temos nagrinjimui tikslinga susikurti modelin udavin. Tarkime, kad staiakampje geometrinje srityje turime penkis daugiakampius ri ir penkis takus pi. Daugiakampiams gali atstovauti j centroidai ci (arba minimals gaubiantys staiakampiai) (22 pav.).

c1

c2

p1

p2 c3 c4

p3

p4 p5

c5

22 pav. Modelinis pavyzdys. 5.1.1. K-D-mediai Viena i labai paplitusi erdvins paiekos struktr yra vadinamieji k-d-mediai. Tai dvejetains paiekos mediai, fiksuojantys rekursyv geometrins erdvs skaidym (d-1) matmen hiperploktumomis. ios ploktumos yra lygiagreios su koordinai ploktumomis, o j orientacija kiekvienu skaidymo atveju yra keiiama viena i d galim krypi (nustatyta seka). Kiekviena ploktuma turi turti bent vien duomen tak, kuris ir naudojamas ploktumai medyje ymti. Be to, kiekvienai vidinei tokiu bdu gaunamo medio virnei priskiriama diskriminanto funkcijos reikm, kuri naudojama paiekos metu. Paiekos ir terpimo tokioje struktroje operacijos atliekamos tiesiogiai, be komplikuot alternatyv. Taiau imetimo operacija gali bti sudtingesn, nes kartais reikia partvarkyti vis pomed, prasidedant imetamoje virnje. Dvejetainis medis, atitinkantis pavaizduot 22 pav. geometrij, parodytas 23 pav. Kadangi medio virns turi atitikti takus, ploktumas identifikuoja daugiakampi centroidai ir takai. Pirmoji kertanti ploktuma eina vertikaliai per centroid c4, kuris saugomas medio aknyje. Kitos dvi ploktumos yra horizontalios ir eina per takus p2 ir c2, kurie yra aknies sns. Savo ruotu i sn sns bus gaunami skaidant staiakamp vertikaliomis ploktumomis, ir t.t.

c1 p2

c2

p1 p2 c3 p3 p4 p5

c4 c2 c1 c5 p3 p1

c3 c4 c5 p4 p5
82

Duomen struktros ir algoritmai

23 pav. Modelinio udavinio k-d-medis. Aiku, kad k-d-mediai yra paprasta ir efektyvi erdvins paiekos struktra, galinanti greitai rasti ar apibrti takus ir kitas geometrines figras erdvje. Taiau jos blogybs yra tai, kad medio forma labai priklauso nuo tak terpimo tvarkos ir duomen takai imtomi po vis med. Buvo pasilytos kelios io medio modifikacijos, ivengianios i blog algoritmui atvej. Viena i j - adaptyvs k-d-mediai. Jose skaidanias ploktumas siloma parinkti taip, kad abiejose pusse bt apytikriai po vienod kiek element, kartu atsisakant taisykls, kad ploktumos turi turti duomen takus. Tokiame medyje duomenys yra talpinami medio lapuose. Vidins virns ymimos skaidanios ploktumos dimensija ir koordinatmis, o skaidymas vyksta tol, kol kiekviename poerdvyje lieka tik po vien tak. Taiau adaptyvus medis nra visikai dinamin struktra. J sunku laikyti subalansuot, kai elementai danai terpiami ir imetami. Geriausia, kai duomen papildymai inomi i anksto arba yra reti. Kitas k-d-medi patobulintas variantas - bin-mediai. i struktra silo rekursyviai skaidyti erdv d-maius lygius briaunainius tol, kol kiekviename i j liks po vien element. Jos privalumas tas, kad visada tiksliai inomas skaidani ploktum isidstymas ir galima su jomis manipuliuoti, pvz., optimizuoti j parinkim priklausomai nuo duomen. Taiau norint med ilaikyti adaptyviai prisitaikant prie duomen reikia daug daugiau pastang. 5.1.2. BSP-mediai Tai, kad geometrin erdv skaidanios hiperploktumos yra lygiagreios su koordinatinmis, apriboja struktros efektyvum. Todl buvo pasilytas nemaas kiekis metod, leidiani skaidyti erdv bet kuriomis kryptimis. Galbt inomiausias i toki metod - BSP-mediai (binary space partitioning). Kaip ir k-d-mediai, BSP-mediai yra dvejetainiai, atitinkantys rekursyv erdvs skaidym poerdvius (d-1)-matmis ploktumomis. Kiekvienas poerdvis yra skaidomas individualiai, nepriklausomai nuo kit poerdvi ir nuo to, kaip jis buvo gautas. Skaidani ploktum parinkimas priklauso tik nuo tak, esani poerdvyje, isidstymo. Poerdviai skaidomi tol, kol juose esani tak skaiius virija tam tikr slenkst. BSP-mediuose kiekvien skaidani ploktum atitinka vidin virn, o poerdvius - lapai. Lapai saugo nuorodas tuos takus, kurie yra poerdvyje. Paiekos medyje metu tako koordinats terpiamos akn ir nustatoma, kurioje hiperploktumos pusje yra takas, po to pereinama atitinkam sn, ir operacija kartojama. Kai tokiu bdu pasiekiamas lapas, iekomasis takas yra lyginamas su kiekvienu taku lapui atitinkamame puslapyje. Tokiu bdu surandama (arba nesurandama), ar takas yra geometrinje erdvje. BSP-mediai lengvai adaptuojasi prie tak pasiskirstymo duomen bazje pobdio. Juos lengva pritaikyti ir ranginei paiekai. Taiau BSP-mediai turi ir neigiam savybi. Paprastai ie mediai yra nebalansuoti, jie kartais turi labai gilius vienakius pomedius, kurie pablogina algoritm efektyvum. Be to, BSP-mediams saugoti reikia daugiau atminties, palyginus su k-dmediais. 5.1.3. Ketvirtainiai mediai Ketvirtainiai mediai (anglikai quadtrees), nors ir artimi k-d-mediams, nra dvejetainiai. Jei jie konstruojami d-matei erdvei, kiekviena virn turi 2d sn. J pavadinimas kils i dvimats ploktumos, ir iuo atveju kiekviena vidin virn turi po keturis snus. Nors ketvirtainiai mediai turi daug variant, pagrindin idja taikoma visiems i j: d-mat geometrin erdv yra
83

Duomen struktros ir algoritmai

skaidoma (d-1)-matmis lygiagreiomis su koordinatinmis ploktumomis 2d poerdvi; paiam skaidiniui priskiriama medio virn, o kiekvienam poerdviui - po sn; visiems iems poerdviams nustatytas tvarkinys (kokia tvarka juos galima perrinkti), nurodantis ir virns sn numeracij. Ketvirtainis medis, atitinkantis modelin udavin, parodytas 24 pav. Jis yra dar vadinamas takiniu ketvirtainiu mediu (nes erdvs skaidymo virns parenkamos duomen bazs takuose). c4
c1 c2 p1

c1 p2 p1 p3

c2 p4 c3

c5

p5

p2 c3 c4

p3

p4 p5

c5

24 pav.Modelinio udavinio takinis ketvirtainis medis. Kitas paplits ketvirtaini medi variantas yra vadinamieji sektoriniai ketvirtainiai mediai (region quadtree). J virns nepriklauso nuo duomen bazs tak, o kiekviena j atitinka reguliar erdvs skaidym sektorius, sutvarkytus pagal kok nors tvarkin. Duomenys yra saugomi lapuose. Modelin udavin atitinkantis sektorinis ketvirtainis medis parodytas 25 pav.

c1

c2

p1

c5 c1 p2 c2 p1 p3 c3 p4 p5

p2 c3 c4

p3

p4 p5

c5

25 pav. Modelinio udavinio sektorinis ketvirtainis medis. Paiekos poiriu ketvirtainiai mediai yra nesubalansuoti ir todl kartais gali bti neefektyvs. Taiau jie labai danai pasitaiko, kai i rastrinio vaizdo (pieinio) yra gaunama vektorin struktra (pvz., geografinse informacinse sistemose).

5.2. Antrins atminties struktros


84

Duomen struktros ir algoritmai

Daugiamats duomen struktros, nagrintos ankstesniame skyrelyje, nepritaikytos duomenims, esantiems iorinje kompiuterio atmintyje, valdyti. Tuo tarpu praktikai duomen negalima rayti vien tik vidinje atmintyje. Jei ias struktras tiesmukikai taikytume ir iorinei atminiai, algoritmai bt labai neefektyvs. Duomen struktras, arba kreipties metodus, valdanius daugiamaius duomenis, galima skirstyti takinius ir sektorinius (arba srities). Duomen bazi takai (arba pakankamai maos sritys) yra skirstomi vadinamuosius buketus, kurie parenkami taip, kad kiekvien i j galima rayti atskir diskins atminties puslap. Be to, i buket atributai turi bti pritaikyti prie kompiuterio operacins sistemos ypatum. Vizualiai buketai gali bti vaizduojami tam tikromis, danai paprastomis, geometrinmis figromis, pvz., staiakampiais. 5.2.1. Daugiamaiai iplstinio dstymo metodai Nors dviej ar daugiau matavim duomenys paprastai neturi kokio nors tvarkinio, isauganio atstumus tarp j, taiau literatroje yra daug bandym vesti tok sutvarkym, bent jau i dalies. Tikimasi, kad tai gali ymiai sumainti kreipi diskin atmint skaii. Aiku tokie bandymai yra euristiniai, jie remiasi noru objektus, esanius geometrinje erdvje arti vienas kito, ir antrinje atmintyje dstyti arti vienas kito. Vienas i populiariausi metod yra iplstinis dstymas, apibendrintas daugiamaiam atvejui - vadinamasis grid file. Yra daug jo modifikacij, taiau visos jos remiasi viena idja - geometrins erdvs skaidymu gardeles. Gardels yra gaunamos skaidant erdv ploktumomis, lygiagreiomis su koordinatinmis, taiau jos gali bti nevienodo dydio ir formos. Gardels gali bti sujungtos buketus taip, kad vienas buketas atitikt vien atminties puslap. Kaip ir iplstinio dstymo algoritme, gardelms sudaroma rodykl. Ji irgi turi bti pritaikyta saugoti iorinje atmintyje. Rodykls pagrind sudaro koordinai ai dalijimo intervalai, kuriais remiantis formuojama vadinamoji liniuot, pritaikyta saugoti vidinje atmintyje. Modeliniam udaviniui sudarytas grid file parodytas 26 pav. Jame vienas skaidymo metu gautas staiakampis atitinka vien disko puslap.

c1

c2

p1

p2 c3 c4

p3

vienas disko puslapis


p4 p5 c5

26 pav. Modelinio udavinio grid file. Paieka grid file struktroje atliekama taip: i pradi randamas iekomojo tako koordinai isidstymas liniuotje ir nusprendiama, kur gardeli rodykls puslap diske reikia skaityti; po to analizuojamas nuskaitytas puslapis ir nustatoma, kur gardels puslap diske reikia skaityti, kad galutinai nusprsti, ar takas yra geometrinje erdvje. Todl paiekos metu reikia (maiausiai) du kartus kreiptis iorin atmint - tokia yra paiekos operacijos kaina. Paiekos operacija reikalinga
85

Duomen struktros ir algoritmai

ir terpiant nauj element struktr. Jos metu surandama gardel, o teisingiau disko puslapis, kur terpiamas elementas. Jei puslapis nepilnas, terpimo operacija papildom veiksm nereikalauja. Taiau jei puslapis pilnas, liniuot vedama nauja ploktuma, duomen buketas yra skaidomas ia ploktuma du buketus ir atitinkamas disko puslapis perraomas du puslapius. iuo atveju reikia pakeisti ir gardels rodykl. Visi ie veiksmai reikalauja papildom I/O operacij. Taiau dar daugiau struktros ir disko pertvarkym gali prireikti imetimo operacijos atveju. Jei paalinus element i puslapio jame liks informacijos kiekis tampa maesnis u leistin, puslap reikia sujungti su kitu gretimu. Taiau tai galima tik tada, kai ir gretimame informacijos kiekis yra maesnis u leistin, ir norint tai pasiekti gali tekti pertvarkyti vis geometrins erdvs idstym diske. Btent tokiam pertvarkymui efektyviai realizuoti yra pasilyti papildomi algoritmai ir struktros (vadinamieji neighbor system ir buddy system). Iplstinio dstymo idja daugiamaiu atveju apibendrinta ir kitaip - algoritmuose EXCELL, BANG file, dviej lygi grid file, dvynuk grid file, kituose metoduose. EXCELL (odi Extendible CELL sutrumpinimas) metodu geometrin erdv siloma skaidyti reguliarias vienodo dydio gardeles, o terpimo ar imetimo atveju visas jas dvigubinti ar perpus mainti, atitinkamai didinant ar mainant skaidymo rodykl. Greitai paiekai rodyklje is metodas silo naudoti hierarchines struktras. Kad hierarchijos nebt perdaug gilios, jos norimu momentu gali bti ubaigiamos specialiai konstruojamais puslapiais (vadinamaisiais overflow pages). Dviej lygi grid file metodas gardels rodyklei silo taikyti gardels konstrukcij, t. y. rodykl interpretuoti kaip geometrin erdv ir j skaidyti gardeles. Metodas BANG file (odi Balanced And Nested Grid sutrumpinimas) gardeles silo konstruoti bet kokio tinkamo daugiakampio formos, be to, leidia j sankirtai bti netuiai. Netuios sankirtos gali bti naudojamos hierarchiniams mediams, priskirtiems gardeli rodyklei, ibalansuoti. Dvynuk grid file metodas silo geometrin erdv skaidyti dvi skirtingas gardeli sistemas, susiejant jas taip, kad element terpimo ar imetimo atveju duomenis bt galima dinamikai perkelti i vienos sistemos kit. Be iplstinio dstymo daugiamai apibendrinim, kurie ia buvo paminti, dar yra daug kitoki metod, besiremiani idstymo funkcijomis. Tai ir daugiamatis tiesinis idstymas, ir vadinamieji buddy-mediai, ir daugelis kit. Visi jie turi teigiam ir neigiam savybi. Vienuose i j netolygiai pasiskirsts skirting operacij sudtingumas, kiti labai sudtingi programuoti, treti naudoja perdaug papildomos atminties. Taiau kiekvienas i j yra tinkamas tam tikriems duomenims ir taikymams. Todl prie nusprendiant, kuriuos i j panaudoti, o kuriuos atmesti, turi bti atlikta detali taikomojo udavinio analiz. 5.2.2. Daugiamaiai hierarchiniai metodai Hierarchiniai metodai remiasi dvejetainiais ar daugiamaiais mediais, jie kitaip negu idstymo metodai, neskaiiuoja atminties adres, taiau duomenis kaip ir anksiau jungia buketus. Kiekvienas medio lapas atitinka duomen buket ir puslap diske, o vidins medi virns skiriamos nuorodoms saugoti ir todl atitinka tam tikrus geometrinius poerdvius. Skirtumai tarp i struktr ir j sudtingum bei realizacij daugiausia remiasi erdvi ypatybmis. k-d-B-mediai jungia adaptyvi k-d-medi ir B-medi konstravimo ypatumus. Jie skaido geometrin erdv lygiai taip, kaip adaptyvs k-d-mediai ir gautiems poerdviams priskiria vidines virnes. Poerdviai, priskiriami broliams, nesikerta, o j sjunga apima vis erdv. Duomen takai, priskiriami atskiriems medio lapams, yra i vieno skaidinio ir saugomi viename disko puslapyje. k-d-B-mediai yra visikai subalansuoti mediai, pritaikyti esamam duomen pasiskirstymui. Modelin udavin atitinkantis k-d-B-medis pavaizduotas 27 pav.

86

Duomen struktros ir algoritmai

c1

c2

p1

p2 c3 c4

p3

p4 p5

c5

c1

p2 c3

p4 p5

c1 c3

p2

p4 p5

disko puslapiai

c2

p1

p3 c4

c5

c2 p1 p3

c4 c5

disko puslapiai

27 pav. Modelinio udavinio k-d-B-medis.

87

Duomen struktros ir algoritmai

Paiekos operacija atliekama lygiai taip kaip ir adaptyviame k-d-medyje. Prie terpiant element, paiekos metu randamas reikiamas duomen buketas ir, jei disko puslapyje yra vietos, elementas ten raomas. Nesant vietos puslapyje, buketas skaidomas du, atitinkamos vidins virns keiiamos taip, kaip tai buvo daroma 2-3-4-medyje (arba B-medyje). Vidini virni keitimas gali apimti kelis medio lygius. Dl ios prieasties negalima sakyti, kad k-d-B-struktra visada efektyvi - galimi atvejai, kai atmintis bus labai netaupiai naudojama. Lygiai tokiomis pat ypatybmis pasiymi ir imetimo operacija. hB-mediai (holey brick tree) konstravimo maniera yra giminingi k-d-B-mediams, skiriasi tik poerdvi skaidymo taisykls - poerdvi takams gali bti taikomi skirtingi atributai. Todl vidines virnes atitinka ne d-maiai intervalai, bet tokie, i kuri gali bti gaunami interval poaibiai. Erdvin struktra, charakteringa hB-mediams, labai panai fraktalin piein. Modelin udaviniui atitinkantis hB-medis parodytas 28 pav. x3 D
c1 c2 p1

C y3
p2 c3 c4 p3

y1 E y4 A
p4 p5 c5

y2

B x1

F x2 x1 u u y1 w w x1 x2 y1 w D E F y2 F

u y4 A

B x3 C y3 D

28 pav. Modelinio udavinio hB-medis. LSD-medis geometrins erdvs skaidyme remiasi adaptyviais k-d-mediais, taiau erdv skaido nelygias gardeles. itaip algoritmas efektyviai prisitaiko prie esamo duomen pasiskirstymo, o naudojant special puslapiavimo algoritm gaunamas subalansuotas medis. Jei duomenys netelpa vidinje atmintyje, algoritmas identifikuoja pomedius, kuriuos tikslinga perkelti iorin atmint. Detalus algoritmo apraymas ir ypa jo realizavimas labai priklauso nuo duomen ir geometrins erdvs. Modelinio udavinio LSD-medio vaizdas pateiktas 29 pav.
88

Duomen struktros ir algoritmai

c1

c2

p1

p2

p3

x2
c3 c4

y3 y2

y1
p4 p5 c5

x1 x: x1 y: y1 vidin rodykl

y: y2 y: y3 x: x3 disko c1 p2 c3 puslapiai p4 p5 c2

iorin rodykl

p1 p3

c4

c5

29 pav. Modelinio udavinio LSD-medis. 5.2.3. Erdviniai kreipties metodai Manipuliacijos su erdviniais duomenimis yra labai skirtingos ir todl joms taikomi labai skirtingi principai. Iki iol nagrintos duomen struktros buvo suformuluotos ir tinkamos daugiausia tam atvejui, kai geometrinje figroje reikia iekoti tak arba jais identifikuojam objekt. Taiau geografini duomen bazs, operuojanios daugiakampiais, ar mechanins CADsistemos, kuri pagrindiniai objektai yra trimaiai briaunainiai, reikalauja daug sudtingesni algoritm. Norint pritaikyti tak paiekos algoritmus tokiems ir panaiems taikymams, reikia papildomai naudoti i algoritm modifikavimo procedras: transformacijas (object mapping); srii persidengim (overlapping regions, object bounding); srii atkartojim (clipping, object duplication). Transformacijos. Objektus, sudarytus i paprast geometrini figr (apskritim, trikampi, staiakampi ir pan.), galima transformuoti takus didesni matavim erdvje. Pavyzdiui, atkarp ir jos viet ploktumoje pilnai apibria atkarpos gal koordinats, t.y. dvi
89

Duomen struktros ir algoritmai

skaii poros, o i j gaut skaii ketvert galima interpretuoti kaip tak keturmatje Euklido erdvje. T pai atkarp galima aprayti ir kitaip: jos centro koordinatmis, atkarpos ilgiu ir kampu, kur atkarpa sudaro su x aimi. Visi ie skaiiai irgi charakterizuoja tak keturmatje erdvje. Galimi ir kitokie figr atvaizdavimai takus didesni matavim erdvje. Kad ir koks bt atvaizdavimas, objektams kompiuterio atmintyje dstyti ir iekoti gali bti naudojami takiniai paiekos metodai. Nusprendus, kokias transformacijas i pradins erdvs didesni matavim erdv ir kokius takinius kreipties metodus nagrinjamame udavinyje tikslinga naudoti, reikia formuluoti taisykles, kaip erdvins paiekos uklausos, manipuliacijos su duomen sritimis, duomen terpimas ar imetimas (pradinje erdvje) bus transformuojami operacijas su takais (vaizdo erdvje). Daniausiai ios operacijos susiveda tak identifikavimo ir duomen interval ar buket iskyrim. Realizuojant tok mechanizm, labai svarbus yra operacij efektyvumas. Praktikai uklaus formulavimas ir vykdymas vaizdo erdvje yra kur kas sudtingesnis, negu pradinje erdvje, todl btina kompleksin viso io proceso analiz. Be to, reikia turti omenyje, kad transformacijas galima gan paprastai formuluoti ir naudoti tik nesudtingiems geometriniams objektams. Jei objektai sudtingesni, pvz., vairi form daugiakampiai, sunku rasti kok nors akivaizd j atvaizdavim didesni matavim takus. Priklausomai nuo konkretaus udavinio galima arba iuos objektus aproksimuoti paprastesniais (pvz., naudoti minimalius gaubiamuosius staiakampius ar trikampius), arba objektus ir takus erdvje sutvarkyti specialiu bdu (pvz., upildyti geometrin erdv fraktalinmis kreivmis), arba pereiti prie kitoki vaizdavimo bd. Per pastaruosius 5-7 metus ioms problemoms sprsti buvo pasilyta daug vairi metod ir algoritm. Srii persidengimas. Takinius kreipties metodus galima modifikuoti, pritaikyti erdvinms sritims saugoti ir su jomis manipuliuoti, leidiant duomenis i susikertani srii (t.y. pasikartojanius takus ar figras) dstyti skirtinguose duomen buketuose. Yra nemaai sistem, kuriose i idja realizuota. J patirtis teigia, kad algoritm funkcionalumas ilieka beveik toks pat (nes hierarchini struktr gylis padidja neymiai). Taiau kitas sistemos darbo parametras naumas - gali labai keistis priklausomai nuo to, koki geometrins erdvs dal upildo duomenys. Jei terpiami duomenys vis laik didina susikertani srii skaii ir sankirt tr, tam tikros duomen rodykls gali tapti labai didels ir neefektyvios. Dar vienas, nors ir maesnis pavojus, slypintis tokiose struktrose - neapibrtumas terpiant naujus elementus susikertanias sritis (t.y. kuriems buketams reikia priskirti naujus elementus, kai jie yra susikertaniose srityse). Nesiimant tam speciali priemoni, paiekos struktros gali bti vaizduojamos nesubalansuotais mediais arba terpimo operacijos metu gali prireikti daug parengiamj skaiiavim. i problema iki iol buvo sprendiama euristiniais metodais. Srii atkartojimas. Paiekos schemos, pagrstos srii atkartojimu, eliminuoja srii netuias sankirtas ir ivengia j tolimensniame konstravime. Netuioms sankirtoms yra priskiriami keli duomen buketai, saugantys vairiar informacij: sankirtos duomen turin, atributus, srities geometrij ir pan. Vadinasi, hierarchini duomen struktr paiekos akos yra vienareikms, o objekt atributai atskirti (informacija apie objekto form saugoma atskirai nuo objekto turinio). Aiku, kad tokioje struktroje paieka yra greita, ar tai bt objekt turinio, ar j formos uklausa. io metodo problemos susij su duomen terpimo ir imetimo operacijomis. terpiant elementus, gali prireikti sritis skaidyti specialiomis hiperploktumomis, o informacij apie objekt saugoti keliuose puslapiuose, viename i j raant srities geometrines charakteristikas, kitame - turin, treiame - specialius atributus, ir pan. itoks duomen saugojimo perteklingumas kelia pavoj, kad struktra gali isigimti, ne tik neleistinai ilgindama paiekos laik, bet ir didindama sankirtoms atstovaujani buket skaii. Be to, terpimo metu gali didti srii sankirtos dydis. Taigi, srii atkartojimo atveju geometrinje erdvje gali neutekti vietos duomen ipltimams dstyti, atsiras vadinamoji aklaviet (deadlock), kuriai isprsti gali prireikti pertvarkyti visus struktros duomenis. Dar viena galima problema - duomen buket skaidymas. Paprastai
90

Duomen struktros ir algoritmai

kiekvienas buketas atitinka tam tikr geometrin srit arba jos atributus. Taiau element terpimo metu disko puslapyje turi bti pakankamai vietos naujiems duomenims. Jei vietos puslapyje neutenka, duomen buket reikia skaidyti, taiau nekeisti paios srities. Vadinasi, vienai sriiai ar vienam srities apraymui gali bti skirti keli duomen buketai. Aiku, kad itokia situacija gali pabloginti paiekos charakteristikas ir algoritmo realizavim. Daugiamai, erdvini ir pan. duomen vedimo kompiuteri atmint, saugojimo joje, paiekos ir ivedimo algoritmai bei atitinkamos duomen struktros yra iuo metu gan plaiai ir intensyviai tiriamos, joms dar nra susiklosiusios vieningos teorijos. Todl dar nra ir vadovli, kuriuose bt nagrinjamos ios struktros. ia pateikta mediaga yra surinkta daugiausia i straipsni urnaluose, technini apra, monografij, kitoki panaaus pobdio leidini. Dalis pateikiam struktr aprayta (daniausiai kitokiame kontekste) [14] leidinyje. Be to, daugiamai duomen struktr ir algoritm yra pasilyta labai daug. Jei tekstinio tipo duomenims yra susiklosiusi tam tikra klasikin teorija ir jos pagrindins struktros iame leidinyje buvo pateiktos, tai apie erdvines arba daugiamates struktras to negalima pasakyti. Liko visikai neaprayti daugiamai erdvi sutvarkymo metodai (pvz., upildanios erdv kreivs ir ztvarkiniai), daugiasieniai mediai, R-mediai ir jais besiremiantys algoritmai, hierarchini daugiamai briaunaini struktros, daugiasluoksniai gardeli failai, ir pan.

91

Duomen struktros ir algoritmai

6. Udaviniai ir pratimai
ia pateikiami udaviniai yra suskirstyti grupes. Kiekvienos grups udaviniams, ypa j sprendimo bdui, keliami kitokie reikalavimai.

6.1. Pirmoji udavini grup


ios grups udaviniai nesudtingi, pagrindinis tikslas yra parayti iems udaviniams tokias programas, kuriose nebt nei vienos bereikalingai vykdomos operacijos, ir rodyti, kad programos isiskiria btent ia savybe. 1. Surasti por didiausi skaii, kuri didiausias bendrasis daliklis (gcd) yra lygus m ir kurie Paskalio sistemoje gali bti apibrti kaip integer tipo kintamieji. 2. Parayti program, skaiiuojani Fibonaio skaii sek iki duoto skaiiaus n. 3. Realizuoti dviej dvejetaini n-bitini skaii, saugom masyvuose A(n) ir B(n), sudt. Sum rayti masyv C(n+1). 4. Realizuoti n-ojo laipsnio vieno kintamojo polinomo reikmi skaiiavim pagal Hornerio schem. 5. Suriuoti masyve A(n) saugomus skaiius, randant maiausi i j ir raant j masyv B(n), po to taikant i procedr pakartotinai. 6. Masyve A(n) yra n skirting skaii. Inversija vadinama situacija, kai indeksai i < j, o A(i) > A(j). Suskaiiuoti inversij skaii masyvui A. 7. Parayti program, kuri i N skaii masyvo irinkt tris skirtingus skaiius taip, kad j suma dalytsi i k. 8. Skaii seka isiskiria savybe: a1 < a2 < a3 < ... < an. Parayti program, kuri nustatyt, kada ai = i. 9. Svarbiausiu masyvo elementu vadinamas toks, kuris pasikartoja daugiau negu n/2 kart. Sudaryti program, kuri rast svarbiausi element, arba nustatyt, kad tokio nra. 10. Parayti program,kuri tikrint dalumo i skaiiaus n poymius. 11. Sudauginti du didelius skaiius M ir N greitos daugybos metodu, taikant j rekursyviai: M = 10nK + L, N = 10nP + R. 12. Parayti program, kuri sudaryt daugybos lentel. 13. Sukurti algoritm ir parayti program, kuri vien simboli sek x pervest kit simboli sek y, terpdama simbol arba imesdama j ir atlikdama minimal kiek toki operacij. 14. Sukurti algoritm ir parayti program, surandani, kurios i atkarp ploktumoje yra lygiagreios. 15. Sukurti algoritm ir parayti program, surandani, kiek atkarp por ploktumoje kertasi. 16. Parayti program realizuojani div ir mod procedras. 17. Parayti program, kuri sveikiems teigiamiems skaiiams a, b, c rast tiesins lygties a*x + b*y = c sveikaskaiius sprendinius, arba nustatyt, kad toki nra. 18. Parayti program, skaiiuojani funkcijos sin(x) reikmes. 19. Parayti program, skaiiuojani derini skaii Ckn.

6.2. Antroji udavini grup


ios grups udavini tikslas - patikrinti duomen struktr programavimo gdius. 1. Realizuoti operacijas su dvejetainiu prefiksiniu mediu masyvo pagrindu.
92

Duomen struktros ir algoritmai

2. Realizuoti operacijas su dvejetainiu infiksiniu mediu masyvo pagrindu. 3. Realizuoti operacijas su dvejetainiu postfiksiniu mediu masyvo pagrindu. 4. Realizuoti operacijas su dvejetainiu infiksiniu mediu rodykls pagrindu. 5. Realizuoti operacijas su dvejetainiu prefiksiniu mediu rodykls pagrindu. 6. Realizuoti operacijas su dvejetainiu postfiksiniu mediu rodykls pagrindu. 7. Realizuoti operacijas su rekursyviu mediu. 8. Realizuoti operacijas su mediu (nuorodos kairj sn ir dein brol) masyvo pagrindu. 9. Realizuoti operacijas su mediu (nuorodos kairj sn ir dein brol) rodykls pagrindu. 10. Realizuoti operacijas su aibmis bitmap vektoriaus pagrindu. 11. Sudaryti program, realizuojani atviro adresavimo dstymo algoritm operacijoms insert, search, delete. 12. Sudaryti program, realizuojani dvigubo dstymo metod operacijoms insert, search, delete. 13. Realizuoti Patricia algoritm. 14. Realizuoti skaitmenins paiekos algoritm (abiem knygoje apraytais atvejais). 15. Realizuoti operacij delete B-medyje. 16. Realizuoti extendible hashing paiekos algoritm: terpimo ir paiekos operacijas. 17. Realizuoti bottom-up mergesort riavimo metod. 18. Realizuoti top-down mergesort riavimo metod. 19. Realizuoti heapsort metod. 20. Realizuoti terpimo ir imetimo operacijas heap struktroje. 21. Realizuoti dviej prioritetini eili suliejimo operacij. 22. Realizuoti Knuth-Morris-Pratto algoritm. 23. Realizuoti Boyer-Mooreo algoritm. 24. Realizuoti Rabin-Karpo algoritm.

6.3. Treioji udavini grup


ios grups udaviniai yra sudtingesni, j sprendime ir realizavime reikia taikyti vairius duomen struktr algoritmus. 1. Rasti dviej aukto laipsnio polinom g(x) ir h(x) didiausi bendrj dalikl. 2. Rasti dviej dideli skaii (keli deimi ar imt skaitmen eils) M ir N didiausi bendrj dalikl. 3. Kiekvien skaii nuo 1 iki n iskaidyti ne daugiau kaip k dmen suma. Kaip parinkti tokius skirtingus dmenis, kad j skaiius bt minimalus? 4. Sukurti algoritm ir parayti program, kuri generuot atsitiktin N-bit (N>1000) sek, o po to rast visus posekius, lygius paskutiniams k bit. 5. Sukurti algoritm ir parayti program, kuri dviej matavim tekste rast visas vietas, kuriose yra tam tikras posekis. 6. Sukurti algoritm ir parayti program, kuri sek aibje S = (y1, y2,... yn) iskirt tas, kurios eina sek x. 7. Sukurti algoritm ir parayti program, kuri surast ilgiausi bendrj tolyd posek dviejuose duotose sekose. 8. Sukurti algoritm ir parayti program, kuri i aibs S poaibi sistemos {s1, s2,... sn } irinkt minimal skaii poaibi, kuri sjunga padengt vis aib. 9. Sukurti algoritm ir parayti program, kuri naudodama medio duomen struktr suspaust tekstin fail. 10. Sukurti algoritm ir parayti program, kuri perkoduot (ir dekoduot) bet kok fail tekstin.
93

Duomen struktros ir algoritmai

11. Sukurti algoritm ir parayti program, kuri aib i n skaii i pradi riuoja Quicksort metodu, o likus maesniems aibms, pereina prie terpimo metodo. Kada toks perjimas tikslingas? 12. Sukurti efektyv algoritm ir parayti program, kuri i n skaii surast k maiausi. 13. Parayti programas ir empirikai palyginti metodus, kai formuojamos heap aibs i atsitiktini skaii, naudojant dvi procedras: bottom-up heap ir top-down heap. 14. Parayti programas heapsort, kada naudojamos dvi skirtingos operacijos: imesti maiausi ir imesti didiausi (heap aib formuojama taip, kaip buvo nagrinta). 15. Parayti program, kuri natraliai urayt algebrin reikin (su skliausteliais) pertvarkyt postfiksin reikin. Kurias struktras geriau naudoti: stek, eil, dek? 16. Sukurti algoritm ir parayti program, kuri polinomus vien i kito dalyt greitos daugybos metodu (polinom laipsnis gali bti labai didelis). 17. Skaii aib yra skaidoma kelias dalis taip, kad i dali sumos bt kiek galima labiau viena kitai artimos. princip rekursyviai galima pritaikyti vis maesnms aibms. Panaudoti dvejetainius ar 2-3, ar 2-3-4-medius. Parayti atitinkam program ir atlikti udavinio analiz. 18. Sudaryti program, kuri naudodama atsitiktini skaii generatori, sudaryt raudonus-juodus medius (ne maiau 1000 virni) ir vertint vidutin ak ilg nuo aknies iki lap. 19. Sudaryti program, kuri pagal raudon-juod med atstatyt 2-3-4-med, ir atvirkiai. 20. Realizuoti operacijas su trie struktra, kai duomenys yra saugomi srao pavidalu masyvo pagrindu. 21. Realizuoti dviej iretint matric daugyb. Algoritmo efektyvum palyginti su standartiniais metodais. 22. Realizuoti dviej iretint polinom daugyb. Algoritmo efektyvum palyginti su standartiniais metodais. 23. Realizuoti dviej labai dideli dvejetaini skaii daugyb. Algoritmo sudtingum palyginti su standartiniais metodais. 24. Sudaryti algoritm ir parayti program, kuris algebrin reikin pertvarkyt prefiksin pavidal. 25. Parayti program, kuri dvejetainiame paiekos medyje rast visas virnes, kurios patenka tam tikr reikmi diapazon. 26. Parayti program, kuri 2-3-4-medyje rast visas virnes, patenkanias tam tikrus diapazonus (j gali bti keli).

6.4. Pratimai tiriamajam darbui


1. Kompleksikai itirti dvejetain paiek ir dvejetainius paiekos medius: ivesti j sudtingumo priklausomai nuo duomen struktros formules; pateikti rekursyvias i algoritm realizacijos programas. 2. Itirti dvejetainius paiekos medius: nustatyti, ar verta terpti raus med j danum majimo tvarka, kai i anksto inomi paiekos rakt danumai; modifikuoti dvejetainius medius, kad jie galt turti pasikartojanius raktus; sudaryti rekursyvias programas, spausdinanias medi virnes eils tvarka. 3. Itirti raudonus-juodus medius: naudojant atsitiktini skaii generatorius, itirti i medi statistines savybes (ak minimalius, maksimalius, vidutinius ilgius; santykius tarp juod ir raudon-juod ak; kitas savybes); palyginti iuos medius su nebalansuotais dvejetainiais paiekos mediais. 4. Sukurti keturi spalv ir atuoni spalv medi teorij (kokio tipo paiekos struktroms gali atstovauti mediai, kai raudoname-juodame medyje spalvai ymti yra naudojami du arba trys bitai), pateikti pavyzdi.
94

Duomen struktros ir algoritmai

5. Ianalizuoti vairias hash funkcijas: kaip galima hash funkcijas keisti atsitiktini skaii generatoriais ir atvirkiai; kokias funkcijas reikia naudoti, kai inomi reikmi diapazonai, element lentelje skaiius, kai laukiama, kad bus daug pasikartojani rakt reikmi; kaip tirti vairi hash funkcij statistines savybes. 6. Itirti skaitmeninius paiekos medius: naudojant atsitiktini skaii generatorius, itirti i medi statistines savybes; surasti duomen savybes, slygojanias blog struktros trie ibalansavim; surasti kaip reikia taisyti struktr tokiu atveju: 26-i nuorod trie struktr naudojama lotyniko alfabeto raidms identifikuoti, taiau kai kurios raids labai retai sutinkamos. 7. Kompleksikai itirti Patricia algoritm: naudojant atsitiktini skaii generatorius, itirti jo statistines savybes; rasti duomen savybes, kurios Patricia med labai debalansuoja; kada verta parayti programas, spausdinanias Patricia medio virnes didjimo tvarka. 8. Kompleksikai ianalizuoti B-medius: naudojant atsitiktini skaii generatorius, itirti i medi statistines savybes; kokie turi bti santykiai tarp puslapio dydio, sn skaiiaus vienai virnei, virni skaiiaus, prefikso dydio, kad paieka (terpimo operacija, imetimo operacija) medyje bt efektyviausia. 9. Kompleksikai itirti iplstin dstym: naudojant atsitiktini skaii generatorius, itirti io algoritmo statistines savybes; parayti elemento imetimo program ir ianalizuoti jos sudtingum; kaip turi bti modifikuotas iplstinio dstymo algoritmas, kai jis dirba vidinje atmintyje. 10. Modifikuoti visus idstytus sek paiekos algoritmus, kai fragmentas turi vien ar kelis wildcard simbolius, itirti j sudtingum. 11. Kompleksikai itirti Huffmano kodo savybes: kaip kodo ilgis priklauso nuo statistinio danum pasiskirstymo; koks yra dvejetainio failo Huffmano kodas; jei raidi danumai visi skirtingi, ar Huffmano kodas yra vienareikmis; kaip taupyti atmint realizuojant Huffmano algoritm.

95

Duomen struktros ir algoritmai

7. Literatra
1. Sedgewick R. Algorithms. Addison-Wesley Publishing Company, Reading, Massachusets, 1988. 2. Ammeraal L. Algorithms and Data Structures in C++. John Wiley & Sons Ltd., Chichester, 1996. 3. Cormen Th. H., Leiserson Ch. E., Rivest R. L. Introduction to Algorithms. The MIT Press, Cambridge, Massachusets, 1993. 4. Jensen K., Wirth N. Pascal User Manual and Report. Springer-Verlag, Berlin, 1974. 5. Horowitz E., Sahni S., Anderson-Freed S. Fundamentals of Data Structures in C. Computer Science Press, New York, 1993. 6. Carrano F., Helman P., Veroff R. Data Structures and Problem Solving with Turbo Pascal. Walls and Mirrors. The Benjamin/Cummings Publishing Company Inc., 1993. 7. Naps Th. L., Nance D. W., Singh B. Introduction to Computer Science: Programming, Problem Solving and Data Structures. West Publishing Company, St. Paul, Minnesota, 1989. 8. Naps Th. L., Singh B. Program Design with Pascal. West Publishing Company, St. Paul, Minnesota, 1988. 9. Gabrini Ph. J., Kurtz B. L. Data Structures and Algorithms with Modula-2. Addison-Wesley Publishing Company, Reading, Massachusets, 1993. 10. Stubbs D. F., Webre N. W. Data Structures with Abstract Data Types and Modula-2. Brooks Cole Publishing Company, Monterey, California, 1987. 11. Aho A. V., Hopcroft J. E., Ullman J. D. The Design and Analysis of Computer Algorithms. Addison-Wesley Publishing Company, Reading, Massachusets, 1976 (yra vertimas rus kalb). 12. Knuth D. E. The Art of Computer Programming. Addison-Wesley Publishing Company, Reading, Massachusets 1968. 1, 1969. 2, 1973. 3 (yra vertimai rus kalb). 13. Greene D. H., Knuth D. E. Mathematics for the Analysis of Algorithms. Birkhuser, Boston Basel - Stuttgart, 1982 (yra vertimas rus kalb). 14. Khoshafian S., Baker A. B. Multimedia and Imaging Databases. Morgan Kaufmann Publishers, Inc. San Francisco, California, 1996.

96

You might also like