of 32 /32
1. lekcija 1. Jēdziens par datu struktūrām. Galvenais datu struktūras uzdevums ir – kā organizēt datus PC brīvajā operatīvajā atmiņā. Datu tips – tas ir mainīgā pieļaujamo vērtību apgabals (iespējamo vērtību kopu). Piemēram, int (integer) – veselo skaitļu kopa (jebkurš vesels skaitlis). Tas nosaka arī kādas operācijas var veikt. Piemēram, ar int var veikt aritmētiskas operācijas. Ja ir vairāki šie datu elementi un ar visiem šiem elementiem tiek veiktas kaut kādas operācijas, tad tiek izmantotas tā sauktās datu struktūras. Datu struktūra – datu struktūras elementu kopa, kur datu struktūras elements sastāv no datu elementa un saites elementa. S = {(D,R)}, kur S-datu strukt.; D-datu elem.; R-saites elem Saites saista kopā vairākus, šos elementus. dati dati saite dati Loģiskā datu struktūra – kā šo struktūru iedomājas, iztēlojas cilvēks. Fiziskā datu struktūra – kā loģiskā datu struktūra tiek norealizēta datora atmiņā. cilvēks – datora lietotājs Kā programmēt, lai šī programma būtu sakārtota – viegli uztverama arī citam programmētājam vai lietotājam. cilvēks palaiž galveno programmu un komunicē ar to (funkciju main) main class LDS main komunicē ar loģisko datu struktūru - klasi Komunicē ar fizisko datu struktūru class FDS Jānis Šablovskis DatZ 040076 1

1. lekcija 1. Jēdziens par datu struktūrām.fizmati.lv/faili/macibu_materiali/lekciju_konspekti_skrepucis.pdf · 1. lekcija 1. Jēdziens par datu struktūrām. Galvenais datu struktūras

  • Author
    others

  • View
    1

  • Download
    0

Embed Size (px)

Text of 1. lekcija 1. Jēdziens par datu...

  • 1. lekcija 1. Jēdziens par datu struktūrām.

    Galvenais datu struktūras uzdevums ir – kā organizēt datus PC brīvajā operatīvajā atmiņā. • Datu tips – tas ir mainīgā pieļaujamo vērtību apgabals (iespējamo vērtību kopu).

    Piemēram, int (integer) – veselo skaitļu kopa (jebkurš vesels skaitlis). Tas nosaka arī kādas operācijas var veikt. Piemēram, ar int var veikt aritmētiskas operācijas. Ja ir vairāki šie datu elementi un ar visiem šiem elementiem tiek veiktas kaut kādas operācijas, tad tiek izmantotas tā sauktās datu struktūras.

    • Datu struktūra – datu struktūras elementu kopa, kur datu struktūras elements sastāv no

    datu elementa un saites elementa. S = {(D,R)}, kur S-datu strukt.; D-datu elem.; R-saites elem Saites saista kopā vairākus, šos elementus.

    dati

    dati

    saite dati

    Loģiskā datu struktūra – kā šo struktūru iedomājas, iztēlojas cilvēks. Fiziskā datu struktūra – kā loģiskā datu struktūra tiek norealizēta datora atmiņā.

    cilvēks – datora lietotājs Kā programmēt, lai šī programma būtu sakārtota – viegli uztverama arī citam programmētājam vai lietotājam.

    cilvēks palaiž galveno programmu un komunicē ar to (funkciju main)

    main

    class LDS

    main komunicē ar loģisko datu struktūru - klasi

    Komunicē ar fizisko datu struktūru

    class FDS

    Jānis Šablovskis DatZ 040076 1

  • 2 lekcija [praktiskie darbi] Pointers

    (norādes datu tips)

    Datoru atmiņa sastāv no bitu rindām, kur 8 biti veido 1 baitu. Katrs baits ir numurējams, šo numuru sauc par baita adresi. Var arī vairākos baitos glabāt informāciju, tad adrese ir sākot ar pirmo baitu.

    int a kompilators zinās, ka šai programmai ir jāparedz vieta, datora atmiņā, kur varēs ierakstīt veselo skaitli a. datora atmiņa

    Jānis Šablovskis DatZ 040076 1

    a

    int*p deklarēts tiek pointer tipa mainīgais. p

    Iedotajā atmiņas apgabalā varēsim ierakstīt adresi (baita numuru) – ierakstīt informāciju, kurā vietā atmiņā stāv kaut kāds intedžers.

    new galā pieraksta datu tipu (piem. new int); new atrod brīvajā atmiņā vienu apgabalu, arī sistēmai rezervē šo apgabalu. New atgriež adresi uz aizņemto apgabalu.

    p = new int ; p tiek piešķirta šī adrese p = new int delete tiek atbrīvota atmiņa no aizņemtā apgabala. delete(p) – atbrīvo p apgabalu. NULL konstante pointeriem, NULL – vērtība ponterim, kad tas nekur nenorāda, ja adreses

    laukā ierakstīts NULL – šim pointeream atmiņas apgabals tad nav. Tāpēc korekti būtu pēc delete p=NULL (p piešķir NULL), tagad iznāk, ka q norāda uz brīvu atmiņu.

    New un delete ir jābūt „sapārotiem” – cik reizes izpilda new, tik reizes jābūt izpildītam arī delete, bet ne vienmēr sakrīt, jo skaita cik reizes izpildās, bet, ja new vai delete ir ielikts ciklā, tad šis skaits var atšķirties. p pati adrese *p (izmanto pašā programmā, nevis deklarācijā) Apzīmē to atmiņas apgabalu uz, ko

    norāda šis pointers.

    int*q; (piešķiršana) Nokopē adresi no p un iekopē q apgabalā, tagad q norādīs tur pat, q=p kura vērtība piešķirta p

    p new

    p q

    p q

  • Jānis Šablovskis DatZ 040076 2

    Tipiskās kļūdas izmantojot pointerus:

    • Nevajag izmantot pointerus bez īpašas vajadzības, jo tie sarežģī programmas kodu. • Ir jāparūpējas par to, lai nepaliktu pointeri, kas norāda uz atbrīvotajiem atmiņas

    apgabaliem

    Klases

    Salikts mainīgais, piemēram, datumu raksturo 3 skaitļi, tātad jānodeklarē 3 mainīgie: struct datums { int gads,men,diena; } datums d1,d2; //katrā būs iekšā visi trīs mainīgie

    d1.gads=2005; d1.men=02; d1.diena=07;

  • 3. lekcija Datu struktūras klasifikācija:

    • Iedalās lineārajās (vienkāršākās) un nelineārajās (visas pārējās). • Pēc fiziskās eksistences – saites elementa datu struktūras elements sastāv no – datu

    elementa un saites elementa. (Nesaistītās datu struktūras un saistītās datu struktūras.) • Pēc datu struktūras elementu skaitu struktūrā iedala:

    o Statiskās datu struktūras – elementu skaits visā struktūras pastāvēšanas laikā ir nemainīgs.

    o Daļēji statiskās datu struktūras – elementu skaits datu struktūrā var mainīties, bet nepārsniegt kaut kādu noteiktu robežu

    o Dinamiskās datu struktūras – elementu skaits datu struktūrā var brīvi mainīties.

    MASĪVI Masīvu klasifikācija: Statiska datu struktūra (uzreiz tiek noteikti cik tur būs elementi). Masīvi ir lineāra datu struktūra, tas ir arī nesaistīta datu struktūra. Datu struktūras operācijas: Piekļūšana elementam pēc uzrādītā elementa indeksa. Datora operatīvā atmiņa ir kā liels viendimensionāls masīvs. Masīvs – numurēta elementu virkne. Masīvs – elementa virkne, numurēta.

    0 1 2 3 4 5 ..... ...... . .. . . .. . . .

    A l

    l nosaka, cik baitus aizņem masīvs.. 1. elementa adrese A+l 2. elementa adrese A+2l ; utt Masīva adresi var izrēķināt pēc šādas formulas: adrese(m[i]) = A + l ⋅ i, kur i∈[0; n-1] Divdimensionāls masīvs:

    Ar indeksiem nosaka, kuru elementu grib paņemt. Divdimensionālā masīvā fiziskā datu struktūra ir viendimensionāls masīvs.

    0 1 2 3 40 1 x 2 3 x 4

    Vienkāršāk sakot: divdimensionāls masīvs ir ļoti garš viendimensionāls masīvs. Atrašana: adz(m[i][j]) = A + l ⋅ i+ l`⋅ j ; (atrod lielajā apgabalā mazo elementu)

    l`

    0 1 2 3 4 0 1 2 3 4 0 1 2 3 4 .........................

    21 0

    Jānis Šablovskis DatZ 040076 1

  • LINEĀRIE SARAKSTI Vienvirziensaraksts Lineārais vienvirzienu saraksts ir lineāra datu struktūra (dinamisku datu struktūru). Salīdzinot lineāru vienvirziena sarakstu ar viendimensionālu masīvu; masīvam pēc indeksa var tikt klāt jebkuram elementam. Ciklā – jo masīvā vairāk elementu, jo cikls ilgāk strādās. Algoritms strādā konstantā laikā, ja algoritma operāciju skaits nav atkarīgs no datu apjoma. Piemēram, ja datu struktūrā ir n elementi, tad algoritmam ir jāizdara kaut kas n reizes. Lineārais saraksts:

    A

    [saites elements]

    [atzīmē, ka beigas]

    [norāda, kur atrodas nākamais elements (saites)]

    Operācijas kādas var veikt konstanta laikā ar vienvirziena sarakstu.

    Jānis Šablovskis DatZ 040076 2

    A

    P

    t • Iespraust sarakstā elementu, ja ir zināma vieta, kur iespraust.

    Pointera t apgabalu iekopē P apgabalā. (P apgabalam piešķir pašu P).

    • Elementa izslēgšana, dara līdzīgi kā ar elementa iespraušanu. (norāda, ka vajag izsviest nākošo, ko norāda pointers).

    • Nākošā atrašana – ir zināms viens elements un viņa adrese, nākamo atrod “paprasot” uz

    kuru norāda šis elements. (Lai atrastu i elementu, tad šim elementam i reizes jāprasa nākamais.)

  • 4. lekcija [praktiskie darbi] struct elem { P int data; elem*next;}; elem*p; p = new elem; (*p)data = 5 tam uz ko norāda p , iekšējai struktūrai piešķir vērtību 5. (*p)data = 5 ; saīsinājumā var rakstīt p->data = 5 P ir norāde, atmiņas apgabalam, kurš ir struktūra iekšējam apgabalam ar vērtību 5. p-> next = new elem // piešķiršanas komanda. Pēc šīs komandas nāk klāt apgabali:

    5

    Jaunizveidotais atmiņas apgabals uz ko norāda P

    Vieta, kur ierakstīt datus

    Kā apraksta klasi:

    • Privātajā daļā – norāde uz sākuma elementu (viens mainīgais). • Publiskajā daļā – jāliek tas, ko gribam nodefinēt -> ko var darīt ar klasi: lineāro

    vienvirziena sarakstu: 3 operācijas – ievietot, izmest, atrast nākamo. Parametri, kas vajadzīgi nākamā atrašanai, elementa izslēgšanai un elementa iespraušanai. struct elem { int data elem*next;} class LVS{ elem*p; public: next elem*(elem*x){ if(x==NULL) return p; nākamā atrašana (ja x=NULL, atgriežam uz pirmo else return x -> next; (p), ja nē, tad uz next.) } void izmest(elem*q){ if(p!=NULL); elem*z; if(q==NULL){ z=p->next; delete p; p=z;} elementa izslēgšana else { if(z!=NULL)){ z=q->next; q->next=z->next; delete z; }} void insert (int a, elem*x) if (x==NULL){ elem*z=p; p=new elem; p->data=a p->next=z;} else{ elementa iespraušana elem*z=new elem; z->next=x->next x->next=z z->data=a; }}

    Jānis Šablovskis DatZ 040076 1

  • 5. lekcija Cikliskais saraksts. Ciklisks saraksts ir kā riņķis; zūd pirmā un pēdējā elementa jēdziens. Lineārais divvirzienu saraksts Atšķirība no vienvirziena saraksta ir tāda, ka divvirzienu sarakstam nāk klāt ceturtā operācija – atrast iepriekšējo. Atšķiras arī datu struktūras elements – pieliek klāt norādes lauku, kas norāda uz iepriekšējo.

    NULL

    Ciklisks divvirziena saraksts:

    STEKS (STACK) Piemērs Kādā kārtībā mašīnas iebrauks sētā, tādā tikai tās arī varēs izbraukt!

    LiFo – last in first out.

    Ja kaut ko liekam šajā stekā, tad varēsim to izņemt tikai apgrieztā sacībā.2 Steks – datu struktūra ar kuru var veikt šādas darbības:

    • Pievienot stekam elementu • Izņemt no steka pēdējo pievienoto elementu •

    Stekus izmanto kompilatoros un operētājsistēmās. Kā ir kaut kas atverošs, ieliekam stekā, bet, ja ir kaut kas aizverošs ņemam ārā no steka. Steka fiziskās struktūras:

    • ielikt • izņemt

    Jānis Šablovskis DatZ 040076 1

  • Steka realizācija masīvā: m masīvs atmiņā [IELIKŠANA] class stack { int m[100]; int s; publicē: int ievieto (int a){ if (s==100) return 0; else m[s++] = a; return 1; };

    [IZNEMŠANA] class stack { int m[100]; int s; publicē: int ievieto (int a){ if (s==0) return -1; else return m[--s]; };

    2 steku realizācija vienā masīvā: Abi steki pārpildās un atbrīvojās vienlaicīgi.

    0 1 2 3 4 5 ..... ...... . .. . . .. . . . n-10

    Indekss pirmajam brīvajam elementam S

    Jānis Šablovskis DatZ 040076 2

  • Jānis Šablovskis DatZ 040076 1

    6. lekcija [praktiskie darbi] KONSTRUKTORS Konstruktors ir klases metode, kura automātiski izpildās pie klases instances (objektu) deklarēšanas. Ja klasē nodefinē metodi ar tādu nosaukumu kā klasei – tas ir konstruktors. Konstruktorus lieto, lai piešķirtu privātajiem mainīgajiem sākuma vērtības. Konstruktorā var būt arī parametri – vērtības parametriem padod pie mainīgo deklarēšanas. Vienai klasei var nodefinēt vairākus konstruktorus, viņi visi sauksies vienādi – tāpat kā klase. Ja ir vairāki konstruktori, tad tiem jābūt ar atšķirīgiem parametriem. Vairākos konstruktoros labāk ir nelietot noklusētos parametrus. Ja klasei definēts konstruktors, tad arī šis konstruktors obligāti ir jālieto. Piemērs: class datums { int gac,men,diena; public: datums (int g){ //definēts tiek konstruktors (ar 1 parametru) gac=g; men=1; diena=1;} } datums (int g, int m, int d){ // konstruktors ar 3 parametriem gac=g; men=m; diena=d; } ...................... // citas publiskās metodes } datums d1(2004) datums d2(2005,3,7) DESTRUKTORS Klases metode, kas automātiski nostrādā katru reizi, kad klases instance (objekts) paliek neredzama – programmas vadība iziet ārā no klases redzamā apgabala. Ja programmā kaut kur ir figūriekavas ( { ), tad, kad būs aizverošās figūriekavas, tad tā būs tā vieta, kas izsauks destruktoru. Destruktoru definē kā publisku metodi, kuras nosaukums ir klases nosaukums tikai ar priekšā pieliktu tildi (~). Piem. ~klases_vards Nevar programmā būt vairāki destruktori, kā arī tam nevar būt parametri (tam nav vajadzīgi parametri, jo destruktors neatgriež vērtību) Destruktorus lieto relatīvi reti, bet lieto, ja klase ir tāda, kas dinamiski aizņem atmiņu.

  • Uzd. Uzrakstīt destruktoru lineārajai vienvirziena struktūrai. class LVS{ elem*p; public: LVS(){ P=NULL;} ~LVS(){elem*tmp;

    } konstruktors while (p!=NULL){ tmp=p; p=p->next; destruktors dlelete tmp;} } Uzd Vienvirziena sarakstam, metodei padod veselu skaitli, šī metode nosaka, vai šāds skaitlis ir vai nav sarakstā. Int mekl(int a){ Elem*q=p; While(q!=0) && (q->data!=a){ Q=nākamais(q);} If(q->data==a); Return 1; Else Return 0; } }

    Jānis Šablovskis DatZ 040076 2

  • 7. lekcija Rindas realizācija Rindu datorsistēmās lieto, piemēram, pie pieslēgtām ierīcēm, kā printeris. Rindas realizē: Fiziskā struktūra – masīvs, var realizēt viendimensionālā masīvā. Privātajā daļā vajag masīvu, kur glabāt rindas datus, vēl nepieciešami divi mainīgie: s – glabā indeksu 1. brīvajam elementam, kurā var ievietot jaunās rindas elementu. Otrs mainīgais – indekss tam elementam, kuru grib ņemt ārā no rindas. C++ kodā šādi: class rinda{ private: int m[101];

    int s,b; public:

    rinda(){ //konstruktors, bez parametriem s=0; // kad rinda tukša s=0,b=0 (sākumā) b=0;}

    }

    masīvs

    0 1 2 3 4 ..............

    b s (sākumā abi elementi norāda uz pirmo elementu masīvā “0”)

    Ja mēs ieliekam pirmo elementu, tad automātiski b norādīs uz nākamo brīvo elementu utt. (liekot iekšā jaunus elementu b visu laiku rādīs uz nākamo tukšo)

    0 1 2 3 4 ..............

    s b

    S norādīs uz pirmo pilno elementu. Ja izmet uz to ko norāda s, tad s tiek pārcelts uz nākamo

    0 1 2 3 4 ..............

    s b Kad pienāk masīva beigas, tad sākas atkal no pirmā elementa, tāpēc vislabāk rindu ir zīmēt riņķa izskatā.

    Jānis Šablovskis DatZ 040076 1

  • Jānis Šablovskis DatZ 040076 2

    Rinda visu laiku “rāpo” uz priekšu.

    n-1

    n-2

    n-3

    3

    2

    1

    0

    b s

    Izņemšana no rindas (realizācija C++) int iznemt(){

    if (s!=b){ //pārbauda vai rinda ir vai nav tukša (s=b) int tmp=[b];

    b=(b+1)%101; return tpm; }

    else return –1;}

    Ja s noķer b, tad rinda būs tukša, tas var notikt jebkurā vietā. Rindā neļauj aizpildīt pēdējo elementu, lai būtu uz kā norādīt s. Ja ir brīvs tikai šis elements, tad rinda ir pilna, tāpēc rindu (masīvu) ņem vienmēr par vienu vairāk, nekā tas ir nepieciešams. Ievietošana rindā (realizācija C++) void ievieto(int a){ if((s+1)%101!=b) //pilnas rindas nosacījums [s]=a; s=(s+1)%101; Rindas realizācija Rindai ir nepieciešamas divas norādes, lai visas operācijas notiktu konstantā laikā. Sākumā abi norāda uz jauno elementu (abi pēc konstruktora ir NULL) Tiek likti iekšā elementi.

    b s

    Ja grib pievienot elementu, tad taisa jaunu elementu, tam pointeram uz kuru norāda s. Izņemt elementu - var izņemot elementu uz ko norāda b un pārceļot pointeru uz nākamo elementu.

  • Jānis Šablovskis DatZ 040076 3

    (A+B)*C-D*E-F/(G+H) infiksā pieraksta forma aritmētiskai izteiksmei. – –*+ABC*DE/F+GH prefiksā pieraksta forma aritmētiskai izteiksmei. AB+C*DE*–FGH+/– postfiksā pieraksta forma aritmētiskai izteiksmei.

    • Ir infiksā formā, ja operācijas apzīmējums ir starp abiem operandiem. (A+B) • Prefiksā formā, ja operācijas apzīmējums ir pirms abiem operandiem. (+AB) • Postfiksā formā, ja operācijas apzīmējums ir pēc abiem operandiem. (AB+)

    A+B = +AB (A+B)*C=*+ABC Iekavas nav vajadzīgas – nav jēgas operāciju prioritātes jēdzienam.

  • Jānis Šablovskis 8. lekcija Algoritms aritmētiskas sistēmas pārvēršanai postfiksā (atbrīvošanās no iekavām). Pirmais algoritms pārvērš postfiksā, otrs algoritms – izrēķina izteiksmes vērtību. Piemērs: (A+B)*C–D*E+G*(F–I).

    Ieeja Izeja Steks( ( A A ( + +( B B +( ) + * * C C * – * – D D – * *– E E *– + *– + G G + * *+ ( (*+ F F (*+ – –(*+ I I –(*+ ) – *+ . *+

    A ir mainīgā apzīmējums, tātad 2. likums Pēc 3. likuma Pēc 4. likuma (ieejā – stekā liekam*) Stekā iet ar augstāku prioritāti

    Likumi: 1. Ja ieejā ir iekava vaļā “(”, tad liekam iekavu stekā. 2. Ja ieejā ir mainīgais “piem. A”, tad to liekam izejā. 3. Ja ieejā ir operācijas apzīmējums “piem. +”, tad papildus jāpārbauda pēdējais ieliktais simbols. 3.1. Ja nav ielikts (tukšs vai iekava), tad operācijas apzīmējumu liekam stekā. 3.2. ja arī stekā pēdējais ieliktais elements ir operācijas apzīmējums, tad tiek salīdzināta

    operācijas prioritāte. Stekā neliek operāciju ar zemāku vai vienādu prioritāti. Tad no steka izņem to operāciju un ieliek izejā – zemākās prioritātes operācija tiek ielikta stekā.

    3.3. Ja stekā atrodas operācija ar stingri zemāku prioritāti nekā ieejā, tad no steka neko ārā neņem, bet ieliek stekā vēl operācijas apzīmējumu no ieejas.

    Tad, kad izteiksme beidzas – viss steka saturs jāpārliek izejā, kamēr steks ir tuksš. Nolasot doto izteiksmi izejā, mēs iegūsim izteiksmi postfiksā: AB+C*DE*–GFI–*+

  • LIKUMI: 1. Ja ieejā redzam mainīgo, tad dabūjam tā vērtību un liekam stekā. 2. Ja ieejā redz operācijas apzīmējumu, tad no steka izņem divas vērtības, ar šīm vērtībām

    izpildām operāciju, un operācijas rezultātu (vērtību) ieliekam atpakaļ stekā. 3. Ja ieraugam izteiksmes beigas, tad stekā stāv tikai viena vērtība un tā ir izteiksmes rezultāts. Infiksā LIKUMI 1. Ja ieejā redzam mainīgo, tad simbolu virkni ieliek stekā. 2. Ja ieejā ir operators, tad no steka izņem divas simbolu virknes. Piemērs: A – viena simbolu virkne A B – divas simbolu virknes A B – izņem abas no steka C (A+B) ((A+B)*C) – simbolu virkne ko ielikām stekā atpakaļ.

    Nelineārā datu struktūra

    Dekarta rezinājums G=(V,R) Divu kopu pāris, kur V – patvaļīga kopa (grafa virsotņu kopa) un R – grafa šķautņu (atteicību) kopa. Grafa ģeometriskā definīcija: virsotņu kopa

    V1V5

    V4 V3

    V2 Grafam ir daudz paveidu, piemēram, ja šķautne pieder V2 V2 tad šo grafu sauc par pseidografu. ∃v∈V: (V,v)∈R tad ir pseidografiks

  • Orientētais grafs: V1V5

    V4 V3

    V2

    ∀i,j (vi;vj)∈R⊃( vj ;vi)∈R Svara grafs – eksistē kaut kāda funkcija f, kas darbojās no šķautņu kopas, reālo skaitļu kopā. ∃f:R->R V1 V2 V3 V4 V5V1 1 1 1 V2 1 1 1 V3 1 1 V4 1 1 V5 1 1 Neorientēta grafa gadījumā kaimiņa matrica sanāk simetriska, ja būtu orientēts grafs, kaimiņu matrica var sanākt nesimetriska. Kaimiņu grafs – vēl viens grafu attēlojums (kaimiņu saraksts)

  • 9. lekcija

    Grafu apstaigāšana (saistītiem grafiem)

    Tas ir process, kurā tiek aplūkota katra grafa virsotne tieši 1 reizi. Secību nosaka grafa uzbūve. Ir divas metodes (algoritmi), kā apstaigāt grafu: Grafu apstaigāšana dziļumā: Apstaigāšana sākas no vienas virsotnes – to padod kā

    parametru.

    • Sāksim ar 1. virsotni • Tagad brīvi izvēlamies kādu no saistītajām

    virsotnēm, piemēram, 2. • Tagad atkal brīvi izvēlas, virsotni, kas saistīta ar 2.

    virsotni (1. neizvēlas, jo tā jau ir apstaigāta) utt. • Kad beidzās neapstaigātās virsotnes, piem. (no 4.),

    tad no turpceļa ir jākāpjas atpakaļ – tātad ejam uz 8 utt. līdz 9.), tagad no 9 varam izvēlēties kādu no neapstaigātajām.

    • Kad esam atkāpušies līdz sākuma virsotnei, tad saka, ka visas virsotnes ir apstaigātas un tālāk vairs, nav kur .

    1 2 3 4 5 6 7 8 9 10

    11

    uz priekšu atpakaļ

    1-2-5-9-8-4-11-10-7-3-6 ?) Kā uzbūvēt algoritmu kodā, kas realizē šo apstaigāšanu . Tas būs rekursīvs algoritms. Ir nepieciešama klase, kas realizē šo apstaigāšanu, un pēc tam pārbauda vai šāds skaitlis jau ir pievienots: pseido kodā:

    viod DFS(v){ //DeepFirstSearch (v) – no šī sākam apstaigāšanu

    visited.add(v); // pasakām, ka v jau apstaigāts; visited ir globāls ...v...; // izpildām vajadzīgās darbības ar v;

    for(w; visi v, kaiminji){ //w-mainās pa visiem virsotnes v kaimiņiem // for cikls tik reizes, cik w būs kaimiņi

    // ja v=1, tad w divas reizesm jo virsotnei v ir // 2 kaimiņi

    if(!visited.ask(w)); // prasām, vai virsotne w vēl nav apstaigāta DFS(w);} // tad rekursīvi izsauc, šo pašu f-ju virsotnē w

    Grafu apstaigāšana dziļumā

    Jānis Šablovskis DatZ 040076 1

    : Izvēlamies patvaļīgi vienu virsotni – izstaigā visas saistītās

    virsotnes, tad vienu virsotni no šīm saistītajām, un šai virsotnei visas saistītās, un tā tālāk Pa līmeņiem ejot

    1 2 3 4 5 6 7 8 9 10

    11

  • ?) Kā uzbūvēt algoritmu kodā, kas realizē šo apstaigāšanu . psiedo kodā: viod BFS(v){

    visited.add(v); q.add(v); // v ieliek rindā q while(!q.isempty()){ v=q get(); // izņem no rindas virsotni ...v...; // izpildām vajadzīgās darbības ar v;

    for(w; visi v, kaiminji){ //w-mainās pa visiem virsotnes v kaimiņiem if(!visited.ask(w)) //ja w nav vēl apstaigāts, tad w ieliekam rindā q.add(w); //un var uzskatīt, ka w ir apstaigāts visited.add(w); }}}

    Koki

    Par koku sauc tādu orientētu grafu, kam eksistē tieši viena virsotne, no kuras eksistē tieši viens ceļš uz jebkuru citu virsotni grafam. Koka sakne ir tā virsotne, no kuras sākas koks.

    Jānis Šablovskis DatZ 040076 2

    1 2 3 4 5 6 7 8 9 10

    11

    1 2 3 4 5 6 7 8 9 10

    11Nav koks, jo uz virsotni 9, var Ir koks aiziet pa vairākiem ceļiem. Def1: Virsotne v1 ir vecāks virsotnei v2, ja grafā (kokā) eksistē šķautne no virsotnes v1 uz v2. Def2: Ja izpildās pirmā definīcija ,tādā gadījumā v2 būs v1 bērns. Visus vienas virsotnes bērnus sauc par kaimiņiem. Virsotni, kurai nav bērnu sauc par lapu. Virsotni, kas nav lapa, sauc par iekšējo virsotni. Virsotnes līmenis ir vesels pozitīvs skaitlis, ko piekārto virsotnei.(katrai virsotnei var noteikt

    līmeni) Sakne ir 0. līmeņa virsotne, visi saknes bērni ir 1. līmeņa virsotnes, visi 1. līmeņa bērni ir 2.

    līmeņa virsotnes utt. Līmenis ir attālums no vienas saknes līdz dotajai virsotnei. Dziļums ir vesels nenegatīvs skaitlis, kuru piekārto kokam (lai varētu izrēķināt koka dziļumu).

    Garākais ceļš no saknes līdz virsotnei (vislielākais līmenis) ir dziļums.

  • Koka pieraksta veidi (4) : 1

    Jānis Šablovskis DatZ 040076 3

    (1(2(5(6)))3)(4(7))

    1 2 4 5 3 7 6

    1 2 5 6 3 4 7

    1 2 3

    4 1

    4 7 3

    2 5 6

  • Jānis Šablovskis DatZ 040076 1

    10. lekcija (praktiskie darbi) [1] uzdevums. Dota simbolu virkne postfiksā, izrēķināt izteiksmes vērtību. (piemēram, dota izteiksme, kas sastāv no četrām operācijām, izteiksmes beigās ir punkts). [1] atrisinājums. #include "stack.h" using namespace std; main(){ string s; stack stk; int a,b; cin.getline(s); for(int i=0; i

  • Jānis Šablovskis DatZ 040076 2

    [3] uzdevums Aprakstīt funkciju kaimiņu matricai. [3] atrisinājums int kaim(int v, int w=-1){ int k=w+1; for(int i=k; i

  • 11. lekcija Koku sauc par n-āru koku, ja koka vienai virsotnei var būt ne vairāk kā n bērni un bērniem tiek ieviests sakārtojums (1. bērns; 2. bērns; 3.bērns utt.) Piem. Kā n-āri koki šie ir dažādi, jo vienam bērns ir pa labi,

    otram – pa kreisi. 1

    2

    1

    2 Realizācija Koka virsotnei ir jāpiekārto kaut kādas vērtības. Struktūra saucās – nelineārais saraksts (saliktais datu tips). datu elements 1

    Jānis Šablovskis DatZ 040076 1

    masīvs ar norādēm (norādes uz visiem bērniem)

    2

    1

    2 N-āru koku, kam n=2, sauc par bināru koku. N-āru koku, kam n=3, sauc par ternāruS koku. Speciāls gadījums bināram kokam – pabeigts binārs koks. (katrai virsotnei ne vairāk kā divi bērni). Koku sauc par pabeigtu bināru koku, ja visas virsotnes veido trijstūri. Šis nav pabeigts binārs koks, jo ir virsotnes, kas neveido trjstūri. Pabeigts binārs koks, jo virsotnes viedo trijstūri

    Ja paliek pāri kāda virsotnes, tad tās ir jāpieliek pēc iespējas tuvāk pie kreisās puses.

  • Pabeigta binārā koka īpašības:

    1) Lapas var būt tikai divos līmeņos. 2) Ja pabeigtam bināram kokam grib pievienot virsotni tā, lai šis koks paliktu pabeigts

    binārais koks, tad ir tikai viena tāda (specifiska) vieta, kur var pievienot šo virsotni. 3) Binārā pabeigtā kokā ir tieši viena virsotne, kuru var izsviest tā, lai šis koks paliktu bināri

    pabeigts.

    ! Tukšs koks ir bināri pabeigts koks. Piemēri:

    Jānis Šablovskis DatZ 040076 2

    1 IR lineāri pabeigts IR IR IR NAV

    1

    Lai uztaisītu pabeigti koku var salikt tukšas virsotnes, kamēr izveidojas salikts binārs koks. Patvaļīgai virsotnei, kur likt bērnu, var atrast pēc formulas, ja ir nosacīti virsotne ir x, tad bērns pa kreisi būs 2x, bet pa labi 2x+1; piem.: Veselā daļa x [x/2] – tā tiek atrasti vecāki, ja sanāk 0, tad nozīmē, ka saknei vecāki neeksistē. Bināro koku apstaigāšana. Aritmētiskās izteiksmes kokos:

    (A+B)*(C–D)+E*F A+B+C+D

    2

    1

    2 3

    6

    1

    2 3

    4

    1

    2 3

    4 5

    x

    2x 2x+1

    A

    +

    * *

    + –

    B C D

    E F

    A

    +

    + D

    + C

    B

  • ! Attēlojot aritmētisku izteiksmi kokā, zūd zīmju prioritātes jēdziens. Ja postfiksā redz mainīgo, tad izveido datu struktūras elementu. Piem: AB+CD--*EF*+ (ejam cauri vienādojumam) left); coutright); } } Postorder binārā koka apstaigāšana: Sakne tiek aplūkota pēdējā 2 – 3 – 1

    1

    2 3 void postorder(elem*p){ if(!=NULL){ postorder(p->left); postorder(p->right); cout

  • Preorder binārā koka apstaigāšana: Sakne tiek aplūkota pirmā 1 – 2 – 3

    1

    Jānis Šablovskis DatZ 040076 4

    void preorder(elem*p){ if(!=NULL){ coutleft); preorder(p->right); } } Algoritms (nerekursīvs), kas izmanto steku: stack s; // šajā stekā glabājas norādes void inorder1(elem*p){ do{ while(p!=NULL){ s.add(p); p=p->left; } if(s.empty()) return; p=s.get(); coutright; }while(1) // mūžīgs cikls

    2 3

  • Jānis Šablovskis DatZ 040076 1

    12. lekcija (praktiskie darbi) [1] uzdevums. Binārs koks, realizēts ar lineāra saraksta palīdzību. Uzrakstīt funkciju, kas kā parametru saņem norādi uz koka sakni, atgriež datu vērtību minimālajam elementam. [1] atrisinājums. Atrod mazāko elementu visam kokam, atrod mazāko kreisajā apakškokā un mazāko labajā apakškokā. Tad salīdzina mazāko labajā, mazāko kreisajā un saknes data elementu. int min(elem * p){ if(p!=NULL){ int x=p->data; int y=min(p->left); int z=min(p->right); if (x>=y && yx && xleft,c); int b=cik(p->right,c); if (p->vert==c); // varēja arī rakstīt: return a+b+1; // return((p->vert)==c)+a+b else // jo, ja true, tad 1, ja false, tad 1 return a+b; }else return 0; }

  • [3] uzdevums. Binārs koks, kuram par parametru tiek padots vesels skaitlis n. Izveidot funkciju, kas izveido atmiņā koku, kas izstās šādi: n

    n-1________________n-1 n-2____n-2______n-2____n-2 ......................................................... 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

    [3] atrisinājums. elem * koks (int num){ elem *e=NULL; if(num!=1) { elem*p=koks(num-1); //izveido labo apakškoku elem*q=koks(num-1); // izveido kreiso apakškoku e=koks new(elem); e->data=num; e->left=p; e->right q; } return e; } [4] uzdevums. Izvedot koku, kur koka sākumā ir 1, bet apakšā daudzi n, tiek padots parametrs n (katrai virsotnei data elements sakrīt ar līmeni). 1

    2 ________________2 3 _______3____ 3____ 3 ......................................................... n n n n n n n n n n n n n n n n n n n

    [4] atrisinājums. elem * koks (int num, int x=1){ elem * l=NULL; if (num>=x) { elem*p=koks(num,x+1); elem*f=koks(num,x+1); l=new (elem); l->data=x; l->left=p; l->right=f; } return l; }

    Jānis Šablovskis DatZ 040076 2

  • 12. lekcija

    Pavedienu koks

    Jānis Šablovskis DatZ 040076 1

    1 2 3 4 6 5

    8 7

    1__1

    1 0

    1__1

    0_0 0_0

    0_0 0_0

    1__1

    Katrā binārajā kokā parādās daudz tukšu norāžu! (4 tukšas norādes) • Ja kādai virsotnei trūkst kreisais bērns, tad realizācijā tukšo norādi aizpilda ar norādi uz to

    elementu, kurš inorder secībā tika apstaigāts iepriekšējais. • Ja kādai virsotnei trūkst labais bērns, tad realizācijā tukšo norādi aizpilda ar norādi uz to

    elementu, kurš inorder secībā tiks apstaigāts nākamais. ements, kas norāda uz loģisko sakni Tukšs el Pavediens - tehniski ieliktās norādes, kas norāda uz citiem elementiem, lai atvieglotu koka

    apstaigāšanu. Katrai virsotnei piekārto divus bitus ( 0 vai 1), lai būtu iespējams pavedienu atšķirt no šķautnes. Ja ir īsta šķautne tad 1, ja pavediens, tad 0. Šādam kokam ir vienkāršs apstaigāšanas algoritms: elem * insuc(elem * x){ //f-jai padod norādi uz 1. elementu kokā elem * s =x->right; // tā atgriež nākamo elementu inorder if(x->r_bit); while (s->l_bit); s=s->l_bit; return s; } inorder algoritms: void inorder(elem * t){ elem * head=t; do{ t=insuc(t); if(t==head); return; cout

  • Funkcija, kas divām norādēm „saāķē” pointerus: void insert_right (elem * s, elem * t){ t->right=s->right; t->r_bit=0; t->left=s; t->l_bit=0; s->right=t; // likvidē pavedienu uz 2 un pieāķē pie 7 s->r_bit=1; }

    Binārais meklēšanas koks

    Visām virsotnēm kokā visi kreisā apakškoka datu vērtības ir mazākas par dotā datu vērtību un visu labā apakškoku datu vērtības ir lielākas par dotā elementa datu vērtībām.

    8

    6 13

    2 1

    Sākumā tukšs koks, liekam iekšā jaunu elementu – 8 Liek klāt jaunu elementu – 13, tā kā 13>8 to liekam pa labi. Jauns elements 10, tā kā 10>8, tas iet pa labi no 8, bet tā kā 10

  • 14. lekcija

    AVL koks

    Binārais meklēšanas koks nav labāks par lineāro sarakstu, tam dēļ tika ieviests AVL koks. Par bināra koka balanci sauc starpību – kreisā apakškoka dziļums mīnus labā apakškoka dziļums.

    -1 , jo (1-2)

    0 , jo (3-3)

    -2 , jo (0-2)

    1 , jo (1-0)

    0

    0 -1 , jo (0-1)

    balance

    Par AVL koku sauc tādu bināro meklēšanas koku, kuram visām virsotnēm balance pēc moduļa nepārsniedz 1, ja virsotne pārsniedz 1, to sauc par „sliktu virsotni”. AVL kokam ir tādas pašas operācijas kā binārajam meklēšanas kokam, tikai sarežģītāka ir elementu ievietošana AVL kokā. Algoritms virsotnes ievietošanai AVL kokā: Ievietojot virsotni, balance var mainīties tikai ceļā no virsotnes līdz jaunajai lapai. 7

    Jānis Šablovskis DatZ 040076 1

    4 9

    1 4 8 12 3 5 10

    0

    -1

    0 1

    -1

    0

    0 -1

    0

    7

    Šajā kokā ievietosim virsotni 3. Vienīgā vieta, kur virsotni 3 var ielikt ir kā virsotnes 4 kreiso bērnu, jo 3 ir mazāks par 7, lielāks par 2 un mazāks par 4, tātad virsotne pa kreisi no 4 (pēc binārā meklēšanas koka definīcijas). Tā kā jaunais elements tika ielikts pa kreisi, tad balance samazinās par 1. Ja balance ir 0, tad augstāk balance nemainīsies. Ja balance samazinās – kļuva par 0, tad uz augšu, vecākiem balance nemainīsies. Ja balance bija 0, bet kļuva lielāka, tad vecāiem arī mainīsies balance.

    AVL koks ar izmainītām balancēm, kad tika pievienota vērtība 3 :

    3 9 0

    1 4 8 12 3 5 10

    -1 -1

    0 1

    0 0

    0 0

    0

  • 7 2 9

    Jānis Šablovskis DatZ 040076 2

    1 4 8 12 3 5 10 3,5

    0

    -2

    0

    Pievienosim vērtību 3,5

    1

    -1

    -1 0

    0 1

    0

    0

    2

    1

    -2

    -1 1

    -2

    7 5 9

    1 4 8 12 3 5 10 3,5

    0

    -2

    0 1

    -1

    -1 0

    0 1

    0

    0

    7 3 9

    2 4 8 12 1 3,5 4 10

    Ja atrod „slikto virsotni”, tad izmanto pārveidojumu, ko sauc par – AVL rotāciju, t.i. pārgrupē elementus tā, lai nezustu binārā koka jēdziens, bet pārveidojumu rezultātā balance nemainās.

    Ir 4 veidu rotācijas (⇔ izpildās abpusēji):

    ⇔ ⇔ Jaunā virsotne vai Tātad:

    Kaudze

    Par kaudzi sauc koku, kas risina citu uzdevumu – ātri atrod minimālu vai maksimālo elementu. Var izņemt un ievietot data elementus (izņemts tiks vienmēr mazākais elements). Def. Par kaudzi sauc pabeigtu bināru koku, kuram katra virsotne ir mazākais elements savā apakškokā.

    Rodas „slikta” virsotne

    A

    B

    T1 T2

    T3

    A

    B T1

    T2 T3

    A

    A T1C

    T4B

    T3T2

    T1

    B

    C

    T4T3T2

  • 5 5 7 12

    9 31 48 42 56 10 6

    Jānis Šablovskis DatZ 040076 3

    6 12

    9 7 48 42

    56 10 31

    31 6 12

    9 7 48 42 56 10

    5 6 12

    9 7 48 42 56 10 31

    5 31 6 12

    9 7 48 42 56 10 31

    6 7 12

    9 31 48 42 56 10

    Jauno elementu salīdzina ar vecāku, ja vecāks ir lielāks, tad samaina vietām. Mazākā elementa izņemšana no kaudzes (saknes izņe es). mšana no kaudz

    liekam iekšā

    vērtību 6

    Dots koks. Mums ir jāizņem 5, tā ir koka sakne. Fiziski izņemam 5, un aizstājam ar to elementu, kuru mēs varam izsviest. Iegūstam šādu koku. Atrodam no saknes,labā,kreisā elementa minimālo un to minimālo aizstājam ar sakni. (31;6;12 min ir 6, tātad to rakstām saknes vietā), un tā tik ilgi, kamēr baigās paliek viens elements no kā izvēlēties. Tālāk meklējam minimālo vērtību un aizstājam tikai uz to pusi, uz kuru bija izmaiņas. Beigās koks izskatīsies šādi.

    lekcijas.pdf1.lekcija[31.01.05].doc2.lekcija(prakt.darbi)[07.02.05.].doc3.lekcija[14.02.05].docMasīvi Datu struktūras operācijas: Vienvirziensaraksts

    4.lekcija(prakt.darbi)[21.02.05].doc5.lekcija[28.02.05].docLineārais divvirzienu saraksts

    6.lekcija(prakt.darbi)[07.03.05].docKonstruktors Destruktors Uzd

    7.lekcija[14.03.05].docRindas realizācija

    8.lekcija(prakt. darbi)[04.04.05].docNelineārā datu struktūra

    9.lekcija[18.04.05].docKoki

    10.lekcija(prakt.darbi)[25.04.05].doc11.lekcija[02.05.05].doc12.lekcija(prakt.darbi)[09.05.05].doc13.lekcija[16.05.05].doc

    14.lekcija[30.05.05].doc