La difficoltà sta nella presenza dell'arrotondamento superiore, visto che stiamo calcolando un limite superiore.
Per avere una idea qualitativa, partiamo dal caso in modo da
non avere problemi di arrotondamento.
Se poniamo ad esempio la soluzione esatta è:
Sulle potenze di due, dunque, Questo suggerisce di tentare, nel caso generale, una ipotesi induttiva della forma Del termine si vede la necessità nel caso base, in quanto vogliamo che Questo fornisce il vincolo Per quanto riguarda il passo induttivo, sfruttando l'ipotesi induttiva otteniamo
Sappiamo che ha un comportamento logaritmico, dobbiamo però trovarne la forma esatta. Conviene tabulare qualche valore:
n T(n) 1 1 2 2 3 2 4 3 5 3 6 3 7 3 8 4
La funzione cambia in corrispondenza delle potenze di due, quindi fa certamente riferimento a Se facesse riferimento a scatterebbe infatti in corrispondenza delle potenze di due aumentate di uno.
Si vede facilmente che si tratta di dimostrarlo per induzione.
Base: nessun problema.
Passo induttivo: dobbiamo mostrare che
Meglio cambiare punto di vista: anziché esprimere in funzione di proviamo a fare l'inverso, esprimendo in funzione di Siccome non è iniettiva, è un insieme. Guardando ai valori tabulati, si capisce subito quale:
Ora, dalla proprietà dimostrata per induzione e dalla definizione di logaritmo segue la forma chiusa che avevamo intuito.
n T(n) S(n) 1 1 1 2 2 2 3 2 3 4 3 3 5 3 4 6 3 4 7 3 4 8 4 4 9 4 5È facile notare che per
Dimostriamolo per induzione, partendo dalla base infatti lo possiamo calcolare a mano, verificando direttamente che
Per il passo induttivo,
Nell'algoritmo mergesort, abbiamo e (o viceversa), da cui il numero di confronti sta nell'intervallo
0 | |||
Veniamo al caso generale. Come curiosità, consideriamo anche la ricorrenza relativa al caso migliore, quello in cui ogni operazione di merge esaurisce nel modo piú rapido possibile la lista più corta:
Con una semplice procedura
void table_mergesort() { int i; M[1]= 0; cout<<" n L(n) M(n) M(n)-M(n-1)"<<endl<<endl; for (i=2; i<18; i++) M[i]= M[i/2] + M[(i+1)/2] + i - 1; for (i=2; i<18; i++) L[i]= L[i/2] + L[(i+1)/2] + i/2; for (i=1; i<18; i++) { cout<<" "<<i<<" "<<L[i]<<" "<<M[i]; if (i>1) cout<<" "<<M[i]-M[i-1]; cout<<endl; } }possiamo tabulare i primi valori di tali ricorrenze, dove di abbiamo anche considerato la successione delle differenze.
n L(n) M(n) M(n)-M(n-1) 1 0 0 2 1 1 1 3 2 3 2 4 4 5 2 5 5 8 3 6 7 11 3 7 9 14 3 8 12 17 3 9 13 21 4 10 15 25 4 11 17 29 4 12 20 33 4 13 22 37 4 14 25 41 4 15 28 45 4 16 32 49 4 17 33 54 5
Si nota che, detto
, abbiamo
Verifichiamolo, trovando una
ricorrenza per