1 / 22

Zadaci

Zadaci. U memoriji oblikovati linearnu listu (pomoću pokazivača) . U pojedini čvor liste upisati : - matični broj studenta (int) - ime i prezime (30+1 znakova) - ocjena (int) - pokazivač na sljedeći čvor

caitir
Download Presentation

Zadaci

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Zadaci • U memoriji oblikovati linearnu listu (pomoću pokazivača). U pojedini čvor liste upisati: - matični broj studenta (int) - ime i prezime (30+1 znakova) - ocjena (int) - pokazivač na sljedeći čvor Napisati funkciju koja će iz liste ispisati sve zapise koji sadrže određenu ocjenu (samo 2, 3, 4 ili 5). Rješava: Janko Ulaga • Strukturu red realizirati kao memorijski rezidentnu listu (upotreba pokazivača). Jedan element sadrži šifru (cijeli broj) i naziv (15+1 znakova). Treba napisati funkciju koja dodaje i funkciju koja briše element iz reda, te funkciju za ispis elementa na kojem se obavlja operacija. Ako je operacija uspjela, funkcija vraća vrijednost 1, a ako nije, vraća 0. Napomena: Novi element dodaje sena kraj liste i pamti se pokazivač na zadnji element, a elementi se skidaju iz redaod glaveliste. Preuzeo, ali odustao: Nikola Cvitaš, preuzela Sandra Krivačić

  2. Napisati funkciju za punjenje memorijski rezidentnog binarnog stabla u čije čvorove treba upisati: cijena artikla (realni broj) i naziv artikla (15+1 znakova). Stablo treba sortirati po cijeni artikala; lijevi jeftiniji, desni skuplji. Napisati funkciju za ispis elementa za koju je ulazni argument korijen stabla. Ispis treba biti poredan po cijeni od najjeftinijeg do najskupljeg artikla. Napisati funkciju koja ispiše sve proizvode čija je cijena manja od neke određene vrijednosti koja se unese u glavnoj funkciji programa tijekom izvršavanja programa. Zadatak preuzeo Danijel Markić • U memoriji napraviti binarno stablo traženja u čije čvorove se upisuju 2 podatka: prvi tipa int i drugi tipa float. Stablo se sortira prema cjelobrojnom podatku (lijevo manji, desno veći). Ispisati BST po algoritmu INORDER. Napisati funkcije MIN() i MAX() koje u najmanjem mogućem broju koraka (u najkraćem mogućem vremenu izvršavanja) moraju naći i ispisati zapise koji odgovaraju najmanjoj i najvećoj cjelobrojnoj vrijednosti (nije dopušteno pročitati zapise u svim čvorovima). U programu zatim izbrisati čvorove koji odgovaraju tim zapisima te ispisati tako nastalo BST u INORDER algoritmu. Napisati funkciju koja izračuna i ispiše prosječnu vrijednost varijable tipa float u BST. Zadatak preuzeo Andrej Vidak

  3. Primjer baratanja s podatcima u binarnom stablu traženja • Napisati funkciju koja upisuje u čvor BST podatke tipa: naziv proizvoda (char 15) i cijena (float). Uređaj između zapisa u čvorovima određuje naziv proizvoda (manje znači bliže početku abecede). Napisati funkciju koja ispiše zapise u BST po algoritmu INORDER, te funkciju koja izračuna prosječnu cijenu proizvoda u cjeniku.

  4. #include <stdio.h> #include <stdlib.h> #include <malloc.h> #include <string.h> typedef struct { char artikl[15+1]; float cijena; } el; typedef struct cv { el element; struct cv *lijevo; struct cv *desno; } cvor; typedef struct { float suma; int broj; } pros;

  5. // upisuje u stablo podatke: lijevo manji, desno veci cvor *upis (cvor *glava, el element) { int smjer; if (glava == NULL) { glava = (cvor *) malloc (sizeof (cvor)); if (glava) { glava->element = element; glava->lijevo = glava->desno = NULL; } else { printf ("Nema dovoljno memorije!\n"); } } else if ((smjer = strcmp (element.artikl, glava->element.artikl)) < 0) { glava->lijevo = upis (glava->lijevo, element); } else if (smjer > 0) { glava->desno = upis (glava->desno, element); } else { printf ("Podatak '%s' vec postoji!\n", element.artikl); } return glava; }

  6. // ispis inorder void ispisin (cvor *glava) { if (glava != NULL) { ispisin (glava->lijevo); printf ("%-15s %6.2f\n", glava->element.artikl, glava->element.cijena); ispisin (glava->desno); } } // sumiranje cijena i brojanje elemenata void prosjek (cvor *glava, pros *prs) { if (glava != NULL) { prs->suma += glava->element.cijena; prs->broj++; prosjek (glava->lijevo, prs); prosjek (glava->desno, prs); } } void main(void) { FILE *fi; int j; cvor *glava; // pokazivac na korijen el element; // sadrzaj cvora pros prs; // broj elemenata i suma cijena

  7. prs.suma = 0.; prs.broj = 0; fi = fopen ("UlazZaProsjekUStablu.txt", "r"); if (!fi) { printf ("Nema ulaznih podataka\n"); exit (1); } j = 1; glava = NULL; while (fscanf (fi, "%s %f", element.artikl, &element.cijena) != EOF) { printf ("%2d. ulazni podatak je %-15s %6.2f\n", j++, element.artikl, element.cijena); glava = upis (glava, element); } fclose (fi); // ispis, racun sume cijena i broja elemenata getchar (); ispisin (glava); getchar (); prosjek (glava, &prs); if (prs.broj) { printf ("Suma=%6.2f, Broj cvorova=%d, Prosjek=%6.2f\n", prs.suma, prs.broj, prs.suma / prs.broj); getchar (); } exit (0); }

  8. Nešto složeniji primjer binarnog stabla traženja Zadatak: Zadani su podaci o studentu: matični broj long, ime 25 znakova, prezime 25 znakova i godina rođenja short. Uz uporabu dinamičke strukture binarnog stabla (sortirano stablo, tj. binarno stablo traženja) potrebno je napisati funkcije za: a) pohranu podataka o studentima uz uvjet da je omogućeno brže pronalaženje studenata po prezimenu b) pronalaženje studenta po prezimenu c) ispis čvorova po INORDER algoritmu d) ispis čvorova na zadanoj razini e) izračunavanje dubine stabla i najmanje razine listova f) ispis listova stabla

  9. #include <stdio.h> #include <stdlib.h> #include <string.h> struct podaci { long matBroj; char ime[25]; char prezime[25]; short godRod; }; typedef struct podaci Podaci; struct cvor { Podaci * student; struct cvor * lijevo; struct cvor * desno; }; typedef struct cvor Cvor;

  10. // funkcija dodaje u binarno sortirano stablo, kljuc je prezime Cvor * dodajPrezime (Cvor * korijen, Podaci * student) { int smjer; if (korijen == NULL) { korijen = (Cvor *) malloc (sizeof(Cvor)); if (korijen) { korijen->student = student; korijen->lijevo = korijen->desno = NULL; } } else if ((smjer = strcmp(student->prezime, korijen->student->prezime)) < 0) korijen->lijevo = dodajPrezime (korijen->lijevo, student); else if (smjer > 0) korijen->desno = dodajPrezime (korijen->desno, student); else printf("Podatak %s vec postoji!\n", student->prezime); return korijen;} // funkcija pretrazuje binarno stablo trazenja po kljucu prezime Cvor * potraziPrezime (Cvor * korijen, char * prezime) { int smjer; if (korijen) { if ((smjer = strcmp(prezime, korijen->student->prezime)) < 0) return potraziPrezime (korijen->lijevo, prezime); else if (smjer > 0) return potraziPrezime (korijen->desno, prezime); } return korijen;}

  11. // funkcija inorder ispisuje zadano binarno stablo void inOrder (Cvor * korijen) { if (korijen) { inOrder (korijen->lijevo); printf("%s, %s %d %d\n", korijen->student->prezime, korijen->student->ime, korijen->student->matBroj,korijen->student->godRod); inOrder (korijen->desno); } } // funkcija ispisuje sve cvorove zadane dubine // poziv ispis(korijen, 1, n) gdje je n trazena dubina void ispisi (Cvor * korijen, int trenutnaDubina, int trazenaDubina) { if (korijen) { if (trenutnaDubina == trazenaDubina) printf("%d %s %s %d\n",korijen->student->matBroj, korijen->student->ime, korijen->student->prezime,korijen->student->godRod); ispisi (korijen->lijevo, trenutnaDubina + 1, trazenaDubina); ispisi (korijen->desno, trenutnaDubina + 1, trazenaDubina); } }

  12. // funkcija trazi listove s najvecom i najmanjom razinom void dubine(Cvor * korijen, int trenDub, int * maxDub, int * minDub) { if (korijen) { if (!korijen->lijevo & !korijen->desno) { if (*maxDub == 0 || trenDub > *maxDub) *maxDub = trenDub; if (*minDub == 0 || trenDub < *minDub) *minDub = trenDub; } else { dubine(korijen->lijevo, trenDub + 1, maxDub, minDub); dubine(korijen->desno, trenDub + 1, maxDub, minDub); } } } // funkcija za zadano binarno stablo ispisuje listove void ispisiListove(Cvor * korijen) { if (korijen) { if (!korijen->lijevo & !korijen->desno) printf("%s %s %d %d; ", korijen->student->ime, korijen->student->prezime, korijen->student->matBroj,korijen->student->godRod); ispisiListove(korijen->lijevo); ispisiListove(korijen->desno); } }

  13. void main () { FILE * fUl; char buf[256], trazim[25]; Podaci * student; Cvor * korijenPrezime = NULL; Cvor * trazeni; int minDubina = 0, maxDubina = 0; int i; if ((fUl = fopen("studenti.txt", "r")) == NULL) { printf("Ne mogu otvoriti 'studenti.txt'\n"); exit(1); } while (fgets(buf, 256, fUl)) { student = (Podaci *) malloc(sizeof(Podaci)); sscanf(buf, "%ld;%[^;];%[^;];%d", &(student->matBroj), student->ime, student->prezime, &(student->godRod)); korijenPrezime = dodajPrezime(korijenPrezime, student); } fclose(fUl); inOrder(korijenPrezime); printf("\n");

  14. while (1){ printf("Upisite prezime koje se trazi, kraj za prekid trazenja\n"); scanf("%s",trazim); if (strcmp(trazim,"kraj")==0) break; if(trazeni = potraziPrezime(korijenPrezime, trazim)) printf("Pronasao: %s, %s %ld %d\n", trazeni->student->prezime, trazeni->student->ime, trazeni->student->matBroj, trazeni->student->godRod); else printf("Nije nadjen student %s\n",trazim); } printf("\nIspis listova:\n"); ispisiListove(korijenPrezime); dubine(korijenPrezime, 1, &maxDubina, &minDubina); printf("\nMaxDubina=%d MinDubina=%d\n", maxDubina, minDubina); for (i=1; i<=maxDubina; i++) { printf("%d razina:\n", i); ispisi(korijenPrezime, 1, i); } }

  15. Sortiranje pomoću hrpe (heapsort) • Na prijašnjim vježbama već smo radili dva algoritma sortiranja (sortiranje umetanjem - Insertion sort i mjehuričasto sortiranje - Bubble sort) koji su ulazni niz od n elemenata sortirali u vremenu proporcionalnom s n2. • Sad ćemo obraditi još jedan algoritam sortiranja – sortiranje pomoću hrpe - Heapsort – koji je efikasniji od Insertion sorta i Bubble sorta. Ovaj algoritam polje od n elemenata sortira u vremenu O(n*log n). • Prije nego izložimo algoritam za ovo sortiranje, ponoviti ćemo najosnovnije o stablastoj strukturi podataka zvanoj hrpa. • Potpuno binarno stablo T je hrpa (heap) ako su ispunjeni uvjeti: - čvorovi od T su označeni podacima nekog tipa za koje je definiran totalni uređaj - neka je i bilo koji čvor od T. Tada je oznaka od i manja ili jednaka od oznake bilo kojeg djeteta od i – minimalna hrpa • ali pazi sad, može biti isto tako: - neka je i bilo koji čvor od T. Tada je oznaka od i veća ili jednaka od oznake bilo kojeg djeteta od i –maksimalna hrpa Općenito: uređaj među podacima može biti i neki drugi, pa se može promijeniti i relacija roditelj - djeca

  16. uzimamo da je oznaka roditelja veća ili jednaka od oznaka svih potomaka • Hrpa je struktura podataka koja se obično implementira pomoću polja • elementi hrpe spremljeni su u polje koje promatramo kao potpuno binarno stablo (jer je svaki nivo stabla, osim posljednjega, do kraja ispunjen, a čvorovi na posljednjem nivou su "gurnuti" u lijevu stranu) • Lako je vidjeti da se lijevo dijete čvora i nalazi na poziciji 2*i+1, a desno na poziciji 2*i+2. Roditelj čvora i nalazi se na poziciji (i-1)/2 • Za svaki čvor u stablu, definiramo njegovu visinu kao broj grana na najdužem putu od tog čvora do nekog lista. Visinu stabla definiramo kao visinu njegovog korijena • Budući da je n-elementna hrpa posebni slučaj potpunog binarnog stabla, njezina visina je jednaka log2 n. Osnovna operacija za rad s hrpom (Heapify) svoj posao obavlja u vremenu koje je, u najgorem slučaju, proporcionalno visini stabla i stoga se izvršava u vremenu proporcionalnom log2 n • Operacije za rad s hrpom su sljedeće: • Funkcija Heapify koja je ključna za očuvanje uređenosti hrpe (log2 n) • Funkcija BuildHeap koja od neuređenog ulaznog polja stvara hrpu (n*log2 n) • Funkcija HeapSort koja sortira polje (n*log2 n)

  17. Implementacija strukture podataka HeapType u C-u • definiramo novi tip podataka, HeapType, kao strukturu koja sadrži: struct heaptype { int * Elements; //pokazivač na polje elemenata hrpe int Size; //veličina hrpe }; typedef struct heaptype HeapType; • Funkcija MakeEmptyHeap stvara praznu hrpu zadane veličine, dok funkcija FreeHeap oslobodi memoriju koju je neka hrpa zauzimala: HeapType MakeEmptyHeap(int size) { HeapType heap; heap.Elements = malloc(size * sizeof(int)); heap.Size = size; return heap; } void FreeHeap(HeapType * hptr) { free(hptr->Elements); }

  18. Operacija Heapify • Heapify je operacija koja kao ulazni parametar prima pokazivač na strukturu HeapType i index i nekog elementa u polju Elements. U času pozivanja funkcije Heapify pretpostavlja se da i lijevo i desno podstablo čvora i zadovoljavaju svojstvo uređenosti hrpe, ali da je element s indeksom i (eventualno) manji od svoje djece i time (eventualno) narušava uređenost hrpe • Funkcija Heapify "pomiče" element upisan u čvor i prema dolje tako da na kraju podstablo hrpe kojemu je korijen čvor i postane ispravna podhrpa (tj. podhrpa koja zadovoljava svojstvo uređenosti hrpe) • Left i Right su jednostavne pomoćne funkcije koje vraćaju indeks lijevog odnosno desnog djeteta čvora i: int Left(int i) { int Right(int i) { return 2*i + 1; return 2*i+2; } }

  19. void Heapify(HeapType * hptr, int i) { int largest; int lft; int rht; int next = 1; do { lft = Left(i); rht = Right(i); if(lft < hptr->Size && hptr->Elements[lft] > hptr->Elements[i]) largest = lft; else largest = i; if(rht < hptr->Size && hptr->Elements[rht] > hptr->Elements[largest]) largest = rht; if(largest != i) { int temp = hptr->Elements[i]; hptr->Elements[i] = hptr->Elements[largest]; hptr->Elements[largest] = temp; i = largest; } else next = 0; } while(next); }

  20. Operacija BuldHeap • Sukcesivnom upotrebom operacije Heapify možemo od "neispravne" hrpe načiniti ispravnu (koja zadovoljava uređenost hrpe). Funkcija izgleda ovako: void BuildHeap(HeapType * heapptr) { for (int i = ParentOfLastElement(heapptr); i >= 0; i--) Heapify(heapptr, i); } • BuildHeap koristi pomoćnu funkciju ParentOfLastElement koja vraća indeks roditelja posljednjeg elementa u hrpi. Ta funkcija izgleda ovako: int ParentOfLastElement(HeapType * h) { return Parent(h->Size - 1); } int Parent(int k) { return (k - 1) / 2; }

  21. Algoritam HeapSort • Algoritam Heapsort najprije pomoću funkcije BuildHeap od ulaznog polja stvori ispravnu hrpu. Nakon toga, stvorenu hrpu pretvara u uzlazno sortirano polje. Funkcija izgleda ovako: void HeapSort(int a[], int n) { HeapType heap; heap.Elements = a; heap.Size = n; BuildHeap(&heap); for(int i = n - 1; i > 0; i--) { int temp = heap.Elements[i]; heap.Elements[i] = heap.Elements[0]; heap.Elements[0] = temp; heap.Size--; Heapify(&heap, 0); } }

  22. Vidimo da algoritam najprije poziva BuildHeap (što traje proporcionalno s n*log2 n) a zatim u osnovi "vrti petlju" u kojoj se n-1 puta obavljaju neke jednostavne operacije i poziva funkcija Heapify koja traje proporcionalno s log2 n . Sveukupno, stoga, funkcija HeapSort se izvršava u vremenu proporcionalnim s n*log2 n, što je bitno bolje od sortiranja umetanjem (Insertion sort) ili mjehuričastog sortiranja (Buble sort) čije je vrijeme izvršavanja dano s n2 . • Kompletan kod za sortiranje pomoću hrpe: primjer • Napisati program koji od ulaznog polja cijelih brojeva izgradi hrpu, te ispiše polje u kojem su spremljeni elementi hrpe. Također napraviti sortiranje polja cijelih brojeva upotrebom sortiranja pomoću hrpe.

More Related