Edit: révision majeure dans la révision 3.
Comme je n’ai jamais enseigné de cours, je ne pense pas pouvoir affirmer ce que nous devrions enseigner de manière convaincante. Néanmoins, voici ce que j'ai pensé à ce sujet.
Il existe des exemples naturels dans lesquels «l’astuce limite» telle qu’elle est écrite ne peut être appliquée. Par exemple, supposons que vous implémentiez un "vecteur de longueur variable" (comme le vecteur <T> en C ++) en utilisant un tableau de longueur fixe doublant la taille (en d'autres termes, chaque fois que vous êtes sur le point de dépasser la taille du tableau, vous réallouez le tableau deux fois plus grand que maintenant et copiez tous les éléments). La taille S ( n ) du tableau lorsque nous stockons n éléments dans le vecteur est la plus petite puissance de 2 supérieure ou égale à n . Nous voulons dire que S ( n ) = O ( n ), mais l’utilisation de «l’astuce limite» telle qu’elle est écrite dans la définition ne nous permettrait pas de le faire car S ( n) / n oscille de manière dense dans la plage [1,2). La même chose s'applique à Ω () et à ().
De manière assez distincte, lorsque nous utilisons ces notations pour décrire la complexité d’un algorithme, je pense que votre définition de Ω () est parfois gênante (bien que je suppose que cette définition soit commune). Il est plus pratique de définir que f ( n ) = Ω ( g ( n )) si et seulement si limsup f ( n ) / g ( n )> 0. C’est parce que certains problèmes sont triviaux pour une infinité de valeurs de n ( comme le problème d’usinage parfait sur un graphique avec un nombre impair n de sommets). La même chose s'applique à Θ () et à ().
Par conséquent, j'estime personnellement que les définitions suivantes sont les plus pratiques à utiliser pour décrire la complexité d'un algorithme: pour les fonctions f , g : → > 0 ,
- f ( n ) = o ( g ( n )) si et seulement si limsup f ( n ) / g ( n ) = 0. (Ceci équivaut à lim f ( n ) / g ( n ) = 0)
- f ( n ) = O ( g ( n )) si et seulement si limsup f ( n ) / g ( n ) <∞.
- f ( n ) = Θ ( g ( n )) si et seulement si 0 <limsup f ( n ) / g ( n ) <.
- f ( n ) = Ω ( g ( n )) si et seulement si limsup f ( n ) / g ( n )> 0. (Ceci est équivalent à ce que f ( n ) n'est pas o ( g ( n )).)
- f ( n ) = ω ( g ( n )) si et seulement si limsup f ( n ) / g ( n ) =. (Ceci est équivalent à ce que f ( n ) n'est pas O ( g ( n )).)
ou équivalent,
- f ( n ) = o ( g ( n )) si et seulement si pour tout c > 0, pour n suffisamment grand , f ( n ) ≤ c ⋅ g ( n ).
- f ( n ) = O ( g ( n )) si et seulement si pour certains c > 0, pour n suffisamment grand , f ( n ) ≤ c ⋅ g ( n ).
- f ( n ) = Θ ( g ( n )) si et seulement si f ( n ) = O ( g ( n )) et f ( n ) = Ω ( g ( n )).
- f ( n ) = Ω ( g ( n )) si et seulement si pour certains d > 0, pour un nombre infini de n , f ( n ) ≥ d ⋅ g ( n ).
- f ( n ) = ω ( g ( n )) si et seulement si pour tout d > 0, pour un nombre infini de n , f ( n ) ≥ d ⋅ g ( n ).
Mais je ne sais pas s'il s'agit d'une pratique courante ou non. Aussi, je ne sais pas si cela convient à l'enseignement. Le problème est que nous voulons parfois définir Ω () avec liminf à la place (comme vous l'avez fait dans la première définition). Par exemple, lorsque nous disons «La probabilité d'erreur de cet algorithme randomisé est 2 Ω ( n ) », nous ne voulons pas dire que la probabilité d'erreur est petite de façon exponentielle simplement pour une infinité de n !