UNIVERSITETI I PRISHTINËS “HASAN PRISHTINA” FAKULTETI I SHKENCAVE MATEMATIKE-NATYRORE DEPARTAMENTI I MATEMATIKËS Detyra nga Analiza e Algoritmeve Asistenti: Dr. sc. Astrit Hulaj Astrit Hulaj 1 Kapitulli 1 1. Algoritmet bazike Çfarë është analiza e algoritmit? Është shumë e zakonshme për fillimin e studentëve të shkencave kompjuterike për të krahasuar programet e tyre me njëri-tjetrin. Ju gjithashtu mund të keni vërejtur se është e zakonshme që programet kompjuterike të duken shumë të ngjashëm, veçanërisht ato që janë të thjeshta. Shpesh lind një pyetje interesante. Kur dy programe zgjidhin të njëjtin problem, por duken ndryshe, a është një program më i mirë se tjetri? Për t'iu përgjigjur kësaj pyetjeje, duhet të kujtojmë se ekziston një ndryshim i rëndësishëm midis një programi dhe algoritmit themelor që programi përfaqëson. Siç dihet, një algoritëm është një listë e përgjithshme, ku përshkruan hap pas hapi se si mund të zgjidhet një problem. Është një metodë për zgjidhjen e çdo instance të problemit e tillë që duke pasur parasysh një input të veçantë, algoritmi prodhon rezultatin e dëshiruar. Një program, nga ana tjetër, është një algoritëm që është kodifikuar në ndonjë gjuhë programimi. Mund të ketë shumë programe për të njëjtin algoritëm, varësisht nga programuesi dhe gjuha e programimit që po përdoret. Për të eksploruar më tej këtë ndryshim, merrni parasysh funksionin e treguar në vazhdim. Ky funksion zgjidh një problem të njohur, duke llogaritur shumën e numrave natyror. Shembull 1.1. Programi në Java për llogaritjen e shumës së numrave natyror. Algoritmi për mbledhjen e shumës së numrave natyrorë. Astrit Hulaj 2 Kodi për shumën n numrave natyrorë është: public class SumNatural { public static void main(String[] args) { int num = 100, sum = 0; for(int i = 1; i <= num; ++i) { // sum = sum + i; sum += i; } System.out.println("Shuma = " + sum); } } Rezultati Shuma = 5050 Shembull 1.2. public class SumNatural { Astrit Hulaj 3 public static void main(String[] args) { int num = 100, i = 1, sum = 0; while(i <= num) { sum += i; i++; } System.out.println("Shuma = " + sum); } } Rezultati: Shuma = 5050 Shembull 1.3. Te shkruhet kodi i cili bënë pjesëtimin e dy numrave. Në vijim janë paraqitur disa shembuj që mund të testohen. Input : num1 = 13, num2 = 2 Output : 6 Input : num1 = 14, num2 = -2 Output : -7 Input : num1 = -11, num2 = 3 Output : -3 Input : num1 = 10, num2 = 10 Output : 1 Input : num1 = -6, num2 = -2 Output : 3 Input : num1 = 0, num2 = 5 Output : 0 Kodi // Java program to divide a number by other // without using / operator import java.io.*; class GFG { Astrit Hulaj 4 // Funksioni për të gjetur pjesëtimin pa përdorur operatorin '/' static int division(int num1, int num2) { if (num1 == 0) return 0; if (num2 == 0) // Integer.MAX_VALUE është një konstante në klasën Integer të paketës java.lang që specifikon që ruan vlerën maksimale të mundshme për çdo ndryshore të plotë në Java. Vlera aktuale e kësaj është 2^31-1 = 2147483647 return Integer.MAX_VALUE; boolean negResult = false; //Trajtimi i numrave negativë if (num1 < 0) { num1 = -num1 ; if (num2 < 0) num2 = - num2 ; else negResult = true; } else if (num2 < 0) { num2 = - num2 ; negResult = true; } // nëse num1 është më i madh ose i barabartë me num2 zbrit num2 nga num1 dhe rrit herësin për një. int quotient = 0; while (num1 >= num2) { num1 = num1 - num2 ; quotient++ ; } // checking if neg equals to 1 then making // quotient negative if (negResult) quotient = - quotient ; return quotient ; } // Driver program Astrit Hulaj 5 public static void main (String[] args) { int num1 = 13, num2 = 2 ; System.out.println("Rezultati:"); System.out.println( division(num1, num2)); } } Rezultati Rezultati: 6 Shembull 1.4. Te shkruhet kodi i cili bënë pjesëtimin e dy numrave si dhe llogarit mbetjen pas pjesëtimit. Pjesa e mbetur është numri i plotë i mbetur pasi ndan një numër të plotë me një tjetër. Herësi është sasia e prodhuar nga pjesëtimi i dy numrave. Për shembull, (7/2) = 3 Në shprehjen e mësipërme 7 ndahet me 2, kështu që herësi është 3 dhe pjesa e mbetur është 1. Kodi public class PL_MB { public static void main(String[] args) { int vl = 556, pjestuesi = 9; int plote = vl / pjestuesi; int mbetja = vl % pjestuesi; System.out.println("Vlera e plote eshte = " + plote); System.out.println("Vlera e mbetur eshte = " + mbetja); } } Shembull 1.5. Te ndërtohet bllok diagrami dhe të shkruhet kodi i cili llogarit prodhimin e numrave natyrorë mes 2 dhe n, nëse është dhënë vlera e variablës n. Astrit Hulaj 6 Bllok diagrami Kodi Kodi për llogaritje të prodhimit të numrave public class Prodhimi { public static void main(String[] args) { int n = 3, p = 1; for(int i = 2; i <= n; ++i) { p = p*i; } System.out.println("P = " + p); Astrit Hulaj 7 } } Rezultati: P = 6 Shembull 1.6. Programi për faktorialin e një numri Faktorial i një numri të plotë jo-negativ, është shumëzimi i të gjithë numrave të plotë më të vogël ose të barabartë me n. Për shembull faktorial i 6 është 6 * 5 * 4 * 3 * 2 * 1 që është 720. Faktoriali mund të llogaritet duke përdorur formulën e mëposhtme recursive. n! = n * (n-1)! n! = 1 if n = 0 or n = 1 Te ndërtohet bllok diagrami dhe të shkruhet kodi i cili bënë llogaritjen e fakrorielit të tillë. Bllok diagrami: Astrit Hulaj 8 Kodi // Programi në Java për gjetjen e faktorelit //import java.util.concurrent.TimeUnit; class Test { // method to find factorial of given number static int factorial(int n) { if (n == 0) return 1; return n * factorial(n - 1); } // Driver method public static void main(String[] args) { // long startTime = System.currentTimeMillis(); int n = 5; System.out.println("Faktorieli per numrin " + n + " eshte= " + factorial(n)); long startTime = System.nanoTime(); long endTime = System.nanoTime(); long timeElapsed = endTime - startTime; System.out.println("Koha e ekzekutimit ne nano sekonda: " + timeElapsed); Astrit Hulaj 9 } } Rezultati Faktorieli per numrin 5 eshte= 120 Koha e ekzekutimit ne nano sekonda: 200 Shembull 1.7. public class Test { // Method to find factorial of the given number static int factorial(int n) { int res = 1, i; for (i = 2; i <= n; ++i) res *= i; return res; } // Driver method public static void main(String[] args) { int num = 5; System.out.println( "Factorial of " + num + " is " + factorial(5)); } } Rezultati Factorial of 5 is 120 Shembull: Llogaritja e vlerës numerike të faktorielit: F=(2m+n)! nëse janë dhënë vlerat e variablave m dhe n. Bllok diagrami Astrit Hulaj 10 Kodi public class Faktorieli { public static void main(String[] args) { int m=1, n = 2, F = 1; for(int i = 1; i <= 2*m+n; ++i) { F = F*i; } System.out.println("F = " + F); } } Shembull 1.8. Llogaritja e vlerës numerike të funksionit: nëse janë dhënë vlerat e variablave x dhe n. Astrit Hulaj 11 Codi public class Faktorieli1 { public static void main(String[] args) { int n=2; int i; int j; double x=3; double y,s,F; s = 0; for (i = 1;i <= n;++i) { F = 1; for (j = 1;j <= 2 * i + 1;++j) { F = F * j; } s = s + (F - x); } y = x / 2 - 3 * s; System.out.println("Vlera e funksionit y="+ y); }} Rezultatet Nëse programi ekzekutohet për vlerat hyrëse x=3 dhe n=2, rezultati që shtypet në ekran duket: Astrit Hulaj 12 Vlera e funksionit y=-358.5 Shembull 1.9. Llogaritja e vlerës numerike të funksionit: nëse janë dhënë vlerat e variablave x, a dhe m. Algoritmi Astrit Hulaj 13 Kodi // Programi Prg5_20 public class Sum { public static void main(String[] args) { double x = 3; double a = 0.5; int m = 3; int i; int k; double s; double p; double F; double z; s = 0; for (k = 1;k <= m - 1;k++) { s = s + Math.pow(k + a,2); } p = 1; i = 2; do { p = p * (i / 2.0 + 3); i = i + 2; } while (i <= 2 * m); F = 1; for (i = 1;i <= m + 1;i++) Astrit Hulaj 14 { F = F * i; } z = 3 * s - 4 * p + F / (x + 2); System.out.print("Rezultati z=" +z); //System.out.print(z); //System.out.print("\n"); } } Rezultati Nëse programi ekzekutohet për vlerat hyrëse të deklaruara si konstante, rezultati që shtypet në ekran është: Rezultati z=-449.7 Shembull 1.10. public class Test { // Method to find factorial of the given number static int factorial(int n) { if(n == 0) return 1; int i = n, fact = 1; while (n / i != n) { fact = fact * i; i--; } return fact; } // Driver method public static void main(String[] args) { int num = 5; System.out.println( "Factorial of " + num + " is " + factorial(5)); } } Rezultati Factorial of 5 is 120 Astrit Hulaj 15 Shembull 1.11. Llogaritja e vlerës së funksionit: nëse dihen vlerat e variablave m, n dhe x. Zgjidhja Bllok diagrami Për vlerat hyrëse që janë marrë si shembull gjatë vizatimit të rrugës në Figurë, vlera e llogaritur e funksionit është: Kodi Astrit Hulaj 16 // Programi ASS public class ASS{ public static void main(String[] args) { long start = System.nanoTime(); int m=3, n=1, i; //int ; //int i; double x=1,s,y; // double s; // double y; s = 0; i = 1; do { s = s + Math.pow(x + 2.0 / i,i / 3.0); i = i + 1; } while (i <= m + n - 1); y = x / 3 + 2 * s; System.out.print("Vlera e funksionit y="); System.out.print(y); System.out.print("\n"); long end = System.nanoTime(); long koha = end - start; System.out.println("Koha e ekzekutimit ne nano sekonda: " + koha +" nano"); } } Rezultati Vlera e funksionit y=9.725967911217882 Koha e ekzekutimit ne nano sekonda: 2634500 nano Metoda 2 // Programi ASS public class ASS1{ public static void main(String[] args) { long start = System.nanoTime(); int m=3, n=1, i; //int ; //int i; double x=1,s,y; Astrit Hulaj 17 s = 0; for (i = 1;i <= m + n - 1; i++) { s = s + Math.pow(x + 2.0 / i,i / 3.0); } y = x / 3 + 2 * s; System.out.print("Vlera e funksionit y="); System.out.print(y); System.out.print("\n"); long end = System.nanoTime(); long koha = end - start; System.out.println("Koha e ekzekutimit ne nano sekonda: " + koha +" nano"); } } Rezultati Vlera e funksionit y=9.725967911217882 Koha e ekzekutimit ne nano sekonda: 2576400 nano Shembull 1.12. Llogaritja e vlerës numerike të funksionit: nëse janë dhënë vlerat e variablave n dhe x. Zgjidhje Bllok diagrami Astrit Hulaj 18 Versioni më i saktë i bllok-diagramit mund të vizatohet duke e vendosur bllokun për leximin e variablës n në degën e majtë të degëzimit që është vendosur në fillim të tij, sepse variabla në fjalë shfrytëzohet vetëm në këtë pjesë. Astrit Hulaj 19 Kodi public class Suma{ public static void main(String[] args) { long startTime = System.nanoTime(); int n=2, k; //int k; double x=3, p, d; //double p; //double d; System.out.print("Vlerat hyrëse n dhe x: "); if (x < (n + 2)) { p = 1; for (k = 1;k <= n + 2;k++) { p = p * (k * k + x / 3); } d = x - 2 * p; } else { if (x == n + 2) { d = Math.exp(2 * x) + 3; } else { d = 2 * x + 3 * n - 1; } } System.out.print("Rezultati d = " +d); //System.out.print(d); System.out.print("\n"); long endTime = System.nanoTime(); long timeElapsed = endTime - startTime; System.out.println("Koha e ekzekutimit ne nano sekonda: " + timeElapsed +" nano"); } } Rezultati Nëse programi i dhënë ekzekutohet për vlerat hyrëse n=2 dhe x=3, në ekran Astrit Hulaj 20 do të shtypet: Vlerat hyrëse n dhe x: Rezultati d = -3397.0 Koha e ekzekutimit ne nano sekonda: 23775800 nano Shembull 1.13. Llogaritja e vlerës numerike të funksionit: nëse janë dhënë vlerat e variablave m, n dhe x. Bllok diagrami Astrit Hulaj 21 Këtu, versioni më i saktë i bllok-diagramit do të vizatohej nëse blloqet për leximin e variablave m dhe n vendosen në degën e majtë dhe të djathtë (përkatësisht), sepse vetëm në këto degë shfrytëzohen. Rruga - për m=4, n=4 dhe x=2 Gjatë rrugës së kaluar, meqë plotësohet kushti x+1<4.5, vlera e funksionit llogaritet përmes shprehjes së parë ku figuron shuma, kështu: Kodi public class Shuma1 { public static void main(String[] args) { long start = System.nanoTime(); int m = 4, n=4, i,k; double s, p, x=2,g; if (x + 1 < 4.5) { s = 0; for (i = 2;i <= n + 1;i++) Astrit Hulaj 22 { s = s + (i + x); } g = 2 * x - 3 * s; } else { if (x + 1 == 4.5) { g = 4 * Math.pow(x,2) + 3 * x + 1; } else { p = 1; for (k = 1;k <= m;k++) { if (k != 3) { p = p * (k + x / 3); }} g = x / 2 + 4 * p; }} System.out.print("Vlera e llogaritur g="); System.out.print(g); System.out.print("\n"); long end = System.nanoTime(); long koha = end - start; System.out.println("Koha e ekzekutimit ne nano sekonda: " + koha +" nano"); } } Rezultati Vlera e llogaritur g=-62.0 Koha e ekzekutimit ne nano sekonda: 2218800 nano Shembull 1.14. Formimi i matricës A(m, n), duke i llogaritur anëtarët aij të saj kështu: nëse dihen dimensionet e matricës. Astrit Hulaj 23 Bllok diagrami Rruga - për m=2, n=3 Astrit Hulaj 24 Kodi public class Matrica{ public static void main(String[] args) { //long start = System.nanoTime(); int m = 2; int n = 3; int i; int j; int[][] A = new int[m][n]; for (i = 0;i < m; i++) { for (j = 0;j < n; j++) { if (i < j) { A[i][j] = 2 * i + 3 * j; } else { if (i == j) { A[i][j] = i + j; } else { A[i][j] = 3 * i - j * j; } }}} System.out.print("Matrica e formuar"); System.out.print("\n"); for (i = 0;i < m;i++) { for (j = 0;j < n;j++) { System.out.print(A[i][j]); System.out.print(" "); } System.out.print("\n"); //long end = System.nanoTime(); //long koha = end - start; //System.out.println("Koha e ekzekutimit ne nano sekonda: " + koha +" nano"); Astrit Hulaj 25 }}} Rezultati Nëse ekzekutohet programi i dhënë, rezultati që shtypet në ekran është: Matrica e formuar 0 3 6 3 2 8 Shembull 1.15. Formimi i matricës katrore A(m,m), duke shfrytëzuar anëtarët e vektorit të dhënë D(m), kështu: Bllok diagrami Astrit Hulaj 26 Siç shihet edhe nga bllok-diagrami, për i<j duhet të mbushen anëtarët mbi diagonalen kryesore, kurse kur është i>j kemi të bëjmë me anëtarët nën diagonalen kryesore. Kodi public class Matrica1{ public static void main(String[] args) { int m = 5; int[] D = {3, -7, 4, 9, -2}; int i; int j; int[][] A = new int[m][m]; for (i = 0;i < m;i++) { for (j = 0;j < m;j++) { if (i < j) { A[i][j] = D[i] + j; } else { if (i == j) { A[i][j] = D[i]; } else { A[i][j] = D[i] + 8; }} }} System.out.print("Matrica e formuar"); System.out.print("\n"); for (i = 0;i < m;i++) { for (j = 0;j < m;j++) { System.out.printf("%5d", A[i][j]); } System.out.printf("\n"); } } } Astrit Hulaj 27 Rezultati Rezultati që shtypet në ekran pas ekzekutimit të programit të dhënë është: Matrica e formuar 3 4 5 1 -7 -5 12 12 4 17 17 17 6 6 6 6 -4 7 9 6 7 -3 8 13 -2 Shembull 1.16. Formimi i matricës T, kështu: ku E(n,n) është matrica njësi, kurse O(n,n) është matrica zero. Bllok diagrami Astrit Hulaj 28 Kodi public class Matricanjesi { public static void main(String[] args) { final int n = 5; int i; int j; int[][] T = new int[2 * n][n]; for (i = 0;i < (2 * n);i++) { for (j = 0;j < n;j++) { if (i < n) { if (i == j) { T[i][j] = 1; } else { T[i][j] = 0; } } else { T[i][j] = 0; } } } System.out.print("Matrica e formuar"); System.out.print("\n"); for (i = 0;i < (2 * n);i++) { for (j = 0;j < n;j++) { System.out.printf("%3d", T[i][j]); } System.out.printf("\n"); } } } Rezultati Astrit Hulaj 29 Matrica e formuar 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 Shembull 1.17. Formimi i matricës R, duke shfrytëzuar anëtarët e matricave F(m,n) dhe G(l,k), kështu: ku me 0 është shënuar matrica zero. Zgjidhje Bllok diagrami Astrit Hulaj 30 Kodi: public class Matrica5 { public static void main(String[] args) { final int m = 3; final int n = 4; final int l = 4; final int k = 3; int[][] F = { {4, 7, 3, 5}, {-2, 3, 9, 2}, {8, -4, 2, 7} }; int[][] G = { {-2, 9, 1}, {4, 8, 3}, {6, 1, 7}, {-9, 4, 2} Astrit Hulaj 31 }; int i; int j; int[][] R = new int[m + l][n + k]; for (i = 0;i < m + l;i++) { for (j = 0;j < n + k;j++) { if (i < m) { if (j < n) { R[i][j] = F[i][j]; } else { R[i][j] = 0; } } else { if (j < n) { R[i][j] = 0; } else { R[i][j] = G[i - m][j - n]; } } } } System.out.print("Matrica e formuar"); System.out.print("\n"); for (i = 0;i < m + l;i++) { for (j = 0;j < n + k;j++) { System.out.printf("%4d", R[i][j]); } System.out.printf("\n"); } } } Astrit Hulaj 32 Rezultati Matrica e formuar: 4 7 3 5 -2 3 9 2 8 -4 2 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2 4 6 -9 0 0 0 9 8 1 4 0 0 0 1 3 7 2 Shembull 1.18. Te shkruhet kodi i cili na mundëson gjetjen e vlerës maksimale në një grup prej n numrave të plotë. Kodi Metoda e parë përmes loop-es for. // Java Program to find maximum in arr[] public class Max_Nr { public static int arr[] = {10, 324, 45, 90, 9808}; // Method to find maximum in arr[] static int nr_ma_i_madh() { int i; // Initialize maximum element int max = arr[0]; // Traverse array elements from second and // compare every element with current max for (i = 1; i < arr.length; i++) if (arr[i] > max) max = arr[i]; return max; } // Driver method public static void main(String[] args) { long startTime = System.nanoTime(); Astrit Hulaj 33 System.out.println("Numri me i madh i dhene ne varg eshte = " + nr_ma_i_madh()); long endTime = System.nanoTime(); long timeElapsed = endTime - startTime; System.out.println("Koha e ekzekutimit ne nano sekonda: " + timeElapsed); } } Rezultati Numri me i madh i dhene ne varg eshte = 9808 Koha e ekzekutimit ne nano sekonda: 18152700 Kodi Metoda e dytë // Java Program to find maximum in arr[] import java.util.Arrays; public class Max_Nr1 { public static void main(String[] args){ long startTime = System.nanoTime(); int arr[] = {10, 324, 45, 90, 9808}; int max = Arrays.stream(arr).max().getAsInt(); System.out.println("Largest in given array is " +max); long endTime = System.nanoTime(); long timeElapsed = endTime - startTime; System.out.println("Koha e ekzekutimit ne nano sekonda: " + timeElapsed); } } Rezultati Numri me i madh i dhene ne varg eshte = 9808 Koha e ekzekutimit ne nano sekonda: 47479200 Kodi Metoda 3: Aplikimi i sortimit // Java program to find maximum in // arr[] of size n import java .io.*; Astrit Hulaj 34 import java.util.*; class Max_Nr2 { // returns maximum in arr[] of size n static int nr_ma_i_madh(int []arr, int n) { Arrays.sort(arr); return arr[n - 1]; } // Driver code static public void main (String[] args) { long startTime = System.nanoTime(); int []arr = {10, 324, 45, 90, 9808}; int n = arr.length; System.out.println("Numri ma i madh ne varg eshte:" +nr_ma_i_madh(arr, n)); long endTime = System.nanoTime(); long timeElapsed = endTime - startTime; System.out.println("Koha e ekzekutimit ne nano sekonda: " + timeElapsed); } } Rezultati Numri ma i madh ne varg eshte: 9808 Koha e ekzekutimit ne nano sekonda: 21293500 Shembull 1.19. Gjeni elementin maksimal në një grup i cili fillimisht rritet dhe pastaj zvogëlohet? Duke pasur parasysh një grup integrimesh që fillimisht rritet dhe më pas zvogëlohet, gjeni vlerën maksimale në grup? Hyrja: arr [] = {8, 10, 20, 80, 100, 200, 400, 500, 3, 2, 1} Dalja: 500 Hyrja: arr [] = {1, 3, 50, 10, 9, 7, 6} Dalja: 50 Rasti i qoshes (Pa pjesë në rënie) Astrit Hulaj 35 Hyrja: arr [] = {10, 20, 30, 40, 50} Dalja: 50 Rasti i qoshes (Pa pjesë në rritje) Hyrja: arr [] = {120, 100, 80, 20, 0} Dalja: 120 Kodi // java program to find maximum // element class Main { // function to find the // maximum element static int findMaximum(int arr[], int low, int high) { int max = arr[low]; int i; for (i = low; i <= high; i++) { if (arr[i] > max) max = arr[i]; } return max; } // main function public static void main (String[] args) { int arr[] = {1, 30, 40, 50, 60, 70, 23, 20}; int n = arr.length; System.out.println("The maximum element is "+ findMaximum(arr, 0, n-1)); } } Rezultati The maximum element is 70 Astrit Hulaj 36 Shembull 1.20. Në vazhdim do të paraqesim metodën se si mund të kalkulojmë në Java kohën e ekzekutimit Runtime. Koha e ekzekutimit mund të merret nga metoda getRuntime. Metodat për Runtime: public static Runtime getRuntime (): Kjo metodë kthen shembullin ose objektin Runtime të shoqëruar me aplikacionin aktual Java. Kodi // Java program to illustrate getRuntime() // method of Runtime class public class Memory { public static void main(String[] args) { // get the current runtime assosiated with this process Runtime run = Runtime.getRuntime(); // print the current free memory for this runtime System.out.println("Free memory for this runtime: " + run.freeMemory()); } } Rezultati Free memory for this runtime: 133169152 Metoda 2 2) public long freeMemory(): Kjo metodë kthen sasinë e kujtesës së lirë në JVM (Java Virtual Machine) // Java program to illustrate freeMemory() // method of Runtime class public class FreeMemory { public static void main(String[] args) { // print the number of free bytes System.out.println("" + Runtime.getRuntime().freeMemory()); } } Astrit Hulaj 37 Shembull 1.21. public long totalMemory() : Kjo metodë kthen sasinë e kujtesës totale në JVM (Java Virtual Machine) // Java program to illustrate totalMemory() // method of Runtime class public class TotalMemory { public static void main(String[] args) { // print the number of total bytes System.out.println("" + Runtime.getRuntime().totalMemory()); } } Shembull 1.22. // Java program to illustrate availableProcessors() // method of Runtime class public class Procesor { public static void main(String[] args) { // check the number of processors available System.out.println("" + Runtime.getRuntime() .availableProcessors()); } } Shembull 1.23. public long maxMemory (): Kjo metodë kthen sasinë maksimale të memorjes që makina virtuale Java do të përpiqet të përdorë. // Java program to illustrate maxMemory() // method of Runtime class public class MaxMemory { public static void main(String[] args) { // print the maximum memory System.out.println("" + Runtime.getRuntime().maxMemory()); } } Astrit Hulaj 38 Kapitulli 2 2. Algoritmet e kërkimit Ekzistojnë disa lloje të Algoritmeve të kërkimit si: Linear Search Algorithm Binary Search Algorithm Jump Search Algorithm Interpolation Search Algorith Exponential Search Algorith 2.1 Algoritmi linear i kërkimit Kërkimi linear është një algoritëm shumë i thjeshtë i kërkimit. Në këtë lloj kërkimi, bëhet një kërkim vijues mbi të gjitha elementet një nga një. Çdo element kontrollohet dhe krahasohet një nga një dhe nëse konstatohet se elementi i veçantë përputhet me ndonjërin nga elementet e vargut, atëherë elementi i veçantë kthehet, përndryshe kërkimi vazhdon deri në fund të vargut të elementeve. Në figurën 1 është paraqitur në formë skematike se si realizohet kerkimi linear. Figura 1. Kërkimi linear Ky algoritem i kërkimit karakterizohet me një vones të konsiderueshme sepse ky algoritëm duhet të bëjë krahasimin se elementit të kërkuar me secilin element në varg. Andaj, ky algoritem rrall përdoret në praktikë sepse algoritmet tjera të kërkimit, si p.sh ai binary ose hash tabelat lejojnë kërkim më të shpejtë krahasuar me kërkimin linear. Analiza e Kërkimit Linear Rasti më i keq është nëse elementi nuk është gjetur ose është gjetur në fund të kërkimit në të cilin rast ka n krahasime. Rasti më i mirë është nëse ajo që kërkohet është në vendin e parë dhe kështu që ka vetëm një krahasim. Andaj, mund të themi: Astrit Hulaj 39 rasti më i mirë është 1 krahasim rasti më i keq është n krahasime Rasti mesatar për kërkimin linear Një supozim i thjeshtë mund të jetë marrja e mesatares së më të mirës dhe më të keqes, duke marrë (n + 1) / 2. Kjo përgjigje rezulton e saktë, por ne duhet ta nxjerrim atë në mënyrë më metodike. Para së gjithash, ne duhet të bëjmë supozimin se kërkimi është i suksesshëm. Le te marrim parasysh një grup me madhësi 10, i cili grup le të përmbajë numra të plotë arbitrar. Atëherë, edhe çelësi do të jetë një numër i plotë arbitrar. Duke qenë se ekzistojnë rreth 4 miliardë integrime 32bitëshe, probabiliteti që çelësi ynë të jetë njëri prej këtyre është efektivisht zero! Përveç kësaj, ne do të supozojmë se çelësi ka të ngjarë të gjendet në secilën prej pozicioneve n. Duke përdorur këtë nocion, kostoja mesatare është: (kostoja totale për gjetjet në të gjitha pozicionet) / numri i pozicioneve Kostoja për gjetjen në pozicionin i është (i + 1), për vlerat i = 0 ... n-1. Prandaj ne nxjerrim: Kostoja mesatare = Problemi: Në një varg të dhënë arr[] me n elementeve, shkruaj një funksion për të kërkuar një element x në arr[]. Shembull 2.1. Hyrja: arr[] = {10, 20, 80, 30, 60, 50, 110, 100, 130, 170} Anëtari që kërkojmë: x = 110; Rezultati: Elementi x gjendet në indeksin 6 Bllok diagrami për kërkim linear Astrit Hulaj 40 Shembull 2.2. Të gjindet një vlerë e caktuar në varg. Një form tjetër e bllok diagramit për kërkim të një vlere në varg. Sta rt Arr[], i=1,n X i=1 Po X=imput[i] Jo i=i+1 Po i <=input.length Jo Elementi nuk eshte gjetur Shtype vleren End Astrit Hulaj 41 Kodi public class LinearSearch { public static void search(int input[], int x){ for (int i = 0; i <input.length; i++) { if(x==input[i]) { System.out.println("Elementi " + x + " eshte gjetur ne varg dhe ka indeksin = " + i); return; } } //Permes rreshtit te me poshtem tregojme qe elementi nuk eshte gjetur System.out.println("Elementi " + x + " nuk eshte gjetur ne varg"); } public static void main(String[] args) { int input [] = {20, 30, 40, 10, 5, 2, 60, 73}; int x = 10; search(input, x); x = 60; search(input, x); x = 9; search(input, x); } } Rezultati Elementi 10 eshte gjetur ne varg dhe ka indeksin = 3 Elementi 60 eshte gjetur ne varg dhe ka indeksin = 6 Elementi 9 nuk eshte gjetur ne varg Shembull 2.3. Shembull për gjetjen e gjatësisë së vargut dhe vlerës së kërkuar. public class LinearSearch1 { public static int Search(int x, int arr[]) { Astrit Hulaj 42 for (int i = 0; i < arr.length; i++) { int y = arr[i]; if (x == y) return i; } return Integer.MAX_VALUE; } public static void main(String[] args) { int varg[]= {1,2,3,4,5,6,7,8,8,8,9,9,9,10,11}; //the element that should be found int nr_i_kerkuar = 9; int Index = LinearSearch1.Search(nr_i_kerkuar, varg); System.out.println(String.format("Numri i kerkuar: %d\n Numri i kerkuar %d eshte ne indeksin= %d\n Gjatsia e vargut eshte= %d\n", nr_i_kerkuar, varg[Index], Index, varg.length)); } } Rezultati Numri i kerkuar: 9 Numri i kerkuar 9 eshte ne indeksin= 10 Gjatsia e vargut eshte= 15 Shembull 2.4. Te shkruhet kodi i cili mundëson gjetjen e një vlere të caktuar në një varg (pozicioni i tij), si dhe të definohet numri i tentativave për gjetje të asaj vlere. import java.io.*; public class Linear { public static void search(int arr[], int search_Element) { int left = 0; int length = arr.length; int right = length - 1; int position = -1; // run loop from 0 to right Astrit Hulaj 43 for (left = 0; left <= right;) { // if search_element is found with left varaible if (arr[left] == search_Element) { position = left; System.out.println( "Elementi u gjet në Array në " + (position + 1) + " Pozicion me " + (left + 1) + " Tentative"); break; } // if search_element is found with right varaible if (arr[right] == search_Element) { position = right; System.out.println( "Elementi u gjet ne Array ne Pozicionin " + (position + 1) + " me " + (length - right) + " Tentative "); break; } left++; right--; } // if element not found if (position == -1) System.out.println("Elementi nuk eshte gjetur ne varg me " + left + " Tentative"); } // Driver code public static void main(String[] args) { long startTime = System.nanoTime(); int arr[] = { 20, 35, 37, 40, 45, 50, 51, 55, 67 }; int element = 50; Astrit Hulaj 44 // Function call search(arr,element); long endTime = System.nanoTime(); long koha = endTime - startTime; System.out.println("Koha e ekzekutimit ne nano sekonda: " + koha); } } Rezultati Elementi u gjet ne Array ne Pozicionin 6 me 4 Tentative Koha e ekzekutimit ne nano sekonda: 39 Metoda 2 import java.io.*; public class Linear { public static int search(int arr[], int x) { int n = arr.length; for (int i = 0; i < n; i++) { if (arr[i] == x) return i; } return -1; } // Driver code public static void main(String args[]) { long startTime = System.nanoTime(); int arr[] = { 20, 35, 37, 40, 45, 50, 51, 55, 67 }; int x = 50; // Function call int result = search(arr, x); Astrit Hulaj 45 if (result == -1) System.out.print("Elementi nuk eshte prezent ne varg"); else System.out.println("Elementi eshte prezent ne poziten " + result); long endTime = System.nanoTime(); long koha = endTime - startTime; System.out.println("Koha e ekzekutimit ne nano sekonda: " + koha); } } Rezultati Elementi eshte prezent ne poziten 5 Koha e ekzekutimit ne nano sekonda: 394 Shembull 2.5. Gjetja e vlerave te ndryshme në varg public class Main { // Returns number of times x occurs in arr[0..n-1] public static int nurmro(int arr[], int n, int x) { int res = 0; for (int i=0; i<n; i++) if (x == arr[i]) res++; return res; } public static void main(String args[]) { int arr[] = {1, 2, 2, 2, 2, 2, 3, 4, 7 ,8 ,8 }; int n = arr.length; int a = 1; int x = 2; int b = 3; int c = 4; int d = 7; int e = 8; Astrit Hulaj 46 System.out.println("Numri nurmro(arr, n, a)); System.out.println("Numri nurmro(arr, n, x)); System.out.println("Numri nurmro(arr, n, b)); System.out.println("Numri nurmro(arr, n, c)); System.out.println("Numri nurmro(arr, n, d)); System.out.println("Numri nurmro(arr, n, e)); } } Rezultati Numri Numri Numri Numri Numri Numri i i i i i i vlerave vlerave vlerave vlerave vlerave vlerave 1 2 3 4 7 8 ne ne ne ne ne ne varg varg varg varg varg varg i vlerave 1 ne varg =" + i vlerave 2 ne varg =" + i vlerave 3 ne varg =" + i vlerave 4 ne varg =" + i vlerave 7 ne varg =" + i vlerave 8 ne varg =" + =1 =5 =1 =1 =1 =2 2.2 Algoritmi binar i kërkimit Bënë kërkimin e një grupi të renditur duke e ndarë intervalin e kërkimit vazhdimisht në gjysmë. Fillon me një interval që mbulon të gjithë vargun. Nëse vlera e çelësit të kërkimit është më e vogël se vlera e mesme e vargut, bën ngushtimin e intervalit të kërkimit në gjysmën e poshtme. Përndryshe fillon kërkimin duke ngushtuar intervalin e kërkimit në gjysmën e sipërme. Kontrollon vazhdimisht derisa vlera të gjendet ose intervali të jetë bosh. Algoritmi i Kërkimit Binar mund të zbatohet vetëm në vargjet e renditura. Pra, para aplikimit të algoritmit elementet duhet të renditen: Në rend rritës nëse elementët janë numra. Në rend të alfabetit nëse elementet janë vargje. Ideja e kërkimit binar është që të përdoret informacioni që grupi fillimisht është i renditur dhe pastaj te mundësoj kërkimin vetëm në një pjesë te intervalit duke ndikuar kështu në zvogëlimin e kohës së kërkimit. Në rast i kërkimit binar është paraqitur në fig. 2. Analiza e ndërlikueshmërisë së kohës së kërkimit binar bëhet si më poshtë: Në çdo përsëritje ose në çdo thirrje rekursive, kërkimi zvogëlohet në gjysmën e grupit. Pra, për n elementë në grup, ka përsëritje log2n ose thirrje rekursive. Astrit Hulaj 47 Figura 2. Kërkimi binar. Sipas kërkimit binar gjysma e elementeve injorohet pas vetëm një krahasimi. Logjika e këtij algoritmi funksionon si në vijim. • Krahaso x me elementin e mesit. • Nëse x është elementi i mesit, ktheje indeksin e tij. • Nëse x është më i madh se elementi i mesit, atëherë x mund të jetë vetëm në të djathtë të nën vargut pas elementit të mesit. Andaj vazhdojmë në të djathtë. • Nëse x është më i vogël, vazhdojmë në të majtë. Kjo procedurë vazhdon edhe në pjesën e rreshtit pas kërkimit të parë. Shembull 2.6. Le te shikojmë funksionimin e algoritmit binary përmes një shembulli. Le të marrim renditjen lineare si në vijim. Te gjendet elementi 15 duhet përdorur kërkimin binary. Zgjidhje Algoritmi i kërkimit binar punon në hapat e mëposhtëm: Hapi-1: Për të filluar, marrim fillimi = 0 dhe fundi = 6. Ne llogarisim vendndodhjen e elementit të mesëm si: Mesi i vargut = (fillimi + fundi) / 2 = (0 + 6) / 2 = 3 Këtu, a [Mesi i vargut] = a [3] = 20 ≠ 15 dhe fillimi <fundi. Pra, fillojmë me përsëritjen tjetër. Hapi-2: Astrit Hulaj 48 Pra [Mesi i vargut] = 20> 15, kështu që ne marrim fundi = Mesi i vargut - 1 = 3 - 1 = 2, ndërsa fillimi mbetet e pandryshuar. Ne llogarisim vendndodhjen e elementit të mesëm si: Mesi i vargut = (fillimi + fundi) / 2 = (0 + 2) / 2 = 1 Këtu, a [Mesi i vargut] = a [1] = 10 ≠ 15 dhe fillimi < fundi. Pra, fillojmë me përsëritjen tjetër. Hapi-3: Meqenëse a [Mesi i vargut] = 10 <15, kështu që ne marrim fillimi = Mesi i vargut + 1 = 1 + 1 = 2 ndërsa fundi mbetet i pandryshuar. Ne llogarisim vendndodhjen e elementit të mesëm si: Mesi i vargut = (fillimi + fundi) / 2 = (2 + 2) / 2 = 2 Këtu, a [Mesi i vargut] = a [2] = 15 që përputhet me elementin që kërkohet. Pra, kërkimi ynë përfundon me sukses dhe indeksi 2 kthehet. Shembull 2.7. Duke pasur parasysh një grup të renditur të elementeve N, atëherë mesatarisht secili element do merr (1 + logN) / 2 për tu gjetur me sukses. Sidoqoftë, kjo formulë nuk merr parasysh fakti që secili element në grup kërkon numër të ndryshëm të përsëritjeve në kërkimin binar para se të gjendet. Le te marrim renditjen e mëposhtme të 15 elementeve: Siç tregohet në përkufizimin e metodës binarySearch () në çdo përsëritje vlera e mesit është i azhurnuar (Vlera e mesit = (i ulët + i lartë) / 2). Elementi në pozicionin 7, për shembull, gjithmonë merr një përsëritje të vetme për tu gjetur. Nga ana tjetër, të dhënat në pozicionin 14 marrin 4 përsëritje sipas kërkimit binar për tu gjendur. Figura 2 tregon një pemë binare që ilustron katër rastet e kërkimit binar, ku secili rast merr një numër të ndryshëm përsëritjesh. Për shembull, elementet në pozicionet 1, 5, 9 dhe 13 secili merr tre përsëritje para se të gjenden, ndërsa elementet në pozicionet 3 dhe 11 secili kërkon vetëm dy përsëritje për t'u gjetur. Astrit Hulaj 49 Tabela 1 përmbledh elementet e grupit dhe numrin përkatës të përsëritjeve që ato mund të gjenden. Shembull 2.8. Merrni parasysh algoritmin e kërkimit binar për gjetjen e një të dhënë vlera brenda një grupi të renditur sipas vlerës nga më e ulëta tek më e larta. Kërkimi binar fillimisht shikon elementin e mesit dhe përcakton nëse vlera që kërkohet është në gjysmën e sipërme apo gjysmën e poshtme të grupit. Algoritmi pastaj vazhdon të ndajë nëngrupin e duhur në gjysmë derisa të gjendet vlera e dëshiruar. Sa herë mund një grup me madhësi n të ndahet në gjysmë derisa të mbetet vetëm një element në nën-grupin përfundimtar? Përgjigja është log2n herë. Bllok diagrami për kërkim binar: Astrit Hulaj 50 Kodi Metoda 1 // Java implementation of recursive Binary Search class BinarySearch { // Returns index of x if it is present in arr[l.. // r], else return -1 int binarySearch(int arr[], int l, int r, int x) { if (r >= l) { int mid = l + (r - l) / 2; // If the element is present at the // middle itself if (arr[mid] == x) return mid; // If element is smaller than mid, then // it can only be present in left subarray if (arr[mid] > x) return binarySearch(arr, l, mid - 1, x); // Else the element can only be present // in right subarray return binarySearch(arr, mid + 1, r, x); } // We reach here when element is not present // in array return -1; } // Driver method to test above public static void main(String args[]) { long startTime = System.nanoTime(); BinarySearch ob = new BinarySearch(); int arr[] = { 2, 3, 4, 10, 40 }; int n = arr.length; int x = 10; int result = ob.binarySearch(arr, 0, n - 1, x); if (result == -1) System.out.println("Elementi nuk eshte i Astrit Hulaj 51 pranishem"); else System.out.println("Elementi gjidet ne poziten = " + result); long endTime = System.nanoTime(); long koha = endTime - startTime; System.out.println("Koha e ekzekutimit ne nano sekonda: " + koha); } } Rezultati Elementi gjidet ne poziten = 3 Koha e ekzekutimit ne nano sekonda: 395 Metoda 2 // Java implementation of recursive Binary Search class BinarySearch { // Returns index of x if it is present in arr[], // else return -1 int binarySearch(int arr[], int x) { int l = 0, r = arr.length - 1; while (l <= r) { int m = l + (r - l) / 2; // Check if x is present at mid if (arr[m] == x) return m; // If x greater, ignore left half if (arr[m] < x) l = m + 1; // If x is smaller, ignore right half else r = m - 1; } // if we reach here, then element was // not present Astrit Hulaj 52 return -1; } // Driver method to test above public static void main(String args[]) { BinarySearch ob = new BinarySearch(); int arr[] = { 2, 3, 4, 10, 40 }; int n = arr.length; int x = 10; int result = ob.binarySearch(arr, x); if (result == -1) System.out.println("Elementi nuk eshte i pranishem"); else System.out.println("Elementi gjidet ne poziten = " + result); long startTime = System.nanoTime(); long endTime = System.nanoTime(); long koha = endTime - startTime; System.out.println("Koha e ekzekutimit ne nano sekonda: " + koha); } } Rezultati Elementi gjidet ne poziten = 3 Koha e ekzekutimit ne nano sekonda: 395 Shembull 2.9. Te shkruhet kodi i cili gjenë sa herë është përsëritur vlera e cila kërkohet? Gjithashtu të llogaritet koha e ekzekutimit në nano sekonda? public class Main { // Returns number of times x occurs in arr[0..n-1] public static int numro(int arr[], int n, int x) { // long startTime = System.nanoTime(); int res = 0; for (int i=0; i<n; i++) if (x == arr[i]) Astrit Hulaj 53 res++; return res; } public static void main(String args[]) { long startTime = System.nanoTime(); int arr[] = {1, 2, 2, 2, 2, 2, 3, 4, 7 ,8 int n = arr.length; int x = 2; int y = 8; System.out.println("Numri total i vlerave numro(arr, n, x)); System.out.println("Numri total i vlerave numro(arr, n, y)); long endTime = System.nanoTime(); long timeElapsed = endTime - startTime; System.out.println("Koha e ekzekutimit ne " + timeElapsed +" nano "); ,8 }; te njejta:" + te njejta:" + nano sekonda: } } Rezultati Numri total i vlerave te njejta:5 Numri total i vlerave te njejta:2 Koha e ekzekutimit ne nano sekonda: 20042201 nano Shembull 2.10. Te shkruhet kodi i cili gjenë poziten (indeksin) e vlerës e cila kërkohet? Gjithashtu të llogaritet koha e ekzekutimit në nano sekonda? public class PeakElement { // A binary search based function that returns index of a peak // element public static int findPeak1(int arr[], int low, int high, int n) { // Gjetja e vleres se mesme Astrit Hulaj 54 int mid = low + (high - low)/2; /* (low + high)/2 */ // krahasimi i elementit te mesem me fqinjet e tij nese ata ekzistojne if ((mid == 0 || arr[mid-1] <= arr[mid]) && (mid == n-1 || arr[mid+1] <= arr[mid])) return mid; // If middle element is not peak and its left neighbor is // greater than it,then left half must have a peak element else if (mid > 0 && arr[mid-1] > arr[mid]) return findPeak1(arr, low, (mid -1), n); // If middle element is not peak and its right neighbor // is greater than it, then right half must have a peak // element else return findPeak1(arr, (mid + 1), high, n); } // A wrapper over recursive function findPeakUtil() static int findPeak(int arr[], int n) { return findPeak1(arr, 0, n-1, n); } // Driver method public static void main (String[] args) { long startTime = System.nanoTime(); int arr[] = {1, 3, 20, 4, 1, 0}; int n = arr.length; System.out.println("Pozita apo indeksi i vleres me te madhe = " + findPeak(arr, n)); long endTime = System.nanoTime(); long timeElapsed = endTime - startTime; System.out.println("Koha e ekzekutimit ne nano sekonda: " + timeElapsed +" nano"); } } Rezultati Astrit Hulaj 55 Pozita apo indeksi i vleres me te madhe = 2 Koha e ekzekutimit ne nano sekonda: 19412600 nano Shembull 2.11. Te shkruhet kodi i cili gjenë sa herë është përsëritur vlera e cila kërkohet në një varg? Kodi public class Gjetjaevleravetenjejta { // A recursive binary search // function. It returns location // of x in given array arr[l..r] // is present, otherwise -1 static int binarySearch(int arr[], int l, int r, int x) { if (r < l) return -1; int mid = l + (r - l) / 2; // If the element is present // at the middle itself if (arr[mid] == x) return mid; // // // if If element is smaller than mid, then it can only be present in left subarray (arr[mid] > x) return binarySearch(arr, l,mid - 1, x); // Else the element can // only be present in // right subarray return binarySearch(arr, mid + 1, r, x); } // Returns number of times x // occurs in arr[0..n-1] public static int veratenjejta(int arr[],int n, int x) { int ind = binarySearch(arr, 0, n - 1, x); Astrit Hulaj 56 // If element is not present if (ind == -1) return 0; // Count elements on left side. int count = 1; int left = ind - 1; while (left >= 0 && arr[left] == x) { count++; left--; } // Count elements // on right side. int right = ind + 1; while (right < n && arr[right] == x) { count++; right++; } return count; } // Driver code public static void main(String[] args) { int arr[] = {1, 2, 2, 2, 2, 3, 4, 7, 8, 8}; int n = arr.length; int x = 2; System.out.print(""Numri i kerkuar perseritet = " + veratenjejta(arr, n, x)); } } Rezultati Numri i kerkuar perseritet = 4 Shembull 2.12. Te shkruhet kodi i cili gjenë poziten (indeksin) e vlerës e cila kërkohet? Astrit Hulaj 57 public class Main1 { /* Function to get index of ceiling of x in arr[low..high] */ public static int vlera_e_pozites(int arr[], int low, int high, int x) { int i; /* If x is smaller than or equal to first element,then return the first element */ if(x <= arr[low]) return low; /* Otherwise, linearly search for ceil value */ for(i = low; i < high; i++) { if(arr[i] == x) return i; /* if x lies between arr[i] and arr[i+1] including arr[i+1], then return arr[i+1] */ if(arr[i] < x && arr[i+1] >= x) return i+1; } /* If we reach here then x is greater than the last element of the array, return -1 in this case */ return -1; } /* Driver program to check above functions */ public static void main (String[] args) { int arr[] = {1, 2, 8, 10, 10, 12, 19}; int n = arr.length; int x = 3; int index = vlera_e_pozites(arr, 0, n-1, x); if(index == -1) System.out.println("Vlera e pozites "+x+" nuk ekziston n varg"); else System.out.println("Vlera e pozites "+x+" eshte "+arr[index]); Astrit Hulaj 58 } } Rezultati Vlera e pozites 3 eshte 8 Astrit Hulaj 59