1 / 47

AAO

AAO. Csink László 2008. november. 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();

joie
Download Presentation

AAO

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. AAO Csink László 2008. november

  2. 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]+" ");

  3. 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;

  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

  5. Geometriai feladat 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!

  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)); };

  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]);

  8. Háromszög területe Heron képlettel A 3szög pontjai (x1,y1), (x2,y2), (x3,y3) public static doubleheron(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)); }

  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);

  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!

  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; • }

  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)

  13. Legnagyobb közös osztó 3. functiongcd(a, b) if b = 0 return a elsereturngcd(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

  14. 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 - 8 = (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];

  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)

  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

  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];

  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]);

  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…

  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.

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

  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);

  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.

  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: http://en.wikipedia.org/wiki/Big_O_notation

  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.

  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)

  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.

  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ú

  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(); }

  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; } } }

  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; }

  32. 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

  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.

  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).

  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++; } } } }

  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ő.

  37. Combsort versus quicksort 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.]

  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], refa[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); } }

  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]); } }

  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--; } } }

  41. Sorting demo • http://www.cs.ubc.ca/~harrison/Java/sorting-demo.html

  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õ. cmaximális elemszáma n és m közül a kisebbik. Feltételeztük, hogy egyik halmaz sem üres.

  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.

  44. Metszet C# kód 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

  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 legfeljebbn+m. Feltételeztük, hogy egyik halmaz sem üres.

  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ükazt 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ű!

  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ő)!

More Related