760 likes | 1.08k Views
PODATKOVNI TIPI V JEZIKU C++. Osnovni podatkovni tipi. Sestavljeni podatkovni tipi. Celoštevilčni: int (zasede 4 zloge) short (2 zloga) long (4 zloge). Izpeljani: kazalci (4 zloge) reference. Homogeni: - polja. Znakovni: - char (1 zlog). Nehomogeni: strukture unije. Realni:
E N D
PODATKOVNI TIPI V JEZIKU C++ Osnovni podatkovni tipi Sestavljeni podatkovni tipi • Celoštevilčni: • int (zasede 4 zloge) • short (2 zloga) • long (4 zloge) • Izpeljani: • kazalci (4 zloge) • reference Homogeni: - polja Znakovni: - char (1 zlog) • Nehomogeni: • strukture • unije • Realni: • float (4 zloge) • double (8 zlogov) • long double (8 zlogov) Naštevni: - enum (4 zloge) Logični: - bool (1 zlog)
POLJA POMNILNIK Fizični naslovi Logični naslovi Polje je zaporedje vrednosti istega tipa, ki jim damo eno ime. Posamezne vrednosti oziroma elemente polja dosegamo z indeksom. Definiramo lahko polja poljubnih tipov (polje celih števil, polje realnih števil, polje znakov, polje struktur, polje polj, itd.). Polje je sestavljeni podatkovni tip, sestavljen iz elementov istega tipa. Deklaracija polja in dostop do elementov Pri deklaraciji polja se za shranjevanje elementov polja v pomnilniku rezervira ustrezno število sosednjih pomnilniških celic. Zato moramo določiti velikost polja, to je število, ki pove, koliko elementov polje vsebuje. Npr. z deklaracijo int test[4] določimo polje test s štirimi elementi tipa int. Pri tem imajo elementi polja nedoločene vrednosti. Do elementov polja dostopamo tako, da za imenom polja zapišemo indeks v oglatem oklepaju. Vrednost izraza, ki predstavlja indeks, mora biti celoštevilčnega tipa. Indeks polja mora biti v območju [0, velikost polja-1], v našem primeru v območju [0, 3]. test[0] = 238; Vsebina test[3] test[2] test[1] test = 0x0012fe84 238 test[0] Zaslon
POLJA POMNILNIK Fizični naslovi Logični naslovi int _tmain(int argc, _TCHAR* argv[]) { int test[4]; test[0] = 10; test[1] = 5; test[2] = 3; test[3] = 200; int vsota; vsota = test[0] + test[1] + test[2] + test[3]; printf("Vsota elementov polja je: %d\n“, vsota); return 0; } Pri deklaraciji polja določimo podatkovni tip elementov polja, ime polja ter število elementov polja. Ime polja je konstantni kazalec, ki vsebuje fizični naslov prve lokacije prvega elementa polja. Pri deklaraciji polja prevajalnik dodeli začetni naslov in zadostno količino pomnilnika, kjer bodo shranjeni elementi polja. Začetni naslov polja je začetna lokacija v pomnilniku, kjer je polje shranjeno, in hkrati naslov prvega elementa polja (elementa z indeksom 0). Inicializacija polja Inicializacija polja pomeni, da poleg definicije polja navedemo še vrednosti elementov, s katerimi polje napolnimo. Polje torej lahko inicializiramo tako, da med zavitimi oklepaji naštejemo vrednosti elementov, ki jih ločimo z vejicami. int test[4] = {8, 7, 6, 4}; Vsebina 200 test[3] 3 test[2] 5 test[1] test = 0x0012fe84 10 test[0] 0x0012fe80 218 vsota Zaslon
POLJA POMNILNIK Prenos polja v funkcijo const int vel_polja = 4; int Sestej(int polje[vel_polja]) { int vsota=0; for (int i=0; i<vel_polja; i++) vsota += polje[i]; return vsota; } int _tmain(int argc, _TCHAR* argv[]) { int prvo[vel_polja]; int drugo[vel_polja]; randomize(); for (int i=0; i<vel_polja; i++) { prvo[i] = random(31); drugo[i] = prvo[i] * prvo[i]; } printf("Prvo polje: %d %d %d %d\n", prvo[0], prvo[1], prvo[2], prvo[3]); printf("Drugo polje: %d %d %d %d\n", drugo[0], drugo[1], drugo[2], drugo[3]); printf("Vsota stevil je %d\n", Sestej(prvo)); printf("Vsota kvadratov je %d\n", Sestej(drugo)); return 0; } Fizični naslovi Logični naslovi Vsebina 0x0014a960 4 vel_polja prvo[3] prvo[2] prvo[1] prvo = 0x0012fe84 prvo[0] drugo[3] drugo[2] drugo[1] drugo = 0x0012fe74 drugo[0] Zaslon
POLJA POMNILNIK Prenos polja se vedno izvaja po referenci. Vrednosti, ki jih v funkciji spremenimo v polju, ostanejo spremenjene tudi po zaključku funkcije Če želimo polje prenesti v funkcijo, kot dejanski argument zapišemo ime polja: Sestej(prvo), formalni argument funkcije Sestej() pa zapišemo enako kot definiramo polje: int Sestej(int polje[vel_polja]) Ob klicu funkcije se torej opravi deklaracija reference polja, ki ga navedemo kot dejanski argument pri klicu funkcije. (Npr.: int polje[vel_polja] = prvo; // oz. polje = prvo) V funkciji Sestej() uporabljamo konstantno spremenljivko vel_polja in jo zato definiramo globalno. Vemo, da lahko kazalcem prištevamo cela števila. Če mu prištejemo vrednost 1, se bo kazalec premaknil za toliko zlogov, kolikor je velikost tipa, na katerega kaže. Zapis (polje+i) pravzaprav pomeni (polje+i*sizeof(int)). Programerju torej ni potrebno skrbeti za pravilno premikanje kazalca ne glede na to, katerega podatkovnega tipa so elementi polja. Nad kazalci lahko izvajamo dve aritmetični operaciji. Prištevamo in odštevamo jim lahko cela števila ter jih med seboj odštevamo. Če kazalcu prištejemo ali od njega odštejemo celo število, dobimo novi kazalec, pri odštevanju dveh kazalcev pa dobimo celo število, ki pove razdaljo med kazalcema. int _tmain(int argc, _TCHAR* argv[]) { const int velikost = 5; int polje[velikost] = {1, 10, 100, 1000, 10000}; int *zac_naslov = polje; // oz. &polje[0] int *konc_naslov = &polje[velikost-1]; int st_elementov = konc_naslov - zac_naslov + 1; printf("%d\n", st_elementov); return 0; } Fizični naslovi Logični naslovi Vsebina 0x0014a960 5 velikost polje[4] 10000 100 polje[3] polje[2] 100 polje[1] 10 polje = 0x0012fe74 polje[0] 1 0x0012fe70 0x0012fe74 zac_naslov 0x0012fe6c 0x0012fe84 konc_naslov 0x0012fe68 5 st_elementov Zaslon
PODATKOVNI TIPI V JEZIKU C++ Osnovni podatkovni tipi Sestavljeni podatkovni tipi • Celoštevilčni: • int (zasede 4 zloge) • short (2 zloga) • long (4 zloge) • Izpeljani: • kazalci (4 zloge) • reference Homogeni: - polja Znakovni: - char (1 zlog) • Nehomogeni: • strukture • unije • Realni: • float (4 zloge) • double (8 zlogov) • long double (8 zlogov) Naštevni: - enum (4 zloge) Logični: - bool (1 zlog)
STRUKTURE POMNILNIK Fizični naslovi Logični naslovi Strukturaomogoča združitev podatkov različnega podatkovnega tipa v skupni objekt novega podatkovnega tipa. S strukturami združimo sorodne podatke pod enim imenom in jih nato obravnavamo kot celoto, ki vsebuje posamezne elemente, komponente oz. člene. Podatkom lahko še dodamo metode (funkcije), ki se izvajajo nad temi podatki. Sintaksa: struct ime_strukture { podatkovni_tip element1; podatkovni_tip element2; podatkovni_tip element3; } ime_objekta1, ime_objekta2; Do posamezne komponente strukture dostopamo z izrazom ime_objekta.komponenta. Strukturni operator “.” naredi povezavo med imenom objekta in njegovo komponento. Primer: struct naslov { char mesto[20]; char ulica[20]; int postSt; } moj_naslov; naslov naslov2; moj_naslov.postSt = 2390; naslov2.postSt = 2380; Vsebina moj_naslov.mesto moj_naslov.ulica 0x0012ff40 2390 moj_naslov.postSt naslov2.mesto naslov2.ulica 0x0012fe84 2380 naslov2.postSt Zaslon
STRUKTURE Prenos strukture v funkcijo Primer: enum spol {moski, zenski}; struct datum { int dan; int mesec; int leto; }; struct oseba { char ime_o[20]; spol spol_o; char naslov_o[30]; datum datum_r; }; void IzpisiOsebo(oseba); int _tmain(int argc, _TCHAR* argv[]) { oseba sosed = {"Marko", moski, "Trg svobode 13", {25, 2, 1998}}; IzpisiOsebo(sosed); oseba soseda = {"Klara", zenski, "Trg svobode 13", {6, 2, 1995}}; IzpisiOsebo(soseda); oseba klonSoseda; klonSoseda = soseda; klonSoseda.ime_o[4]='o'; klonSoseda.spol_o=moski; IzpisiOsebo(klonSoseda); return 0; } void IzpisiOsebo(oseba nekdo) { printf("Ime osebe: %s\n", nekdo.ime_o); printf("Spol: %s\n", ((nekdo.spol_o == moski)?"moski":“zenski")); printf("Naslov: %s\n", nekdo.naslov_o); datum datum_r = nekdo.datum_r; printf("Datum rojstva: %d.%d.%d\n", datum_r.dan, datum_r.mesec, datum_r.leto); } POMNILNIK Fizični naslovi Logični naslovi Vsebina
STRUKTURE POMNILNIK Kazalci na strukture Kot pri ostalih podatkovnih tipih lahko tudi pri strukturah uporabimo kazalce. Kazalec definiramo kot kazalec na objekt strukture ter ga inicializiramo s fizičnim pomnilniškim naslovom, kjer se objekt te strukture nahaja v pomnilniku. Primer: #include<iostream.h> #include<stdlib.h> struct str_film { char naslov [70]; int leto; }; int _tmain(int argc, _TCHAR* argv[]) { char vmesnik[70]; str_film film, *kaz_film; kaz_film = &film; printf("Naslov: "); cin.getline(kaz_film->naslov, 70); printf("Leto: "); cin.getline(vmesnik, 70); kaz_film->leto = atoi(vmesnik); printf("\nVnesel si: %s (%d)\n", kaz_film->naslov, kaz_film->leto); return 0; } Operator -> uporabljamo za dostop do posamezne komponente strukture, na katero kaže kazalec. Imenujemo ga dereferenčni operator. Namesto (*kaz_film).naslov lahko napišemo kaz_film->naslov. Fizični naslovi Logični naslovi Vsebina Zaslon
PODATKOVNI TIPI V JEZIKU C++ Osnovni podatkovni tipi Sestavljeni podatkovni tipi • Celoštevilčni: • int (zasede 4 zloge) • short (2 zloga) • long (4 zloge) • Izpeljani: • kazalci (4 zloge) • reference Homogeni: - polja Znakovni: - char (1 zlog) • Nehomogeni: • strukture • unije • Realni: • float (4 zloge) • double (8 zlogov) • long double (8 zlogov) Naštevni: - enum (4 zloge) Logični: - bool (1 zlog)
UNIJE, Bitna polja Unije Unije so podobne strukturam, le da je v njih vedno veljaven le en element. Unija zasede vedno toliko prostora, kot ga zasede njen največji element: #include <iostream.h> struct complex { double re, im; }; union vrednost { int v_int; double v_dbl; complex v_cpx; }; void main() { vrednost v; printf("Velikost celotne unije: %d\n", sizeof(vrednost)); printf("Velikost elementa int: %d\n", sizeof(v.v_int)); printf("Vel. elementa double: %d\n", sizeof(v.v_dbl)); printf("Vel. elementa complex: %d\n", sizeof(v.v_cpx)); printf("Naslovi spremenljivk so:\n"); printf("naslov v: %d\n", &v); printf("naslov v.v_int: %d\n", &v.v_int); printf("naslov v.v_dbl: %d\n", &v.v_dbl); printf("naslov v.v_cpx: %d\n", &v.v_cpx); printf("naslov v.v_cpx.re: %d\n", &v.v_cpx.re); printf("naslov v.v_cpx.im: %d\n\n", &v.v_cpx.im); } VARČEVANJE S SPOMINOM C++ nam omogoča varčevati s spominom na dva načina. Spremenljivke, ki obsegajo malo vrednosti, lahko opišemo s toliko biti, kot je to potrebno in nič več. Večje strukture pa lahko razbijemo glede na to, kaj trenutno lahko vsebujejo. Bitna polja Precej potratno je za spremenljivko, ki lahko zasede samo dve vrednosti, uporabiti tip char, ki lahko zasede 256 vrednosti. Zato lahko več takšnih spremenljivk povežemo v strukturo, ki bo zavzela toliko prostora, kot ga spremenljivke potrebujejo. Bitna polja definiramo preprosto kot strukture, katere elementi so vsi tipa unsigned int, le da vsakemu elementu dodamo še podatek, ki pove število bitov, ki jih bo ta podatek zasedel: struct tiskalnik { unsigned prost : 1; unsigned pise : 1; unsigned papir_vstavljen : 1; unsigned tip_papirja : 1; unsigned font : 3; }
GENERIRANJE NAKLJUČNIH ŠTEVIL POMNILNIK #include <stdlib.h> #include <stdio.h> #include <time.h> #define SPODNJA_M 65 #define ST_ELEM 26 int main(void) { srand((unsigned)time(NULL)); // Prikaz 10 naključnih števil. int i; for(i = 0; i < 10; i++) printf(" %6d\n", rand()); printf("\n"); // Generiranje naključnih števil v razponu od 1 do 6: for (i = 0; i < 10; i++) { int rand100 = (((double)rand() / (double)RAND_MAX) * 6 + 1); printf( " %6d\n", rand100); } printf("\n"); // Generiranje naključnih črk v razponu od A do Z: for (i = 0; i < 10; i++) { int rand100 = (((double)rand() / (double)RAND_MAX) * ST_ELEM + SPODNJA_M); printf( " %6c\n", (char)rand100); } } Naključna števila se generirajo na osnovi trenutnega časa. Zato so generirana števila vedno drugačna. Fizični naslovi Vsebina Logični naslovi Običajno želimo generirati števila znotraj nekega razpona. Zaslon
Delo z datotekami POMNILNIK Kaj je datoteka. Datoteka je osnovna organizacijska enota z računalnikom zapisanih podatkov, pri čemer je podatek vse, kar lahko zapišemo na pomnilniški nosilec. Vsebina vsake datoteke je niz binarnih števil. Njen binarni prikaz je nepregledna množica ničel in enic. Bolj pregleden je njen šestnajstiški zapis, ker je vsak bajt predstavljen le z dvema šestnajstiškima števkama. Seveda bo nam najbolj razumljiv izpis datoteke v obliki ASCII znakov, vendar bo tak izpis smiseln le, če datoteka predstavlja besedilo. Vsaka datoteka ima svoje ime in zaseda določen prostor na disku. Lahko je različnega tipa – lahko vsebuje besedilo, lahko so izvršljive in podobno. Katerega tipa je datoteka, pa nam pove njena končnica, npr. .doc, .exe, .bmp itn. Pri delu z datotekami upoštevamo standardno zaporedje postopkov: 1. Deklariramo datotečni kazalec 2. Odpremo podatkovni tok in ga usmerimo proti datoteki 3. Beremo ali zapisujemo podatke (z zanko while) 4. Datoteko zapremo Fizični naslovi Vsebina Logični naslovi Zaslon
Delo z datotekami POMNILNIK Primer: char beseda[30]; FILE* tok1; tok1 = fopen("c:\\test1.txt", "rt"); while(!feof(tok1)) { fscanf(tok1, "%s", beseda); printf("%s\n", beseda); } fclose(tok1); Datoteko lahko odpremo v različnih načinih. Najpogostejši so: "r" - odpre datoteko za branje; če datoteka ne obstaja, vrne fopen vrednost NULL. "w" - odpre prazno datoteko za pisanje; če datoteka že obstaja, bo njena vsebina zbrisana. "a" - odpre datoteko za dodajanje teksta na konec; če datoteka ne obstaja, jo fopen ustvari. "r+" - odpre datoteko za branje in pisanje; datoteka mora obstajati. "w+" - odpre prazno datoteko za branje in pisanje; če datoteka že obstaja, bo njena vsebina uničena. Fizični naslovi Vsebina Logični naslovi
Delo z datotekami POMNILNIK Nekatere funkcije (metode razreda FILE) za delo z datotekami: fopen(…) – odpre datoteko, fclose(…) – zapre datoteko, feof(…) – ugotavlja konec datoteke, fscanf(…) – formatirano branje iz datoteke, fprintf(…) – formatirano pisanje v datoteko, rewind(…) – vrnitev datotečnega kazalca na začetek, fgetc(…) – branje enega znaka, fputc(…) – pisanje enega znaka, fread(…) – neformatirano branje, fwrite(…) – neformatirano pisanje, fgetpos(…) – vrne pozicijo datotečnega kazalca, fsetpos(…) – nastavi pozicijo datotečnega kazalca, … Fizični naslovi Vsebina Logični naslovi
Delo z datotekami POMNILNIK Še en primer programa: int _tmain(int argc, _TCHAR* argv[]) { int stevila[10] = {123,231,304,512,8,65,66,67,10,13}; FILE* tok1; tok1 = fopen("c:\\Zdravko\\Šola\\test1.bin", "w"); fwrite(stevila, sizeof(int), 10, tok1); fclose(tok1); printf("Konec\n"); return 0; } Fizični naslovi Vsebina Logični naslovi Zaslon
Urejanje podatkov POMNILNIK • Podatke v tabelah lahko uredimo na več možnih načinov: • Urejanje po metodi izbora najmanjšega elementa: • poiščemo najmanjše število v neurejeni tabeli, • postavimo ga na prvo mesto neurejenega dela tabele, hkrati pa število, ki je bilo do tedaj na prvem mestu neurejenega dela tabele, postavimo na mesto, na katerem smo našli najmanjše število v neurejeni tabeli, • neurejeni del tabele se s tem zmanjša za eno število, • to ponavljamo dokler v neurejenem delu tabele ne ostane samo eno število, ki je hkrati največje v urejeni tabeli. • #define DIM 5 • void UrediTabelo(int[], int); • int Najmanjse(int[], int, int); • int _tmain(int argc, _TCHAR* argv[]) • { • int stevila[DIM] = {304,231,123,512, 66}; • UrediTabelo(stevila, DIM); • for(int i = 0; i < DIM; i++) • printf("%d\n", stevila[i]); • return 0; • } Fizični naslovi Vsebina Logični naslovi 5 DIM 66 stevila[4] 512 stevila[3] 123 stevila[2] 231 stevila[1] 304 stevila[0] Zaslon
Urejanje podatkov POMNILNIK void UrediTabelo(int tabela[], int dim) { int indeks, pom; for(int i = 0; i < dim-1; i++) { indeks = Najmanjse(tabela, dim, i); pom = tabela[i]; tabela[i] = tabela[indeks]; tabela[indeks] = pom; } } int Najmanjse(int polje[], int ki, int zi) { int najS = polje[zi]; int ind = zi; for(int j = zi+1; j < ki; j++) { if(polje[j] < najS) { najS = polje[j]; ind = j; } } return ind; } Fizični naslovi Vsebina Logični naslovi 5 DIM, dim 66 stevila[4], tabela[4] 512 stevila[3], tabela[3] 123 stevila[2], tabela[2] 231 stevila[1], tabela[1] 304 stevila[0], tabela[0] indeks pom i Zaslon
Urejanje podatkov POMNILNIK void UrediTabelo(int tabela[], int dim) { int indeks, pom; for(int i = 0; i < dim-1; i++) { indeks = Najmanjse(tabela, dim, i); pom = tabela[i]; tabela[i] = tabela[indeks]; tabela[indeks] = pom; } } int Najmanjse(int polje[], int ki, int zi) { int najS = polje[zi]; int ind = zi; for(int j = zi+1; j < ki; j++) { if(polje[j] < najS) { najS = polje[j]; ind = j; } } return ind; } Fizični naslovi Vsebina Logični naslovi 5 DIM, dim, ki 66 stevila[4], tabela[4], polje[4] 512 stevila[3], tabela[3], polje[3] 123 stevila[2], tabela[2], polje[2] 231 stevila[1], tabela[1], polje[1] 304 stevila[0], tabela[0], polje[0] indeks pom i, zi najS ind j Zaslon
Urejanje podatkov POMNILNIK • Urejanje po metodi mehurčkov (Bubble sort): • začnemo na začetku tabele, primerjamo i-ti in i+1-vi element tabele; če nista v predpisanem zaporedju, ju zamenjamo, • v enem prehodu skozi tabelo pomaknemo največje število na konec tabele, manjša števila pa pomikamo proti začetku tabele, • zgornja koraka ponavljamo dokler ni tabela urejena. • #define DIM 5 • void Bubble(int[], int); • int _tmain(int argc, _TCHAR* argv[]) • { • int stevila[DIM] = {304,231,123,512, 66}; • Bubble(stevila, DIM); • for(int i = 0; i < DIM; i++) • printf("%d\n", stevila[i]); • return 0; • } Fizični naslovi Vsebina Logični naslovi 5 DIM 66 stevila[4] 512 stevila[3] 123 stevila[2] 231 stevila[1] 304 stevila[0] Zaslon
Urejanje podatkov POMNILNIK void Bubble(int tabela[], int n) { int pom; for(int i = 0; i < n; i++) { for(int j = 0; j < n-1; j++) { if(tabela[j] > tabela[j+1]) { pom = tabela[j]; tabela[j] = tabela[j+1]; tabela[j+1] = pom; } } } } Fizični naslovi Vsebina Logični naslovi 5 DIM, n 66 stevila[4], tabela[4] 512 stevila[3], tabela[3] 123 stevila[2], tabela[2] 231 stevila[1], tabela[1] 304 stevila[0], tabela[0] pom i j Zaslon
Urejanje podatkov POMNILNIK Urejanje z vstavljanjem: Vse elemente od drugega mesta do konca tabele vstavimo na ustrezno mesto v urejeni del tabele. Vedno primerjamo vrednost elementa, ki ga vstavljamo z vsemi predhodnimi elementi v urejenem delu tabele. Pri tem vse večje elemente pomikamo za eno mesto v desno, da pridobimo prostor za vstavljanje na ustrezno mesto v urejenem delu tabele. Z ustreznim vstavljanjem enega elementa se urejeni del tabele poveča za ena. #define DIM 5 void UrediVstavi(int[], int); int _tmain(int argc, _TCHAR* argv[]) { int stevila[DIM] = {304,231,123,512, 66}; UrediVstavi(stevila, DIM); for(int i = 0; i < DIM; i++) printf("%d\n", stevila[i]); return 0; } Fizični naslovi Vsebina Logični naslovi 5 DIM 66 stevila[4] 512 stevila[3] 123 stevila[2] 231 stevila[1] 304 stevila[0] Zaslon
Urejanje podatkov POMNILNIK void UrediVstavi(int tabela[], int n) { int element; for(int i = 1; i < n; i++) { element = tabela[i]; for(int j = 0; j < i; j++) { if(element < tabela[j]) { for(int k = i-1; k >= j; k--) { tabela[k+1] = tabela[k]; } tabela[j] = element; break; } } } } Fizični naslovi Vsebina Logični naslovi 5 DIM, n 66 stevila[4], tabela[4] 512 stevila[3], tabela[3] 123 stevila[2], tabela[2] 231 stevila[1], tabela[1] 304 stevila[0], tabela[0] element i i k Zaslon
Iskanje podatkov POMNILNIK Podatke v tabelah lahko poiščemo na več načinov. Zaporedno iskanje: #define DIM 5 int PoisciZaporedno(int[], int, int); int _tmain(int argc, _TCHAR* argv[]) { int iskanoSt = 123; int stevila[DIM] = {304,231,123,512, 66}; int ind = PoisciZaporedno(stevila, DIM, iskanoSt); if(ind >= 0) printf("%d je v tabeli na indeksu %d\n", iskanoSt, ind); else printf("%d ni v tabeli\n", iskanoSt); return 0; } int PoisciZaporedno(int tabela[], int n, int stevilo) { int indeks; for(indeks = 0; indeks < n; indeks++) { if(tabela[indeks] == stevilo) return indeks; } return (-1); } Fizični naslovi Vsebina Logični naslovi 5 DIM, n 66 stevila[4], tabela[4] 512 stevila[3], tabela[3] 123 stevila[2], tabela[2] 231 stevila[1], tabela[1] 304 stevila[0], tabela[0] 123 iskanoSt, stevilo ind indeks Zaslon
Iskanje podatkov POMNILNIK Podatke v tabelah lahko poiščemo na več načinov. Binarno iskanje: Pogoj za binarno iskanje je, da so elementi tabele urejeni po velikosti. Urejeno tabelo razdelimo enakomerno na dve polovici. Iskani podatek je lahko v prvi ali drugi polovici. Ustrezno polovico tabele izberemo s pomočjo primerjave iskanega podatka s sredinskim elementom tabele. Tako izločimo polovico tabele. Iskanje nadaljujemo na isti način v izbrani polovici. V dveh korakih izločimo tri četrtine podatkov. Postopek ponavljamo dokler ne najdemo števila, ki ga iščemo ali dokler ne ugotovimo, da iskanega števila ni v tabeli. #define DIM 5 int PoisciBinarno(int[], int, int); int _tmain(int argc, _TCHAR* argv[]) { int iskanoSt = 304; int stevila[DIM] = {66, 123, 231, 304,512}; int ind = PoisciBinarno(stevila, DIM, iskanoSt); if(ind >= 0) printf("%d je v tabeli na indeksu %d\n", iskanoSt, ind); else printf("%d ni v tabeli\n", iskanoSt); return 0; } Fizični naslovi Vsebina Logični naslovi 5 DIM 512 stevila[4] 304 stevila[3] 231 stevila[2] 123 stevila[1] 66 stevila[0] 304 iskanoSt ind Zaslon
Iskanje podatkov POMNILNIK int PoisciBinarno(int tabela[], int n, int stevilo) { int sredina; int spodaj = 0; int zgoraj = n-1; while(spodaj <= zgoraj) { sredina = (spodaj+zgoraj)/2; if(stevilo > tabela[sredina]) spodaj = sredina + 1; else if(stevilo < tabela[sredina]) zgoraj = sredina; else return sredina; } return (-1); } Fizični naslovi Vsebina Logični naslovi 5 DIM, n 512 stevila[4], tabela[4] 304 stevila[3], tabela[3] 231 stevila[2], tabela[2] 123 stevila[1], tabela[1] 66 stevila[0], tabela[0] 304 iskanoSt, stevilo sredina spodaj zgoraj Zaslon
REKURZIJA POMNILNIK Rekurzivnefunkcije so takšne funkcije, kikličejo same sebe. Uporabljamo jih takrat, ko lažje izrazimo rešitev problema tako, da se pri rešitvi sklicujemo na rešitev samo. Primer Faktoriela (rekurzivna definicija): n! = n * (n-1) * (n-2) * … * 3 * 2 * 1 To lahko zapišemo tudi na drugi način: n * (n-1) * (n-2) * … * 3 * 2 * 1 = n * (n-1)! Po predpostavki, da je 1! enaka 1 lahko zapišemo naslednji program: int _tmain(int argc, _TCHAR* argv[]) { printf("%d\n", fakt(4)); return 0; } int fakt(int n) { if (n == 1) return 1; return n * fakt(n - 1); } Fizični naslovi Vsebina Logični naslovi Zaslon 4* fakt(4)
REKURZIJA POMNILNIK Rekurzivnefunkcije so takšne funkcije, kikličejo same sebe. Uporabljamo jih takrat, ko lažje izrazimo rešitev problema tako, da se pri rešitvi sklicujemo na rešitev samo. Primer Faktoriela (rekurzivna definicija): n! = n * (n-1) * (n-2) * … * 3 * 2 * 1 To lahko zapišemo tudi na drugi način: n * (n-1) * (n-2) * … * 3 * 2 * 1 = n * (n-1)! Po predpostavki, da je 1! enaka 1 lahko zapišemo naslednji program: int _tmain(int argc, _TCHAR* argv[]) { printf("%d\n", fakt(4)); return 0; } int fakt(int n) { if (n == 1) return 1; return n * fakt(n - 1); } Fizični naslovi Vsebina Logični naslovi Zaslon 4* 3* fakt(4) fakt(3)
REKURZIJA POMNILNIK Rekurzivnefunkcije so takšne funkcije, kikličejo same sebe. Uporabljamo jih takrat, ko lažje izrazimo rešitev problema tako, da se pri rešitvi sklicujemo na rešitev samo. Primer Faktoriela (rekurzivna definicija): n! = n * (n-1) * (n-2) * … * 3 * 2 * 1 To lahko zapišemo tudi na drugi način: n * (n-1) * (n-2) * … * 3 * 2 * 1 = n * (n-1)! Po predpostavki, da je 1! enaka 1 lahko zapišemo naslednji program: int _tmain(int argc, _TCHAR* argv[]) { printf("%d\n", fakt(4)); return 0; } int fakt(int n) { if (n == 1) return 1; return n * fakt(n - 1); } Fizični naslovi Vsebina Logični naslovi Zaslon 4* 3* 2* fakt(4) fakt(3) fakt(2)
REKURZIJA POMNILNIK Rekurzivnefunkcije so takšne funkcije, kikličejo same sebe. Uporabljamo jih takrat, ko lažje izrazimo rešitev problema tako, da se pri rešitvi sklicujemo na rešitev samo. Primer Faktoriela (rekurzivna definicija): n! = n * (n-1) * (n-2) * … * 3 * 2 * 1 To lahko zapišemo tudi na drugi način: n * (n-1) * (n-2) * … * 3 * 2 * 1 = n * (n-1)! Po predpostavki, da je 1! enaka 1 lahko zapišemo naslednji program: int _tmain(int argc, _TCHAR* argv[]) { printf("%d\n", fakt(4)); return 0; } int fakt(int n) { if (n == 1) return 1; return n * fakt(n - 1); } Fizični naslovi Vsebina Logični naslovi Zaslon 4* 3* 2* 1 fakt(4) fakt(3) fakt(2) fakt(1)
REKURZIJA POMNILNIK Rekurzivnefunkcije so takšne funkcije, kikličejo same sebe. Uporabljamo jih takrat, ko lažje izrazimo rešitev problema tako, da se pri rešitvi sklicujemo na rešitev samo. Primer Faktoriela (rekurzivna definicija): n! = n * (n-1) * (n-2) * … * 3 * 2 * 1 To lahko zapišemo tudi na drugi način: n * (n-1) * (n-2) * … * 3 * 2 * 1 = n * (n-1)! Po predpostavki, da je 1! enaka 1 lahko zapišemo naslednji program: int _tmain(int argc, _TCHAR* argv[]) { printf("%d\n", fakt(4)); return 0; } int fakt(int n) { if (n == 1) return 1; return n * fakt(n - 1); } Fizični naslovi Vsebina Logični naslovi Zaslon 4* 3* 2* 1 fakt(4) fakt(3) fakt(2) fakt(1) 1
REKURZIJA POMNILNIK Rekurzivnefunkcije so takšne funkcije, kikličejo same sebe. Uporabljamo jih takrat, ko lažje izrazimo rešitev problema tako, da se pri rešitvi sklicujemo na rešitev samo. Primer Faktoriela (rekurzivna definicija): n! = n * (n-1) * (n-2) * … * 3 * 2 * 1 To lahko zapišemo tudi na drugi način: n * (n-1) * (n-2) * … * 3 * 2 * 1 = n * (n-1)! Po predpostavki, da je 1! enaka 1 lahko zapišemo naslednji program: int _tmain(int argc, _TCHAR* argv[]) { printf("%d\n", fakt(4)); return 0; } int fakt(int n) { if (n == 1) return 1; return n * fakt(n - 1); } Fizični naslovi Vsebina Logični naslovi Zaslon 4* 3* 2* 1 fakt(4) fakt(3) fakt(2) fakt(1) 2 1
REKURZIJA POMNILNIK Rekurzivnefunkcije so takšne funkcije, kikličejo same sebe. Uporabljamo jih takrat, ko lažje izrazimo rešitev problema tako, da se pri rešitvi sklicujemo na rešitev samo. Primer Faktoriela (rekurzivna definicija): n! = n * (n-1) * (n-2) * … * 3 * 2 * 1 To lahko zapišemo tudi na drugi način: n * (n-1) * (n-2) * … * 3 * 2 * 1 = n * (n-1)! Po predpostavki, da je 1! enaka 1 lahko zapišemo naslednji program: int _tmain(int argc, _TCHAR* argv[]) { printf("%d\n", fakt(4)); return 0; } int fakt(int n) { if (n == 1) return 1; return n * fakt(n - 1); } Fizični naslovi Vsebina Logični naslovi Zaslon 4* 3* 2* 1 fakt(4) fakt(3) fakt(2) fakt(1) 6 2 1
REKURZIJA POMNILNIK Rekurzivnefunkcije so takšne funkcije, kikličejo same sebe. Uporabljamo jih takrat, ko lažje izrazimo rešitev problema tako, da se pri rešitvi sklicujemo na rešitev samo. Primer Faktoriela (rekurzivna definicija): n! = n * (n-1) * (n-2) * … * 3 * 2 * 1 To lahko zapišemo tudi na drugi način: n * (n-1) * (n-2) * … * 3 * 2 * 1 = n * (n-1)! Po predpostavki, da je 1! enaka 1 lahko zapišemo naslednji program: int _tmain(int argc, _TCHAR* argv[]) { printf("%d\n", fakt(4)); return 0; } int fakt(int n) { if (n == 1) return 1; return n * fakt(n - 1); } Fizični naslovi Vsebina Logični naslovi Zaslon 4* 3* 2* 1 fakt(4) fakt(3) fakt(2) fakt(1) 24 6 2 1
REKURZIJA POMNILNIK Naloga: 1. Napišite rekurzivno funkcijo, ki poišče vsoto N celih števil. 2. Napišite rekurzivno funkcijo, ki vpisana števila izpiše v obratnem vrstnem redu. Fizični naslovi Vsebina Logični naslovi Zaslon
DREVESNA REKURZIJA POMNILNIK • Oglejmo si zaporedje Fibonaccijevih števil: • 0, 1, 1, 2, 3, 5, 8, 13, 21, ... • To zaporedje je definirano z naslednjo enačbo: • fib(n) = fib(n - 1) + fib(n - 2) • Pri tem velja, da je • fib(0) = 0 in fib(1) = 1 • Program, ki računa Fibonaccijeva števila je naslednji: • int _tmain(int argc, _TCHAR* argv[]) • { • printf("%d\n", fib(5)); • return 0; • } • int fib(int n) • { • if(n <= 0) return 0; • else if(n == 1) return 1; • else return fib(n - 1) + fib(n - 2) ; • } Fizični naslovi Vsebina Logični naslovi Zaslon
DREVESNA REKURZIJA fib(5)
DREVESNA REKURZIJA fib(5) fib(3) fib(4)
DREVESNA REKURZIJA fib(5) fib(3) fib(4)
DREVESNA REKURZIJA fib(5) fib(3) fib(4) fib(3) fib(2)
DREVESNA REKURZIJA fib(5) fib(3) fib(4) fib(3) fib(2)
DREVESNA REKURZIJA fib(5) fib(3) fib(4) fib(3) fib(2) fib(2) fib(1)
DREVESNA REKURZIJA fib(5) fib(3) fib(4) fib(3) fib(2) fib(2) fib(1)
DREVESNA REKURZIJA fib(5) fib(3) fib(4) fib(3) fib(2) fib(2) fib(1) fib(1) fib(0)
DREVESNA REKURZIJA fib(5) fib(3) fib(4) fib(3) fib(2) fib(2) fib(1) fib(1) fib(0)
DREVESNA REKURZIJA fib(5) fib(3) fib(4) fib(3) fib(2) fib(2) fib(1) fib(1) fib(0) 1
DREVESNA REKURZIJA fib(5) fib(3) fib(4) fib(3) fib(2) fib(2) fib(1) fib(1) fib(0) 1
DREVESNA REKURZIJA fib(5) fib(3) fib(4) fib(3) fib(2) fib(2) fib(1) 1 fib(0) 1
DREVESNA REKURZIJA fib(5) fib(3) fib(4) fib(3) fib(2) fib(2) fib(1) 1 fib(0) 1
DREVESNA REKURZIJA fib(5) fib(3) fib(4) fib(3) fib(2) fib(2) fib(1) 1 fib(0) 1 0