0) b1[--n] = b[i]; // az utolsót már így is lehet! else Console.WriteLine("a tömb üres!"); for(i=0; i < b.Length; i++) Console.Write(b1[i]+" "); AAO">

Az előadás letöltése folymat van. Kérjük, várjon

Az előadás letöltése folymat van. Kérjük, várjon

AAO Csink László 2008. november.

Hasonló előadás


Az előadások a következő témára: "AAO Csink László 2008. november."— Előadás másolata:

1 AAO Csink László 2008. november

2 Egy n elemű sorozat csupa 0-ból és 1-ből áll
Egy n elemű sorozat csupa 0-ból és 1-ből áll. Rendezzük n-1 összehasonlítással! int i; int[] b = { 0,0,1,0,1,1,0,0,1,0,1,0,0,1,1,0 }; for (i = 0; i < b.Length; i++) Console.Write(b[i] + " "); Console.WriteLine(); int n = b.Length; int[] b1 = new int[n]; // b1 segédtömb for (i = 0; i < n - 1; i++) // b1 végére rakjuk az 1-ket if (b[i] ==1) b1[--n] =b[i]; // fontos, hogy --n és nem n-- if (b.Length > 0) b1[--n] = b[i]; // az utolsót már így is lehet! else Console.WriteLine("a tömb üres!"); for(i=0; i < b.Length; i++) Console.Write(b1[i]+" "); AAO

3 Egy n elemű sorozat csupa 0-ból és 1-ből áll
Egy n elemű sorozat csupa 0-ból és 1-ből áll. Rendezzük összehasonlítás nélkül! int szum = 0, i = 0; int[] b = { 0,0,1,0,1,1,0,0,1,0,1,0,0,1,1,0 }; // megszámoljuk, hány 1-es van for (i = 0; i < b.Length; i++) szum += b[i]; // b „elejét” kellő számú nullával feltöltjük for (i = 0; i < b.Length - szum; i++) b[i]=0; // b „végét” feltöltjük annyi 1-essel, amennyivel kell for (int j= i; j < b.Length; j++) b[j] = 1; AAO

4 A két megoldás összehasonlítása
Az első változatban kellett egy n hosszú ciklus és n-1 összehasonlítás, valamint még egy tömb A második változatban nem kellett összehasonlítás és extra tömb, de több ciklusra volt szükség AAO

5 Geometriai feladat Számítsuk ki a sokszög kerületét és területét!
Legyen adott egy konvex sokszög a síkban, csúcsainak koordinátáival, melyek óramutató járása szerinti bejárási tömbben adottak egy tömbben: x0 y0 x1 y1 x2 y2 ….. Számítsuk ki a sokszög kerületét és területét! AAO

6 A kerületszámítás eleje
Az egyik pont (x,y), a másik (xx,yy) koordinátájú A távolságot számító függvény: public static double tav(double x, double y, double xx, double yy) { return Math.Sqrt((x - xx) * (x - xx) + (y - yy) * (y - yy)); }; AAO

7 Közepe (a Main() belseje)
double[] tomb = new double[] { 1.0, 0.0, 0.0, 2.0, -1.0, 0.0, 0.0, -3.0 }; double x, y, xx, yy, d = 0.0; int i, n=tomb.Length; for (i = 0; i+3 < n; i=i+2) { // végig a pontokon x = tomb[i]; y = tomb[i+1]; xx = tomb[i+2]; yy = tomb[i+3]; d += tav(x, y, xx, yy); } d += tav(tomb[0], tomb[1], tomb[n - 2], tomb[n - 1]); AAO

8 Háromszög területe Heron képlettel
A 3szög pontjai (x1,y1), (x2,y2), (x3,y3) public static double heron(double x1, double y1, double x2, double y2, double x3, double y3){ double s, d1, d2, d3 ; d1 = Math.Sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)); d2 = Math.Sqrt((x2 - x3) * (x2 - x3) + (y2 - y3) * (y2 - y3)); d3 = Math.Sqrt((x1 - x3) * (x1 - x3) + (y1 - y3) * (y1 - y3)); s = (d1 + d2 + d3) / 2.0; return Math.Sqrt(s * (s - d1) * (s - d2) * (s - d3)); } AAO

9 Konvex sokszög területszámítása
double[] tomb = new double[] { 1.0, 0.0, 0.0, 2.0, -1.0, 0.0, 0.0, -3.0 }; double x, y, x1, y1, x2,y2, h = 0.0; int n = tomb.Length; x = tomb[0]; y = tomb[1]; for (int i = 2; i +3 < n; i = i+2) { x1 = tomb[i]; y1 = tomb[i+1]; x2 = tomb[i+2]; y2 = tomb[i+3]; h += heron(x, y, x1, y1, x2,y2); } Console.WriteLine("terulet: " + h); AAO

10 Miért kell a konvexitás?
Amit számítunk: T=(sárga+lila+kék)+(lila+kék) +(lila+barna) Helyesen: T=(sárga+lila+kék)-(lila+kék) +(lila+barna)=sárga+lila+barna A konvexitás biztosítja, hogy a területek összeadhatók! AAO

11 Legnagyobb közös osztó 1.
public static int euklidesz(int a, int b) { int t,a1,b1; a1 = Math.Max(a, b); b1 = Math.Min(a, b); while (a1 != b1) if (a1 > b1) a1 = a1 - b1; else { t = a1; a1 = b1; b1 = t; } } return a1; AAO

12 Legnagyobb közös osztó 2.
public static int gcd(int a, int b) { int t; while (b != 0) t = b; b = a % b; a = t; } return a; Hívás gcd(6,10) t b a 10 6 4 2 AAO

13 Legnagyobb közös osztó 3.
function gcd(a, b) if b = 0 return a else return gcd(b, a mod b) Pszeudokódban public static int gcd(int a, int b) { return ( b == 0 ? a : gcd(b, a % b) ); } Rekurzív C# algoritmus AAO

14 Példa egy harmadfokú polinomra:
Horner séma egy polinom adott x helyen vett értékének gyors kiszámítására Példa egy harmadfokú polinomra: P(x)=7x3 – 2x2 + 5 x = (7x2 – 2x + 5) x - 8= ((7x-2) x +5) x - 8 Az együtthatókat jelöljük: a[3] = 7 a[2]= - 2 a[1]= 5 a[0]= - 5 N=3; POL= a[N]; for(i=n-1; i>=0; i--) POL = POL*x + a[i]; AAO

15 A Fibonacci sorozat A Fibonacci számsorozatban minden szám az első kettő után - az azt megelőző kettő összege. Így tehát a számsorozat: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233 stb. Minél későbbi tagjait vesszük a sorozatnak, két egymást követő szám aránya annál inkább az aranymetszéshez fog közelíteni (ami megközelítőleg 1:1,618 vagy 0,618:1) AAO

16 Kiszámítás rekurzívan
public static int fibo(int i){ if (i == 0) return 0; else if (i == 1) return 1; else return fibo(--i) + fibo(--i); } Beugrató kérdés: Ez ugyanaz-e, mint return 2*fibo(--i) ? return fibo(i-1) + fibo(i-2); A Fibonacci számok gyorsan nőnek, a long indokolt lehet AAO

17 Fibonacci tömbbel int i, n; Console.Write("n= ");
n = int.Parse(Console.ReadLine()); long[] f = new long[n]; // Fibonacci számok gyorsan nőnek f[0]=0; f[1]=1; for( i=2;i<n; i++) f[i]= f[i-1]+f[i-2]; AAO

18 Fibonacci ArrayList-tel
int i=0, value=0; Console.Write(„Keressük az első Fibonacci számot, amely nagyobb mint: "); int n = int.Parse(Console.ReadLine()); ArrayList fiblist = new ArrayList(); fiblist.Add(0); fiblist.Add(1); for (i = 2; value <= n; i++) { int[] tomb = new int[fiblist.Count]; fiblist.CopyTo(tomb); value = tomb[i - 1] + tomb[i - 2]; fiblist.Add(value); } Console.WriteLine(n+" . fibo= " + fiblist[--i]); AAO

19 Volt-e szükség menetközben mindegyik Fibonacci számra?
Ha a feladat úgy szól, hogy olvassunk be egy n számot, és ha az első n-nél nagyobb Fibonacci szám 5-tel osztható, akkor írjuk ki az eddigi Fibonacci számok számtani közepét, egyéb esetben pedig a mértani közepét, akkor szükség van az összes korábbi Fibonacci számra (avagy mégsem??) De ha csak az aktuális Fibonacci szám kell, akkor van a tömbhasználatnál egyszerűbb megoldás. A rekurzió, vagy… AAO

20 Fibonacci segédváltozókkal
int i = 0, seged0 = 0, seged1 = 1, f=0; Console.Write("Keressük az n-dikFibonacci számot, ahol n= "); int n = int.Parse(Console.ReadLine()); if (n == 0) Console.WriteLine("A válasz 0"); else if (n==1) Console.WriteLine("A válasz 1"); else{ for (i = 2; i <= n; i++) { f =seged0 + seged1; seged0 = seged1; seged1 = f; } Console.WriteLine("f= "+f); Gyors és memóriatakarékos! Csak a legutolsó Fibonacci számot adja meg. AAO

21 Fibonacci zárt alakban – a képlet
Ekkor c0=0, c1=1, és n >=1 esetén (teljes indukcióval belátható) AAO

22 Fibonacci zárt alakban – a program
int fib; Console.Write("Hanyadik Fibonacci számot számítsuk: "); double n = double.Parse(Console.ReadLine()); double gyot =Math.Sqrt(5.0); fib = (int) Math.Truncate( (1.0/gyot)*( Math.Pow(((1.0+gyot)/2.0),n) - Math.Pow(((1.0-gyot)/2.0),n) ) ); Console.WriteLine("Az eredmény:"+fib); AAO

23 Rendezések A rendezési algoritmus olyan algoritmus, amely egy lista vagy egy tömb elemeit egy meghatározott (növekvő vagy csökkenő) sorrendbe helyezi el. A rendezés lehet numerikus és lehet lexikografikus. A rendezés legtöbbször azért szükséges, hogy utána könnyebben lehessen keresni. Ezentúl, szűkebb értelemben vett rendezés alatt egy olyan algoritmust fogunk érteni, melynek inputja egy egészeket tartalmazó számsorozat, outputja a számsorozat növekvő sorrendben. Az output mindig egy permutációja az inputnak. AAO

24 A rendezési algoritmusok osztályozása
Egy n elemű tömb esetében a szükséges összehasonlítások száma szerint Általános esetben (mi is az általános eset ?!) O(n*log n) összehasonlításnál kevesebb nem elég Számos ismert esetben (példák jönni fognak) O(n*n) összehasonlítás szükséges Néhány esetben (legutóbb tárgyalt eset, ahol csak 0 és 1 szerepelt) O(n) is elég Az O (ordó) jelölés magyarázatát ld. az Analízis tárgyban, vagy itt: AAO

25 További szempontok Szokás vizsgálni a cserék (swap) számát is.
Legyen a és b egészek. Cseréljük ki az értéküket! { int kesztyu = a; a = b; b = kesztyu; } Vizsgálható a memória takarékosság, vannak „helyben” rendező algoritmusok, és vannak olyanok, amelyek segéd tárterületeket igényelnek. Vannak rekurzív és nem rekurzív rendezések. AAO

26 Stabilitás Stabil rendezésnél az azonos kulcsú rekordok relatív sorrendje megmarad, nem stabil rendezésnél változhat. Tekintsünk egész koordinátájú pontokat a síkban, és bocsássunk merőlegeseket az x-tengelyre. Legyen az a feladat, hogy az így keletkezett szakaszokat rendezni kell az x-tengelyen vett korrdinátájuk szerint. Nevezzük az x-koordinátákat kulcsnak. Eszerint történnek az összehasonlítások, de csere esetén a teljes szakaszt (azaz pontpárt) kell cserélni. Legyen a pontsorozat (4, 2) (3, 7) (3, 1) (5, 6) Két sorrend is létrejöhet, ha vannak azonos x-koordinátájú (x=3) pontok: (3, 7) (3, 1) (4, 2) (5, 6) (eredeti sorrend marad, ez a stabil) (3, 1) (3, 7) (4, 2) (5, 6) (eredeti sorrend változik) AAO

27 Buborékrendezés A buborék rendezés a legrosszabb esetben (amikor az elemek csökkenő sorrendben vannak) valamint az átlagos esetben (amikor az elemek véletlenszerűen helyezkednek el) is O(n*n) komplexitású. Mivel sok O(n*log n) komplexitású rendezés van, nagy n esetén a buborék nem előnyös, kivéve, ha az elemek nagyjából eleve növekvően rendezettek. AAO

28 Buborék 1. (csere figyelésével)
public static void bubbleSort(int[] A) { bool csereltunk; int i, kesztyu; do { csereltunk = false; for (i = 0; i < A.Length - 1; i++) { if (A[i] > A[i + 1]) { kesztyu = A[i]; A[i] = A[i + 1]; A[i + 1] = kesztyu; csereltunk = true; } } while (csereltunk); } // nem kezeltük, ha a tömb 0 vagy 1 hosszú AAO

29 Buborék 1. főprogram static void Main() {
int[] A = new int[10]; int i; Random RandomClass = new Random(); for (i = 0; i < A.Length; i++) { A[i] = RandomClass.Next(10, 30); Console.Write(A[i] + " "); } Console.WriteLine(); bubbleSort( A ); for (i = 0; i < A.Length; i++) Console.Write(A[i] + " "); Console.ReadLine(); AAO

30 Buborék 2. public static void bubbleSort(int[] A) {
if (A.Length == 0) Console.WriteLine("A tömb üres!"); else if (A.Length == 1) Console.WriteLine("A tömb 1 elemű!"); else { int i, j, kesztyu; for (i = 0; i < A.Length - 1; i++) for (j = A.Length - 1; j > i; j--) if (A[ j – 1 ] > A[ j ]) { kesztyu = A[j]; A[j] = A[j - 1]; A[j - 1] = kesztyu; } } AAO

31 Kétirányú buborék – cocktail sort (C#)
bottom = 0; top = n-1; bool csere_volt = true; while (csere_volt == true){ csere_volt = false; for (i = bottom; i < top; i++) if (a[i] > a[i + 1]) { csere_volt= true; cs = a[i]; a[i]=a[i+1]; a[i+1]=cs; } top = top - 1; for (i = top; i > bottom; i--) if (a[i] < a[i - 1]) { csere_volt = true; cs = a[i]; a[i] = a[i-1]; a[i-1] = cs; } bottom = bottom + 1; } AAO

32 if (a[i - 1] <= a[i]) i++; // ha jó a sorrend, előre! else {
Kerti törpe rendezés (C#) Wikipedia: The name comes from the supposed behavior of the Dutch garden gnome in sorting a line of flowerpots. It is conceptually simple, requiring no nested loops. i = 1; while (i < n) { if (a[i - 1] <= a[i]) i++; // ha jó a sorrend, előre! else { int cs = a[i - 1]; a[i - 1] = a[i]; a[i] = cs; i--; if (i == 0) i = 1; } // else vége } // while vége AAO

33 Hogyan működik? Az algoritmus megkeresi az első olyan helyet, ahol két egymást követő elem rossz sorrendben van, és megcseréli őket. Ha egy ilyen csere után rossz sorrend keletkezik, az csak közvetlenül a legutolsó csere előtt lehet, így ezt is ellenőrizzük. Talán ez az elképzelhető legegyszerűbb rendezés. AAO

34 A buborék lényeges javítása: fésűs rendezés
A fésűs rendezést (comb sort) eredetileg 1980-ban tervezték, majd újra felfedezték és 1991-ben publikálták a Byte magazinban. A buborék rendezés módosítása, sebességében közelít a híres quicksorthoz. Az alapötlet az, hogy a sorozat végén levő kicsi értékekre találjunk rá minél hamarabb, mert ezek lassítják jelentősen a buborékot. (A sorozat elején levő nagy értékek nem annyira lassítóak, mert ezekre hamar rátalálunk). AAO

35 A fésű kódja public static void combSort(int[] A) { int i; if (A.Length == 0) Console.WriteLine("A tömb üres!"); else if (A.Length == 1) Console.WriteLine("A tömb egyelemű!"); else { int gap = A.Length, cserevolt = 0, kesztyu; while ((gap >1) || (cserevolt !=0)) { if (gap > 1) // gap /1.3 lefelé kerekítve gap = (int)Math.Truncate((double)gap / 1.3); if ((gap == 10) || (gap == 11)) gap = 9; i = 0; cserevolt = 0; while (i + gap < A.Length) { if (A[i] > A[i+gap]){ kesztyu = A[i]; A[i]=A[i+1]; A[i+1] = kesztyu; cserevolt = 1; } i++; AAO

36 Megjegyzések 10 ezer elemű tömbön végzett kísérletek szerint a fésűs rendezés alig rosszabb a quicksortnál (10 %-kal); a változtatás a buborékhoz képest nem nagy. Ugyanakkor nem kell gondoskodni az eleve rendezett esetről, ami a quicksortot nagyon lelassítja (látni fogjuk). A gap beállításával először a távollevő elemeket rendezzük. Ezután a gap csökken, míg végül egy lesz. Ez esetben azonos a program a buborékkal; következésképpen korrekt. Lacey és Richard Box megmutatták, hogy a gap minden lépésben 1.3-mal osztandó. Továbbá felfedezték, hogy 9 és 10 nem alkalmas gap-nek, és 11-gyel helyettesítendő. AAO

37 Combsort versus quicksort
sec Combsort sec Bubblesort 1.36 sec 10 ezer egész szám rendezési kísérletének időeredményei Forrás:http://www.yagni.com/combsort/index.php [2008. nov. 16.] AAO

38 Quicksort -rekurzívan
static void csere( ref int x, ref int y) { int t= x; x = y; y = t; } static int partition (int[] a, int first, int last) { int pivot = a[first], lastS1 = first, firstUnknown = first + 1; while (firstUnknown <= last) { if (a[firstUnknown] < pivot) { lastS1++; csere( ref a[firstUnknown], ref a[lastS1]); } firstUnknown++; } csere( ref a[first], ref a[lastS1]); return lastS1; static void quicksort (int[] a) { quicksort (a, 0, a.Length - 1); } static void quicksort (int[] a, int first, int last) { if (first < last) { int pivotIndex = partition (a, first, last); quicksort (a, first, pivotIndex - 1); quicksort (a, pivotIndex + 1, last); AAO

39 Minimum kiválasztásos rendezés
static void csere (ref int x, ref int y) { int cs =x; x=y; y=cs; } static void Main() { int i,min, n = 10; int[] a = new int[n]; Random RandomClass = new Random(); for (i = 0; i < n; i++) a[i] = RandomClass.Next(10, 26); for (i = 0; i < n; i++) { min = i; for (int j = i + 1; j < n; j++) if (a[j] < a[min]) min = j; csere(ref a[i], ref a[min]); } AAO

40 Beszúrásos rendezés static void csere (ref int x, ref int y) { int cs =x; x=y; y=cs; } static void Main() { int i,min, n = 10; int[] a = new int[n]; Random RandomClass = new Random(); for (i = 0; i < n; i++) a[i] = RandomClass.Next(10, 26); for (i = 1; i < n; i++) { j = i - 1; while ((j> -1) && (a[j] > a[j+1])) { csere(ref a[j], ref a[j+1]); j--; } AAO

41 Sorting demo AAO

42 Halmazműveletek: metszet
A feladat most két tömb a[0..n-1] és b [0..m-1] azonos elemeinek kiválogatása c tömbbe. A feladat csak úgy értelmezhető pontosan, ha az egyes tömbökben egy elem nem szerepel kétszer. (Mivel most a matematikai halmazokat tömbként ábrázoljuk.) Az algoritmus lényege: menjünk végig az a tömb elemein, és válogassuk ki azokat (kiválogatás), melyek szerepelnek b-ben (eldöntés). Így a feladat a korábbi tételekre visszavezethetõ. c maximális elemszáma n és m közül a kisebbik. Feltételeztük, hogy egyik halmaz sem üres. AAO

43 Deklarációk a metszethez C#
int n = 10, m=6, db =Math.Min(n,m); // tömbméretek int i,j,k; // ciklusváltozók int[] a = new int [n]; // a halmaz elemei 0..n-1 int[] b = new int [m]; // b halmaz elemei 0..m-1 int[] c = new int [db]; // a metszet elemei // db csak a maximális lehetséges tömbméret. Ha a metszet // üres, akkor nyilván nincs elem a metszetben. AAO

44 Metszet C# kód k = 0; for (i=0; i<n;i++) {
Az if NINCS a ciklusban, mert a for törzse üres! k = 0; for (i=0; i<n;i++) { for(j=0; (j<m) && (b[j] != a[i]); j++); // amíg j<m és b[j]<>a[i] if (j<m) c[k++]=a[i]; // ha j=m, akkor a[i] nem szerepelt b-ben // ha j<m, akkor a[i] előfordult b-ben } for (i = 0; i < k; i++) Console.WriteLine(c[i]); // kiíratás AAO

45 Halmazműveletek: unió
A feladat most két tömb a[0..n-1] és b [0..m-1] elemeinek egyesítése c tömbbe. Az egyes tömbökben egy elem nem szerepel kétszer. (mint az előbb) A legkézenfekvőbb megoldás: tegyük be c-be a összes elemét, majd b-ből azokat, melyek nem szerepelnek a-ban. c elemszáma legfeljebb n+m. Feltételeztük, hogy egyik halmaz sem üres. AAO

46 Unió C# kód for (i = 0; i < n; i++) c[i] = a[i]; //a-t áttöltjük c-be k = n; for (j = 0; j < m; j++){ // keressük azt a b-belit, ami nincs a-ban for (i = 0; (i< n) && (b[j] != a[i]); i++) ; if (i >= n) c[k++] = b[j]; // ha volt ilyen, c-be teszzük } for (i = 0; i < k; i++) Console.WriteLine(c[i]); // Futásidő n*m nagyságrendű! AAO

47 Unió speciális esetben (C#): az a és b (halmazokat reprezentáló) tömbök rendezettek (összefuttatás)
Csak az egyik fut! i = 0; j = 0; k = 0; while(( i < n) && ( j < m)) if (a[i]<b[j]) c[k++] = a[i++]; else if (a[i]==b[j]) {c[k++]= a[i++]; j++;} else c[k++] = b[j++]; for (x=i; x<n; x++) c[k++] =a[x]; for (x=j; x<m; x++) c[k++] =b[x]; for (i = 0; i < k; i++) Console.WriteLine(c[i]); // Futásidő n+m nagyságrendű, n*m helyett (előző)! AAO


Letölteni ppt "AAO Csink László 2008. november."

Hasonló előadás


Google Hirdetések