Un supplément d'information permet souvent de réduire la complexité d'un problème. L'algorithme de recherche séquentielle n'utilisait comme information que le test d'égalité sur les clés, avec deux résultats possibles : égalité, non-égalité. Supposons maintenant que les clés d'une table soient rangées par ordre croissant ; cela a pu être obtenu par un algorithme de tri. On peut alors réaliser un test avec trois résultats : égalité, inférieur, supérieur.
L'idée est de comparer la chaîne recherchée avec la clé du milieu du tableau ; si la chaîne est plus petite, on continue la recherche dans la première partie du tableau ; si elle est plus grande, on continue dans la seconde partie du tableau. La formulation récursive est la plus naturelle :
data dicho_search_rec(const char s[], int a, int b, const data t[]) { /* recherche dans t[a],...,t[b] */ if (a<=b) { int m = (a+b)/2; int ordre = strcmp(s, t[m].key); if (ordre == 0) { return t[m]; } else if (ordre < 0) { return dicho_search_rec(s, a, m-1, t); } else { return dicho_search_rec(s, m+1, b, t); } } else { return empty_data; } }
L'appel de cette fonction sur un tableau de taille N est
search_dicho_rec(s, 0, N-1, table);
Cette définition récursive (terminale) se transforme facilement en définition itérative.
data dicho_search_iter(const char s[], int n, const data t[]) { /* recherche dans t[a],...,t[b] */ int a = 0; int b = n-1; while (a<=b) { int m = (a+b)/2; int ordre = strcmp(s, t[m].key); if (ordre == 0) { return table[m]; } else if (ordre < 0) { b = m-1; } else { a = m+1; } } return empty_data; }
La recherche dans une table de taille N nécessite au plus comparaisons. Cette réduction logarithmique de la complexité est
un exemple de la méthode << diviser pour régner >>.