Complessita' asintotica

di il
5 risposte

Complessita' asintotica

Scusate in classe (sono alle superiori) il prof ha spiegato questo in merito alla complessità asintotica :

Ricerca lineare: ricerca "classica" di un elemento in un vettore;
Ricerca dicotomica: parto da un array ordinato e procedo come spiegato( O(log2(n)). Notazioni O, Omega, Theta.

QUalcuno di buon cuore puo' aiutarmi a capire la ricerca dicotomica?
Grazie a tutti.

5 Risposte

  • Re: Complessita' asintotica

    La complessita asintotica si puo spiegare solo tramite esempi. Essendo alle superiori non devi preoccuparti di andare troppo nei dettagli, ma e' giusto sapere a grandi linee come funziona essendo uno strumento essenziale per calcolare l'efficienza di un algoritmo che stai scrivendo o che e' gia stato ideato e lo stai studiando.

    Esempio, una semplice ricerca lineare di un array A con n elementi :
    
    for(int i=0;i < A.length; ++i){
    	System.out.println(A[i]);
    }
    
    Questo ciclo avra complessita O(n) perche iteri n volte su un totale di n elementi nell'array A. E' importante escludere le costanti nel calcolo della complessita, esempio :
    
    for(int i=0;i < A.length; ++i){
    	System.out.println(A[i]);
    }
    
    for(int i=0;i < A.length; ++i){
    	System.out.println(A[i]);
    }
    
    Siccome svolgiamo lo stesso lavoro di prima saresti tentato a dire O(2n), ma nel calcolo totale escludiamo le costanti quindi sara sempre O(n).
    Se non conosci la dimensione totale degli arrays con cui hai a che fare, attenzione :
    
    for(int i=0;i < A.length; ++i){
    	System.out.println(A[i]);
    }
    
    for(int i=0;i < B.length; ++i){
    	System.out.println(B[i]);
    }
    
    Questo avra complessita O(a+b) supponendo che a e' la quantita di element in A e b la quantia di elementi in B. Se fossero annidati :
    
    for(int i=0;i < A.length; ++i){
    	System.out.println(A[i]);
    	for(int i=0;i < B.length; ++i){
    		System.out.println(B[i]);
    	}
    }
    
    La complessita diventerebbe O(ab). Le complessita del tipo O(logN) sono diverse, in particolare ricordati che nel calcolo della complessita asintotica di un algoritmo la base del logaritmo non ha significato, che sia 2, 3, 10, e' lo stesso. Per capirla puoi pensare al famoso algoritmo "binarySearch" che ha complessita O(logn).
    In binarySearch si cerca un elemento in un array ordinato :

    Obbiettivo : cerca x in {1,2,3,...,n} , chiamiamo l'array A

    funzione binarySearch(array, elementoDaTrovare)

    confronta con x con l'elemento in mezzo all'array (indice mid = A.length/2)
    se x == A[mid], abbiamo trovato x
    se x < A[mid] allora x sara per forza nel sub-array sinistro
    se x > A[mid] allora x sara per forza nel sub-array destro

    
    public int runBinarySearchIteratively(
      int[] sortedArray, int key, int low, int high) {
        int index = Integer.MAX_VALUE;
         
        while (low <= high) {
            int mid = (low + high) / 2;
            if (sortedArray[mid] < key) {
                low = mid + 1;
            } else if (sortedArray[mid] > key) {
                high = mid - 1;
            } else if (sortedArray[mid] == key) {
                index = mid;
                break;
            }
        }
        return index;
    }
    
    Il tempo totale rappresenta quindi quanti passi (quante volte divido A.length) dobbiamo fare affinche mid diventi 1, esempio con A.length = 16.

    N=16
    [diviso 2]N=8
    [diviso 2]N=4
    [diviso 2]N=2
    [diviso 2]N=1

    Ho diviso per 2 quattro volte quindi , 2^4 = 16 ma allora log16 = 4 quindi O(log16) quindi O(logn) dove n e' il nostro A.length.


    Questa spiegazione e' semplicistica ma ti da almeno un'idea di come funzioni la complessita. Se vuoi andare oltre ti consiglio di scaricarti (lo trovi anche gratis), "cracking the coding interview" di Gayle Laakmann McDowell.
  • Re: Complessita' asintotica

    Scusami credo che hai usato il linguaggio java, puoi spiegarmi con linguaggio c++?
    es.
    
    #include<iostream>
    using namespace std;
    
    int main()
    {
            int arr[10], i, num, n, cnt=0, pos;
            cout<<"\n Enter Array Size : ";
            cin>>n;
            cout<<"\n Enter Array Elements : \n";
            for(i=0; i<n; i++)
            {
                    cout<<" ";
                    cin>>arr[i];
            }
            cout<<"\n Enter Element to be Searched : ";
            cin>>num;
            for(i=0; i<n; i++)
            {
                    if(arr[i]==num)
                    {
                            cnt=1;
                            pos=i+1;
                            break;
                    }
            }
            if(cnt==0)
            {
                    cout<<"\n Element Not Found..!!";
            }
            else
            {
                    cout<<"\n Element "<<num<<" Found At Position "<<pos;
            }
            return 0;
    }
    
    QUesto fa una ricerca in un array in c++ (ma non binaria a questo punto)
    Da qui vorrei capire bene il resto.
    Ti ringrazio moltissimo.
  • Re: Complessita' asintotica

    Ciao mpg la sintassi non importa (java,c++...) basta che capisci l'algoritmo. Java ha una sinstassi molto intuitiva non dovresti avere problemi
  • Re: Complessita' asintotica

    In generale, la complessita' di analizza su algoritmi scritti in un linguaggio "procedura;e", alla C, per intenderci.
    Ma un linguaggio procedurale e' MOOOOLTO semplice:

    1) ci sono le varabili/vettori, raramente strutture dati piu' complesse come liste/alberi o grafi
    2) ci sono le strutture di controllo (sequenza - {}, ciclo - for/while/..., selezione - if/switch/...)
    3) ci sono le chiamate a funzione. Le "procedure" non si considerano, perche' le puoi vedere come funzioni "stupide"
    4) in piu' ci metti le quattro operazoni matematiche- +/-/*/div/.., logartimi ed esponenziali, e poco altro.

    Con questi 4 elementi, fai tutto!.
  • Re: Complessita' asintotica

    SCusami avrei trovato cosi' guardando qualcosa online , il concetto diciamo l'ho capito.
    
    #include <iostream>
    using namespace std;
    
    #define x 15
    #define N 5
    
    int main(){
    	int a[N]={1,5,8,10,15};
    	int i=0, j=N-1, m, pos=-1;
    
    	do { 
    		m=(i+j)/2;
    		if(a[m]==x)  
    			pos=i;
    		else if (a[m]<x)
    			i=m+1;
    		else
    			j=m-1;
    	} while(i<=j && pos==-1);	 ///?????
    
    	if(pos!=-1) ///?????
    		cout<<"numero trovato in posizione: "<<pos<<endl;
    	else 
    		cout<<"numero non trovato";
    	
    	return 0;
    }
    
    Non capisco bene quelle righe in cui metto i ??? e quel pos=-1.
Devi accedere o registrarti per scrivere nel forum
5 risposte