Adatszerkezetek és algoritmusok 1
Bevezetés Adatszerkezet egyszerű vagy összetett alapadatok rendszerének matematikai, logikai modellje elég jó ahhoz, hogy tükrözze a valós kapcsolatokat elég egyszerű a kezeléshez Adatszerkezet típusok Tömbök lineáris egy vagy többdimenziós Kapcsolt listák a kapcsolati információ is adat Gráf adathalmaz adatpárok kapcsolattal Fa hurok nélküli gráf Verem LIFO (Last In First Out) Sor FIFO (First In First Out). Műveletek feldolgozási tevékenységek (algoritmusok) Bejárás - az elemek elérése Keresés - adott értéknek megfelelő elemek kiválasztása Beszúrás - új adat beillesztése Törlés - adatelem eltávolítása Rendezés - elemeket logikai sorrendbe Összeválogatás - különböző rendezett adathalmazokból új elemhalmaz kialakítása Bonyolultság futási idő vagy helyigény az adatok számának függvényében B(n) 2
III.1 Lineáris tömbök N db. azonos típusú adatelem az elemekre egymást követő számokból álló indexhalmazzal hivatkozunk az elemeket egymást követő memóriahelyek tárolják az elemekhez bejárás nélkül férünk hozzá LB LB+1 UB-1 UB Lower Bound Upper Bound Hosszúság (Length) L = UB-LB+1 Indexelt alak A 1, A 2 A(1), A(2) A[1], A[2] Példa (C#) int [] DATA; DATA = new int [5]; DATA[0]=154 ; DATA[3]=-33 ; DATA[4]=1 ; 154-33 1 154. -33 1 III.1.1 Hozzáférés tömbelemhez - indexelés (C) int DATA[5]; LOC(DATA) LOC(DATA[4]) LOC(DATA[k])=LOC(DATA)+w * k ; w az alapadat tárolási mérete 4
III.1.2 Bejárás Ha L n elemű lineáris tömb, akkor minden eleme kiírható k számláló k=0 k<n hamis k=k+1 PRINT L[k] igaz Példa (C#) const int n = 6; int[] l; l = new int[n]; Random vletlen = new Random(); for (int k = 0; k < n; k++) { l[k] = vletlen.next(100); for (int k = 0; k < n; k++) { Console.WriteLine(l[k]); III.1.2.1 Pl 90 94 65 38 51 83 Példa (C) const int n = 10; int l[n]; for (int k = 0; k < n; k++) { l[k] = rand(); for (int k = 0; k < n; k++) { printf("%i\n",l[k]); 5
III.1.3 Rendezés Ha L n elemű lineáris tömb, akkor rendezett, ha L[0]< L[1]< L[2]<L[3]... L[n-1]<L[n] III.1.3.1 Buborék rendezés k, p számláló, s segéd k=0 k<n hamis k=k+1 hamis p<n-1-k igaz L[p]>L[p+1] igaz s=l[p] L(p)=L[p+1] L[p+1]=s p=p+1 hamis p=0 igaz n ( n 1 ) 2 Bonyolultság : O( n ) 2 6
Példa (C#) const int n =6; int[] l; l = new int[n]; Random vletlen=new Random(); for (int k = 0; k < n; k++) { l[k] = vletlen.next(100); for (int k = 0; k < n; k++) { for (int p=0; p<n-1-k;p++){ if (l[p] > l[p + 1]) { int s = l[p]; l[p] = l[p + 1]; l[p + 1] = s; for (int k = 0; k < n; k++) { Console.WriteLine(l[k]); Példa (C) const int n = 6; int l[n]; for (int k = 0; k < n; k++) { l[k] = rand(); for (int k = 0; k < n; k++) { for (int p=0; p<n-1-k;p++) { if (l[p] > l[p + 1]) { int s = l[p]; l[p] = l[p + 1]; l[p + 1] = s; for (int k = 0; k < n; k++) { printf("%i\n",l[k]); 7
III.1.3.2 Például 90 94 65 38 51 83 90 65 94 38 51 83 90 65 38 94 51 83 90 65 38 51 94 83 90 65 38 51 83 94 65 90 38 51 83 94 65 38 90 51 83 94 65 38 51 90 83 94 65 38 51 83 90 94 38 65 51 83 90 94 38 51 65 83 90 94 38 51 65 83 90 94 8
III.1.4 Keresés III.1.4.1 Szekvenciális keresés KER-t keressük, az n elemű L elemei között, LOC a keresett pozíció L[n]=KER K=0 L[K] KER hamis LOC=k Példa (C#) Bonyolultság : n 1 O( n ) k=k+1 const int n = 6; int[] l; l = new int[n+1]; Random vletlen = new Random(); for (int k = 0; k < n; k++) { l[k] = vletlen.next(10); Console.WriteLine("l[{0]={1", k, l[k]); int ker=5; l[n]=ker; int j = 0; while (l[j]!=ker) { j++; Console.WriteLine("Az 5 a {0.", j); igaz Példa (C) const int n = 10; int l[n+1]; for (int k = 0; k < n; k++) { l[k] = rand(); int ker=l[7]; l[n]=ker; int j = 0; while (l[j]!=ker) { j++; printf("az %i az %i.\n",l[7],j); III.1.4.2 Pl. 0 9 0 6 0 4 Az 5 a 6. - nincs ilyen 9
III.1.4.3 Bináris keresés KER-t keressük, ha L sorbarendezett, Beg, End, Mid segédváltozók, LOC a keresett pozíció, (INT) az egészrész Beg=LB(L) End=UB(L) Mid=INT((Beg+End)/2) igaz LOC=Mid End=Mid-1 igaz Beg<End és L(Mid) KER hamis L[Mid]=KER Mid=(INT)((Beg+End)/2) KER<L[Mid] igaz hamis LOC=Null Beg=Mid+1 hamis Bonyolultság : A legalább szükséges összehasonlítások száma f(n), Minden összehasonlításkor feleződik a minta f ( n ) 2 n f ( n ) log2( n ) 1 10
Példa (C#) const int n = 10; int[] l; l = new int[n + 1]; Random vletlen = new Random(); for (int k = 0; k < n; k++) { l[k] = vletlen.next(10); Console.WriteLine("l[{0]={1", k, l[k]); Console.WriteLine("Sorbarakva"); Array.Sort(l); for (int k = 0; k < n; k++) { Console.WriteLine("l[{0]={1", k, l[k]); int beg = 0; int end = n - 1; int mid = (int)((beg + end) / 2); int ker = 5; while ((beg<end) && (l[mid]!=ker)) { if (ker < l[mid]) end=mid-1; else beg=mid+1; mid = (int)((beg + end) / 2); if (l[mid] == ker) Console.WriteLine("Az 5 az {0.",mid); else Console.WriteLine("Nincs 5"); Példa (C) const int n = 10; int l[n+1]; for (int k = 0; k < n; k++) { l[k] = rand(); printf("%i") for (int k = 0; k < n; k++) { for (int p=0; p<n-1-k;p++) { if (l[p] > l[p + 1]) { int s = l[p]; l[p] = l[p + 1]; l[p + 1] = s; int beg = 0; int end = n - 1; int mid = (int)((beg + end) / 2); int ker = l[7]; while ((beg<end) && (l[mid]!=ker)) { if (ker < l[mid]) end=mid-1; else beg=mid+1; mid = (int)((beg + end) / 2); if (l[mid] == ker) printf("az %i az %i.",l[mid],mid); else printf("nincs"); 11
III.1.4.4 Pl. 2 4 3 2 4 7 7 2 1 2 Sorbarakva 1 2 2 2 2 3 4 4 7 7 beg=0 mid=4 end=9 beg=5 mid=7 end=9 beg=8 mid=8 end=9 Az 7 az 8. 12
III.2. Többdimenziós tömbök N * M db. azonos típusú adatelem az elemekre egymást követő számokból álló indexhalmazokból alkotott számpárokkal hivatkozunk az elemeket egymást követő memóriahelyek tárolják az elemekhez bejárás nélkül férünk hozzá III.2.1 Hozzáférés tömbelemhez - indexelés Kétdimenziós eset LB SOR1 LB SOR1 +1 UB SOR1-1 UB SOR1 LB SOR2 LB SOR2 +1 UB SOR2-1 UB SOR 2 LB SORn-1 LB SORn-1 +1 UB SORn-1-1UB SORn-1 LB SORn LB SORn +1 UB SORn -1 UB SOR n Indexelt alak A 1,1, A 12 A(1,1), A(1,2) A[1,1], A[1,2] Memória pozíció (A m * n-es mátrix) LOC(A(j,k))=LOC(A)+w * (n * j+k) ; w az alapadat tárolási mérete 13
Példa (C#) float[,] matrix; matrix = new float [3,3]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (i == j) matrix[i, j] = 1; else matrix[i, j] = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) Console.Write("{0,8:f2",matrix[i, j]); Console.WriteLine(); Példa (C) float matrix [3][3]; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { if (i == j) matrix[i][ j] = 1; else matrix[i][j] = 0; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) printf("%8.2f",matrix[i][j]); printf("\n"); III.2.2 Pl. 1,00 0,00 0,00 0,00 1,00 0,00 0,00 0,00 1,00 14
III.3. Rekordok, rekordszerkezetek, állományok A rekord egymáshoz tartozó (a világ egy egyedére vonatkozó) adattételek (mezők, attribútumok) gyűjteménye. az adattételek lehetnek összetettek** és tovább nem bonthatók egyszerűek*. például változó méretű adatsorok, szabálytalan tömbök tárolására használható Az állomány rekordok összessége. Név LB Lakcím** SOR1 +1 Testmagasság Testsúly* Példa (C#) struct ember { public String nev; public String lakcim; public int testmagassag; public int testsuly; // ember x; x = new ember(); x.nev = "Lajos"; x.lakcim = "Budapest"; x.testmagassag = 160; x.testsuly = 50; Console.WriteLine(x.nev + " " + x.lakcim + " " + x.testmagassag + " " + x.testsuly); Console.ReadLine(); LB SOR1 #include <stdio.h> #include <conio.h> Példa (C) #include <string.h> int _tmain(int argc, _TCHAR* argv[]) { struct ember { char nev[64]; char lakcim[64]; int testmagassag; int testsuly; ; // ember x; strcpy(x.nev,"lajos"); strcpy(x.lakcim,"budapest"); x.testmagassag = 160; x.testsuly = 50; printf("%s ",x.nev); printf("%s ",x.lakcim); printf("%i ",x.testmagassag); printf("%i \n",x.testsuly); getch(); return 0; 15
III.3.1 Szintszám, minősítés Az adattételek lehetnek összetettek, altételekkel. Például: Gyermek Név Apa Anya Példa (C#) struct ember { public string nev; public int apa; public int anya; static void Main(string[] args) { ember[] x; x = new ember[5]; x[0].nev = "Ádám"; x[1].nev = "Éva"; x[2].nev = "Káin"; x[2].apa = 0; // tömbindex a pointer helyett x[2].anya = 1; Console.ReadLine(); Név Példa (C) struct ember { char nev[64]; int apa; int anya; ; ember x[5]; strcpy(x[0].nev,"ádám"); strcpy(x[1].nev, "Éva"); strcpy(x[2].nev, "Káin"); x[2].apa = 0; // tömbindex a pointer helyett x[2].anya = 1; Név 16
III.5. Verem (Stack) Last In First Out Új elem behelyezése (PUSH) a tetejére (TOP) Elem leemelése (POP) III.5.1 A verem tárolása a b c d III.5.1.1 PUSH igaz TOP TOP=TOP+1 STACK(TOP)=Elem maxstk TOP<MAXSTK III.5.1.2 POP hamis hamis túlcsordul Elem=STACK(TOP) TOP=TOP-1 TOP=0 igaz alulcsordul 17
Példa C++ class stack { public: static const int max_stack = 10; int stack_pointer; double * x; stack() { x = new double[max_stack]; stack_pointer=0; void push(double be) { if (stack_pointer < max_stack) x[stack_pointer++] = be; double pop() { return x[--stack_pointer]; ; //Verem létrehozása stack * s=new stack(); printf("eloszor bekerul a 13\n"); s->push(13); printf("utana bekerul a 14\n"); s->push(14); printf("eloszor a %f jon ki\n", s->pop()); printf("aztan a %f jon ki\n", s->pop()); 18
III.6. Sor (Queue) First In First Out III.6.1 A sor tárolása (lebegő sor) a BOT b c d TOP maxque III.6.1.1 PUSH igaz TOP=TOP+1 QUE(TOP)=Elem TOP<MAXQUE-1 III.6.1.2 POP hamis túlcsordul hamis Elem=QUE(BOT) BOT=BOT+1 BOT>TOP igaz üres 19
public class queue { public const int size = 10; public int max_queue = 0; public int min_queue = 0; public double[] x; public queue() { x = new double[size]; public void push(double be) { if (max_queue< size -1) x[max_queue++] = be; public double pop() { if (min_queue < max_queue) return x[min_queue++]; else return 99999; //Sor létrehozása queue q = new queue(); Console.WriteLine("Először bekerül a 13"); q.push(13); Console.WriteLine("Utána bekerül a 14"); q.push(14); Console.WriteLine("Először a {0 jön ki", q.pop()); Console.WriteLine("Aztán a {0 jön ki", q.pop()); #include "stdafx.h" #include <conio.h> #include <stdlib.h> class queue { public: static const int size = 10; int max_queue; int min_queue; double x[size]; queue() { max_queue=0; min_queue=0; void push(double be) { if (max_queue< size -1) x[max_queue++] = be; double pop() { if (min_queue < max_queue) return x[min_queue++]; else return 99999; ; Példa (C) int _tmain(int argc, _TCHAR* argv[]) {//Sor létrehozása queue q = queue(); printf("eloszor bekerul a 13.0\n"); q.push(13); printf("utana bekerul a 14.0\n"); q.push(14); printf("eloszor a %f jon ki\n", q.pop()); printf("aztan a %f jon ki\n", q.pop()); getch(); return 0; 20
III.5.2 Rekurzió III.5.2.1. Faktoriális iteratív definíció n!=1 2 3 (n-2) (n-1) n N=0 hamis Fakt=1 k=1 k<=n k=k+1 Fakt=Fakt*k igaz hamis igaz Fakt=1 III.5.2.2. Faktoriális rekurzív definíció 0!=1 ; n!=n (n-1)! hamis Fakt()=n * Fakt(n-1) N=0 Példa (C#) public class Szamitasok { public static int fakt(int n) { if (n<2) return 1; else return n*fakt(n-1); igaz Fakt()=1 Console.Write("Nem negatív egész="); int n=convert.toint32(console.readline()); Console.WriteLine("{0!={1",n, Szamitasok.fakt(n)); 21
Hanoi tornyai Adott 3 torony Egyre csökkenő méretű lemezek vannak elhelyezve az első rúdon Minden lemezt át kell helyeznünk az első rúdról az utolsó rúdra Nagyobb lemezt nem lehet kisebb méretű lemezre helyezni A harmadik rudat segéd rúdként tudjuk használni
Hanoi tornyai: Rekurzív algoritmus void Hanoi(int n, char honnan, char hova, char seged) { if (n == 1) { printf("\n Tedd át az 1. lemezt a(z) %c rúdról a(z) %c rúdra", honnan, hova); return; Hanoi(n-1, honnan, seged, hova); printf("\n Tedd át a(z) %d. lemezt a(z) %c rúdról a(z) %c rúdra", n, honnan, hova); Hanoi(n-1, seged, hova, honnan); int main() { int n = 4; // lemezek száma Hanoi(n, 'A', 'C', 'B'); // A, B és C a rudak nevei return 0;
Tedd át a(z) 1. lemezt a(z) A rúdról a(z) B rúdra Tedd át a(z) 2. lemezt a(z) A rúdról a(z) C rúdra Tedd át a(z) 1. lemezt a(z) B rúdról a(z) C rúdra Tedd át a(z) 3. lemezt a(z) A rúdról a(z) B rúdra Tedd át a(z) 1. lemezt a(z) C rúdról a(z) A rúdra Tedd át a(z) 2. lemezt a(z) C rúdról a(z) B rúdra Tedd át a(z) 1. lemezt a(z) A rúdról a(z) B rúdra Tedd át a(z) 4. lemezt a(z) A rúdról a(z) C rúdra Tedd át a(z) 1. lemezt a(z) B rúdról a(z) C rúdra Tedd át a(z) 2. lemezt a(z) B rúdról a(z) A rúdra Tedd át a(z) 1. lemezt a(z) C rúdról a(z) A rúdra Tedd át a(z) 3. lemezt a(z) B rúdról a(z) C rúdra Tedd át a(z) 1. lemezt a(z) A rúdról a(z) B rúdra Tedd át a(z) 2. lemezt a(z) A rúdról a(z) C rúdra Tedd át a(z) 1. lemezt a(z) B rúdról a(z) C rúdra
Gyorsrendezés (Quicksort) Válasszunk egy t támpont elemet a rendezendő S halmazban Partícionáljuk S elemeit t kivételével 2 diszjunkt csoportba: 1. S 1 = {x S {t x t 2. S 2 = {x S {t x > t A rendezés eredménye: {Quicksort(S 1 ) + t + Quicksort(S 2 )
Gyorsrendezés (Quicksort) támpont kiválasztása particionálás
Gyorsrendezés (Quicksort)