2010-11-26 19 views
2

J'ai découvert la recherche ternaire de Wikipedia. Je ne suis pas sûr de ce qu'ils veulent dire par le paramètre de précision absolue. Ils n'ont pas élaboré. Mais voici le pseudo-code:La récursivité de recherche ternaire n'est pas correcte

def ternarySearch(f, left, right, absolutePrecision): 
    #left and right are the current bounds; the maximum is between them 
    if (right - left) < absolutePrecision: 
     return (left + right)/2 

    leftThird = (2*left + right)/3 
    rightThird = (left + 2*right)/3 

    if f(leftThird) < f(rightThird): 
     return ternarySearch(f, leftThird, right, absolutePrecision) 

    return ternarySearch(f, left, rightThird, absolutePrecision) 

Je souhaite trouver la valeur maximale d'une fonction unimodale. Cela signifie que je veux imprimer le point de bordure de la séquence croissante et décroissante. Si la séquence est

1 2 3 4 5 -1 -2 -3 -4 

alors je veux imprimer 5 en sortie.

Voici ma tentative. Il ne donne pas de sortie. Pouvez-vous s'il vous plaît aider ou me donner un lien qui contient un bon tutoriel sur la recherche ternaire pour l'auto-apprentissage?

#include<iostream> 

using namespace std; 
int ternary_search(int[], int, int, int); 
int precval = 1; 

int main() 
{ 
    int n, arr[100], target; 
    cout << "\t\t\tTernary Search\n\n" << endl; 
    //cout << "This program will find max element in an unidomal array." << endl; 
    cout << "How many integers: "; 
    cin >> n; 
    for (int i=0; i<n; i++) 
     cin >> arr[i]; 
    cout << endl << "The max number in the array is: "; 
    int res = ternary_search(arr,0,n-1,precval)+0; 
    cout << res << endl; 
    return 0; 
} 

int ternary_search(int arr[], int left, int right, int precval) 
{ 
    if (right-left <= precval) 
     return (arr[right] > arr[left]) ? arr[right] : arr[left]; 
    int first_third = (left * 2 + right)/3; 
    int last_third = (left + right * 2)/3; 
    if(arr[first_third] < arr[last_third]) 
     return ternary_search(arr, first_third, right, precval); 
    else 
     return ternary_search(arr, left, last_third, precval); 
} 

Merci d'avance.

Répondre

2

Une précision absolue signifie l'erreur maximale entre le résultat renvoyé et le résultat vrai, c'est-à-dire max | returned_result - true_result |. Dans ce contexte, f est une fonction continue.

Puisque vous regardez une fonction discrète, vous ne pouvez pas faire beaucoup mieux que d'arriver au point right - left <= 1. Ensuite, comparez simplement les deux valeurs résultantes et renvoyez la valeur correspondant à la plus grande (puisque vous recherchez max).

EDIT

Le premier point de la partition, étant mathématiquement 2/3*left + right/3, devrait être discrétisée à ceil(2/3*left + right/3) (de sorte que la relation est left < first_third <= last_third < right

Alors first_third = (left*2+right)/3 devrait être remplacé first_third = (left*2 + right + 2)/3.

+0

> Puisque vous regardez une fonction discrète, vous ne pouvez pas faire beaucoup mieux que d'arriver au point> où droite - gauche <= 1. Puis, comparez simplement les deux valeurs résultantes et renvoyez la valeur> correspondant au plus grand (puisque vous cherchez max). Merci, j'ai édité le code en écrivant si (droite-gauche <= précval) // j'ai atteint 'precval' une variable globale ayant la valeur 1 return (arr [droite]> arr [gauche])? Arr [droite ]: arr [à gauche]; mais il ne donne aucune sortie. – nerd

+0

pouvez-vous éditer votre question pour inclure les changements? quand je trace à la main, cela fonctionne (le dernier appel récursif a '(gauche, droite) = (4, 5)'. – lijie

+1

Voici ce qui s'est passé: Dans la recherche ternaire quand il reste <= 3 valeurs, il faut le gérer dans le cas contraire, cela peut provoquer un débordement de pile car la fonction avec le même paramètre est appelée encore et encore [Mémoriser dans le cas de base de recherche binaire lorsque <= 2 valeurs sont laissées] Exemple: N = 3 Les valeurs sont 0 2 1 premier appel-> ternary_search (arr, 0, 2) first_third = 0 // observer à gauche et first_third est devenu le même, donc vous devez gérer cela comme un cas de base c'est-à-dire que right-left <= 2 est le cas de base. second_third = 1 arr [first_third] nerd

0

Essayez d'or Recherche de section (ou recherche de Fibonacci pour des fonctions discrètes) Il a un plus petit nombre de récursions et une réduction de 50% ons de f, par rapport à la recherche ternaire ci-dessus.