come calcolare la complessità della ricerca binaria


144

Ho sentito qualcuno dire che poiché la ricerca binaria dimezza l'input richiesto per la ricerca, quindi è l'algoritmo log (n). Poiché non provengo da un background matematico, non sono in grado di relazionarmi con esso. Qualcuno può spiegarlo in modo un po 'più dettagliato? deve fare qualcosa con la serie logaritmica?


1
Questo potrebbe aiutare a: stackoverflow.com/a/13093274/550393
2cupsOfTech

Risposte:


385

Ecco un modo più matematico di vederlo, anche se non molto complicato. IMO molto più chiaro di quelli informali:

La domanda è: quante volte puoi dividere N per 2 finché non hai 1? Questo in sostanza sta dicendo: fai una ricerca binaria (metà degli elementi) fino a quando non l'hai trovata. In una formula questo sarebbe questo:

1 = N / 2 x

moltiplicare per 2 x :

2 x = N

ora fai il registro 2 :

log 2 (2 x ) = log 2 N
x * log 2 (2) = log 2 N
x * 1 = log 2 N

questo significa che puoi dividere il registro N volte fino a quando non hai tutto diviso. Ciò significa che devi dividere il registro N ("fai il passo della ricerca binaria") finché non trovi il tuo elemento.


l'ho appena calcolato in t (n) = (2 ^ 2) * K. come farlo accedere al modulo?
Shan Khan,

1
lo stesso concetto spiegato graficamente: stackoverflow.com/a/13093274/550393
2cupsOfTech

La parte che mi manca è, se hai un BST con 7 voci, qual è la sua formula? log2 (7)? Ho fatto un calcolo della forza bruta con ogni possibile risultato e sono arrivato a una risposta che non era uguale a log2 (7), quindi cosa sto facendo di sbagliato?
Perry Monschau,

1
Molto più facile della spiegazione dell'albero binario.
NoName

1
Risposta molto bella
VHS

22

Per Ricerca binaria, T (N) = T (N / 2) + O (1) // la relazione di ricorrenza

Applicare il teorema dei master per il calcolo Complessità runtime delle relazioni di ricorrenza: T (N) = aT (N / b) + f (N)

Qui, a = 1, b = 2 => log (a base b) = 1

inoltre, qui f (N) = n ^ c log ^ k (n) // k = 0 & c = log (a base b)

Quindi, T (N) = O (N ^ c log ^ (k + 1) N) = O (log (N))

Fonte: http://en.wikipedia.org/wiki/Master_theorem


1
perché log (a base b) è 1 quando a = 1 eb = 2, non dovrebbe essere 0?
GAURANG VYAS,

16

T (n) = T (n / 2) +1

T (n / 2) = T (n / 4) + 1 + 1

Metti il ​​valore di The (n / 2) sopra così T (n) = T (n / 4) + 1 + 1. . . . T (n / 2 ^ k) + 1 + 1 + 1 + 1 .....

= T (2 ^ k / 2 ^ k) + 1 + 1 .... + 1 fino a k

= T (1) + k

Come abbiamo preso 2 ^ k = n

K = registro n

Quindi la complessità temporale è O (log n)


10

Non metà tempo di ricerca, questo non lo renderebbe log (n). Lo diminuisce logaritmicamente. Pensaci un attimo. Se avessi 128 voci in una tabella e dovessi cercare linearmente il tuo valore, probabilmente occorrerebbero in media 64 voci per trovare il tuo valore. Questo è n / 2 o tempo lineare. Con una ricerca binaria, si eliminano 1/2 voci possibili per ogni iterazione, in modo tale che al massimo occorrerebbero solo 7 confronti per trovare il proprio valore (la base di registro 2 di 128 è 7 o 2 alla potenza di 7 è 128.) Questo è il potere della ricerca binaria.


Ci scusiamo per il necropost ma 128 non è un albero uniformemente compilato. Ho usato un esempio di base per aggirare il problema e ho scoperto che 7 voci riempiono uniformemente un albero con 3 strati. Ho calcolato che la complessità dovrebbe essere 17/7 (la media della somma totale dei confronti) che è 2,43. Ma log2 (7) è 2,81. Quindi cosa mi sto perdendo qui?
Perry Monschau,

Due risposte - La prima qui: anche se non ci sono errori in matematica, possiamo vedere che la media 2.43 è ancora migliore della media 3.5 per lineare, e questo ha un valore basso. Una volta entrati nelle centinaia di voci, log2 () è molto meglio di lineare. Penso che tu lo veda, quindi al prossimo.
Michael Dorgan,

1
Seconda risposta: non sono sicuro del tipo di albero in cui 7 ha compilato tutto. Quando penso a un albero perfetto di 8 voci, vedo un albero profondo a 3 livelli con 8 foglie totali. In questo albero, indipendentemente dal numero che cerchi, sono necessari 3 confronti totali per passare da radice a foglia. Per 7 voci, uno dei percorsi richiederebbe un confronto in meno quindi 20/7 (6 nodi di 3 confronti, 1 nodo di 2 confronti) che è ~ 2,85. Log2 (7) è ~ 2,81. Non ho le basi matematiche per spiegare la differenza .04, ma immagino che abbia a che fare con il fatto di non avere parti frazionarie disponibili o altra magia :)
Michael Dorgan,

il numero è il numero di foglie !? Non è il numero di nodi? Beh, quella era una grande informazione che mi mancava. Mi sembra strano che la funzione si basi sulle foglie, quando ogni nodo ramificato è anche un potenziale punto di arresto. Bene comunque, grazie per avermi risolto!
Perry Monschau,

5

La complessità temporale dell'algoritmo di ricerca binaria appartiene alla classe O (log n). Questo si chiama notazione O grande . Il modo in cui dovresti interpretarlo è che la crescita asintotica del tempo impiegato dalla funzione per eseguire un dato set di dimensioni n non supererà log n.

Questo è solo un linguaggio matematico formale per essere in grado di provare affermazioni, ecc. Ha una spiegazione molto semplice. Quando n diventa molto grande, la funzione log n supererà il tempo necessario per eseguire la funzione. La dimensione del "set di input", n, è solo la lunghezza dell'elenco.

In poche parole, il motivo per cui la ricerca binaria è in O (log n) è che dimezza l'input impostato in ogni iterazione. È più facile pensarci nella situazione opposta. Su x iterazioni, per quanto tempo può esaminare l'algoritmo di ricerca binaria al massimo? La risposta è 2 ^ x. Da questo possiamo vedere che il contrario è che in media l'algoritmo di ricerca binaria necessita di log2 n iterazioni per un elenco di lunghezza n.

Se è perché è O (log n) e non O (log2 n), è semplicemente perché si ripete - L'uso delle costanti della notazione O grande non conta.


4

Ecco la voce di Wikipedia

Se guardi al semplice approccio iterativo. Stai eliminando solo la metà degli elementi da cercare finché non trovi l'elemento che ti serve.

Ecco la spiegazione di come ci viene in mente la formula.

Diciamo che inizialmente hai N numero di elementi e poi quello che fai è ⌊ N / 2⌋ come primo tentativo. Dove N è la somma del limite inferiore e del limite superiore. Il primo valore di N sarebbe uguale a (L + H), dove L è il primo indice (0) e H è l'ultimo indice dell'elenco che stai cercando. Se sei fortunato, l'elemento che cerchi di trovare sarà nel mezzo [ad es. Stai cercando 18 nell'elenco {16, 17, 18, 19, 20} quindi calcoli ⌊ (0 + 4) / 2⌋ = 2 dove 0 è il limite inferiore (L - indice del primo elemento dell'array) e 4 è il limite superiore (H - indice dell'ultimo elemento dell'array). Nel caso precedente L = 0 e H = 4. Ora 2 è l'indice dell'elemento 18 che stai cercando. Bingo! L'hai trovato.

Se il caso fosse un array diverso {15,16,17,18,19} ma stavi ancora cercando 18, non saresti fortunato e faresti il ​​primo N / 2 (che è ⌊ (0 + 4) / 2⌋ = 2 e poi rendi conto che l'elemento 17 nell'indice 2 non è il numero che stai cercando. Ora sai che non devi cercare almeno metà dell'array nel tuo prossimo tentativo di ricerca in modo iterativo. lo sforzo di ricerca è dimezzato, quindi in pratica non si cerca metà dell'elenco di elementi cercati in precedenza, ogni volta che si tenta di trovare l'elemento che non è stato possibile trovare nel tentativo precedente.

Quindi il caso peggiore sarebbe

[N] / 2 + [(N / 2)] / 2 + [((N / 2) / 2)] / 2 .....
ovvero:
N / 2 1 + N / 2 2 + N / 2 3 + ..... + N / 2 x … ..

fino a quando ... non hai terminato la ricerca, dove l'elemento che stai cercando di trovare si trova alla fine dell'elenco.

Ciò mostra il caso peggiore quando si raggiunge N / 2 x dove x è tale che 2 x = N

In altri casi N / 2 x dove x è tale che 2 x <N Il valore minimo di x può essere 1, che è il caso migliore.

Ora dal momento matematicamente peggiore è quando il valore di
2 x = N
=> log 2 (2 x ) = log 2 (N)
=> x * log 2 (2) = log 2 (N)
=> x * 1 = log 2 (N)
=> Più formalmente ⌊log 2 (N) + 1⌋


1
Come si ottiene esattamente la versione più formale?
Kalle,

Viene utilizzata una funzione da pavimento. I dettagli si trovano nella sezione delle prestazioni del collegamento wiki ( en.wikipedia.org/wiki/Binary_search_algorithm ) fornito nella risposta.
RajKon


2

Diciamo che l'iterazione in Ricerca binaria termina dopo k iterazioni. Ad ogni iterazione, l'array viene diviso per metà. Quindi supponiamo che la lunghezza dell'array in ogni iterazione sia n In Iterazione 1,

Length of array = n

Alla Iterazione 2,

Length of array = n⁄2

All'iterazione 3,

Length of array = (n⁄2)⁄2 = n⁄22

Pertanto, dopo Iterazione k,

Length of array = n⁄2k

Inoltre, sappiamo che dopo le divisioni After k, la lunghezza dell'array diventa 1 Pertanto

Length of array = n⁄2k = 1
=> n = 2k

Applicazione della funzione di registro su entrambi i lati:

=> log2 (n) = log2 (2k)
=> log2 (n) = k log2 (2)
As (loga (a) = 1)

Perciò,

As (loga (a) = 1)
k = log2 (n)

Quindi la complessità temporale della ricerca binaria è

log2 (n)

1

Una ricerca binaria funziona dividendo il problema a metà ripetutamente, qualcosa del genere (dettagli omessi):

Esempio di ricerca di 3 in [4,1,3,8,5]

  1. Ordina il tuo elenco di articoli [1,3,4,5,8]
  2. Guarda l'elemento centrale (4),
    • Se è quello che stai cercando, fermati
    • Se è maggiore, guarda la prima metà
    • Se è inferiore, guarda la seconda metà
  3. Ripetere il passaggio 2 con il nuovo elenco [1, 3], trovare 3 e interrompere

Si tratta di un bi ricerca -nary quando si divide il problema in 2.

La ricerca richiede solo i passaggi log2 (n) per trovare il valore corretto.

Consiglierei Introduzione agli algoritmi se vuoi conoscere la complessità algoritmica.


1

Dal momento che abbiamo ridotto un elenco a metà ogni volta, quindi abbiamo solo bisogno di sapere in quanti passaggi otteniamo 1 mentre continuiamo a dividere un elenco per due. Nel calcolo sotto indicato x indica il numero di volte in cui dividiamo un elenco fino a quando non otteniamo un elemento (Nel peggiore dei casi).

1 = N / 2x

2x = N

Prendendo log2

log2 (2x) = log2 (N)

x * log2 (2) = log2 (N)

x = log2 (N)


1

T (N) = T (N / 2) + 1

T (N) = T (N / 2) + 1 = (T (N / 4) + 1) + 1

...

T (N) = T (N / N) + (1 + 1 + 1 + ... + 1) = 1 + logN (base 2 log) = 1 + logN

Quindi la complessità temporale della ricerca binaria è O (logN)


0
ok see this
for(i=0;i<n;n=n/2)
{
i++;
}
1. Suppose at i=k the loop terminate. i.e. the loop execute k times.

2. at each iteration n is divided by half.

2.a n=n/2                   .... AT I=1
2.b n=(n/2)/2=n/(2^2)
2.c n=((n/2)/2)/2=n/(2^3)....... aT I=3
2.d n=(((n/2)/2)/2)/2=n/(2^4)

So at i=k , n=1 which is obtain by dividing n  2^k times
n=2^k
1=n/2^k 
k=log(N)  //base 2

0

Permettetemi di renderlo facile per tutti voi con un esempio.

Per semplicità, supponiamo che ci siano 32 elementi in una matrice nell'ordine ordinato da cui stiamo cercando un elemento usando la ricerca binaria.

1 2 3 4 5 6 ... 32

Supponiamo che stiamo cercando 32. dopo la prima iterazione, rimarremo con

17 18 19 20 .... 32

dopo la seconda iterazione, rimarremo con

25 26 27 28 .... 32

dopo la terza iterazione, rimarremo con

29 30 31 32

dopo la quarta iterazione, rimarremo con

31 32

Nella quinta iterazione, troveremo il valore 32.

Quindi, se lo convertiamo in un'equazione matematica, otterremo

(32 X (1/2 5 )) = 1

=> n X (2 -k ) = 1

=> (2 k ) = n

=> k log 2 2 = log 2 n

=> k = registro 2 n

Da qui la prova.


0

Ecco la soluzione che usa il teorema principale, con LaTeX leggibile.

Per ogni ricorrenza nella relazione di ricorrenza per la ricerca binaria, convertiamo il problema in un sottoproblema, con runtime T (N / 2). Perciò:

T (n) = T (n / 2) +1

Sostituendo il teorema principale, otteniamo:

T (n) = aT (n / b) + f (n)

Ora, poiché logbaè 0 e f (n) è 1, possiamo usare il secondo caso del teorema principale perché:

f (n) = O (1) = O (n0) = O (nlogba)

Ciò significa che:

T (n) = O (nlogbalogn) = O (n0logn) = O (logn)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.