2009-06-07 11 views
67

Donc je pense que je vais être enterré pour poser une question aussi banale mais je suis un peu confus à propos de quelque chose.O (N log N) Complexité - Similaire à linéaire?

J'ai implémenté quicksort en Java et C et je faisais quelques comparissons de base. Le graphique est sorti comme deux droites, avec le C étant 4ms plus rapide que la contrepartie de Java plus de 100 nombres entiers aléatoires.

Results

Le code pour mes tests peuvent être trouvés ici; ligne

android-benchmarks

Je ne savais pas quel (n log n) ressemblerait mais je ne pensais pas que ce serait simple. Je voulais juste vérifier que c'est le résultat attendu et que je ne devrais pas essayer de trouver une erreur dans mon code.

Je bloqué la formule dans Excel et pour la base 10, il semble être une ligne droite avec un coude au début. Est-ce parce que la différence entre log (n) et log (n + 1) augmente linéairement?

Merci,

Gav

+1

La recherche Google * image * semble étonnamment bonne sur les recherches comme "n log n". –

+1

La ligne Java sur le dessus ne me regarde pas directement. – Puppy

+0

Similaire, en effet, ce qui explique pourquoi il est appelé ["temps linearithmic"] (http://en.wikipedia.org/wiki/Time_complexity#Linearithmic_time) – msanford

Répondre

76

rendre le graphique plus grand et vous verrez que O (n log n) est pas tout à fait une ligne droite. Mais oui, c'est assez proche du comportement linéaire. Pour voir pourquoi, prenez juste le logarithme de quelques très grands nombres.

Par exemple (base 10):

log(1000000) = 6 
log(1000000000) = 9 
… 

Ainsi, pour trier 1.000.000 numéros, un O (n log n) tri ajoute un facteur measly 6 (ou juste un peu plus que la plupart des algorithmes de tri dépendent base 2 logarithmes). Pas énormément.

En fait, ce facteur de journal est donc extraordinairement petit que pour la plupart des ordres de grandeur, les algorithmes O (n logn) établis surpassent les algorithmes de temps linéaire. Un exemple important est la création d'une structure de données de tableau de suffixes.

Un cas simple m'a récemment mordu when I tried to improve a quicksort sorting of short strings by employing radix sort. Il s'avère que, pour les chaînes courtes, ce type de base de temps (linéaire) était plus rapide que le tri rapide, mais il y avait un point de bascule pour les chaînes relativement courtes, puisque le tri radix dépend crucialement de la longueur des cordes que vous triez.

+2

Réponse fantastique, merci pour éclaircir cela pour moi. Il suffit de lire votre message maintenant, des choses vraiment intéressantes. – gav

+1

Les bons types ont tendance à opter pour un algorithme linéaire une fois qu'ils ont divisé et conquis en morceaux suffisamment petits. Exactement comment petite est une question de benchmarking (données réelles). –

+2

Tom: Je ne suis pas sûr de ce que vous voulez dire exactement par linéaire. Souvent, les algorithmes de tri font l'inverse en utilisant des triages O (n^2) tels que le tri d'insertion sur de petites portions, puisque leur facteur constant est si petit que même l'exécution quadratique surpasse le tri nlogn. D'un autre côté, l'introsort utilise une stratégie pour sortir des récursions trop profondes - mais là encore, ce n'est pas linéaire, il échange juste un pire cas quadratique pour le comportement O (n logn). –

1

log (N) est (très) à peu près le nombre de chiffres à N. Ainsi, pour la plupart, il y a peu de différence entre log (n) et log (n + 1)

+3

log-base- * 10 * correspond très approximativement au nombre de chiffres de N (en supposant que vous utilisez la représentation décimale). La plupart des algorithmes de tri/recherche utilisent log-base-2 qui, bien que proportionnel à log-base-10 (donc le big-O s'applique toujours), n'a rien à voir avec ce que vous décrivez :-) – paxdiablo

+0

Une autre façon de le dire log-base-2 est à peu près le nombre de chiffres dans N lorsqu'il est écrit en binaire, alias le nombre de bits requis pour représenter N. –

0

Essayez comploter une ligne linéaire réelle sur le dessus de celui-ci et vous verrez la petite augmentation. Notez que la valeur Y à 50,0000 est inférieure à la valeur 1/2 Y à 100 000.

Il est là, mais il est petit. C'est pourquoi O (nlog (n)) est si bon!

+0

C'est encore mieux que O (n^2). – paxdiablo

3
  1. Habituellement, les algorithmes O (n * log (n)) ont une implémentation logarithmique à 2 bases.
  2. Pour n = 1024, log (1024) = 10, alors n * log (n) = 1 024 * 10 = 10240 calculs, une augmentation d'un ordre de grandeur.Donc, O (n * log (n)) est similaire à linéaire seulement pour une petite quantité de données.

Conseil: n'oubliez pas que le tri rapide se comporte très bien sur les données aléatoires et qu'il ne s'agit pas d'un algorithme O (n * log (n)).

+2

Tous les logarithmes sont les mêmes, ils ne diffèrent que par l'échelle. Donc, je ne vois pas la signification de votre première déclaration. De plus, je ne suis pas d'accord avec votre affirmation selon laquelle O (n log n) n'est similaire à linéaire que pour une petite quantité de données. Encore une fois, c'est une mise à l'échelle. En guise de contre-exemple, il suffit de regarder les graphiques dans la question initiale. – waxwing

+0

Je ne veux pas dire graphiquement similaire (à une ligne droite) mais complexité temporelle similaire. O (n * logn) temps peut facilement être un ordre de grandeur plus grand que O (n). Si les graphes comparaient les algorithmes O (n * logn) et O (n), vous verriez ce que je veux dire. :) Comme le N devient de plus en plus grand, le O (n * logn) * se déplace * vers les échelles logarithmiques suivantes. –

+1

En moyenne, le Quicksort EST un algorithme O (n log n). – Manu

5

Pour encore plus de plaisir dans la même veine, essayez de tracer le temps pris par les opérations n sur la norme disjoint set data structure. Il a été asymptotiquement n   α (n) où α (n) est l'inverse de la Ackermann function (si votre manuel d'algorithmes habituels montrera probablement une limite de n log log n ou éventuellement n   log*   n). Pour tout type de numéro que vous serez susceptible de rencontrer la taille d'entrée, α (n)   ≤   5 (et même log *   n   ≤   5), bien qu'il ne l'infini approche asymptotiquement. Ce que je suppose que vous pouvez apprendre de ceci est que si la complexité asymptotique est un outil très utile pour penser à des algorithmes, ce n'est pas tout à fait la même chose que l'efficacité pratique.

10

Pour votre information, quicksort est en fait O (n^2), mais avec une moyenne de cas O (nlogn)

Pour votre information, il y a une différence assez importante entre O (n) et O (nlogn). C'est pourquoi il n'est pas limitable par O (n) pour toute constante.

Pour voir de démonstration graphique:

O(n) vs O(nlogn)

+2

a) Sans spécifier, O() est généralement utilisé pour désigner la complexité * attendue * (moyenne). b) La notation O() n'inclut pas les facteurs constants, donc O (n) et O (2n) sont les mêmes. Puisque log (n) est presque constant (pour les grands nombres, comparé à n), on peut dire que O (n) et O (n log (n)) sont presque les mêmes. Vous devriez avoir tracé: http://www.wolframalpha.com/input/?i=plot+7+x%2C+x+log+x+from+1+to+1500 – Timmmm

+12

Ceci est généralement faux. La notation Big O indique généralement la complexité asymptotique du cas le plus défavorable et notifie une fonction qui limite la complexité des algorithmes. O (n) ne se rapproche pas de O (nlogn), bien que, pour des raisons pratiques, O (nlogn) soit relativement bon et pas très pire. Le pire des cas de tri rapide n'est certainement pas une chose rare à rencontrer. Essayez de faire un quicksort sur les entrées dans le dictionnaire si vous ne me croyez pas. – groundhog

+0

Je ne pense pas qu'il y ait une grande différence. Surtout quand vous le comparez à l'ordre suivant $ O (n^2) $. https://i.sli.mg/9zXUQR.png –

2

Toutes les données peuvent être tracées sur une ligne si les axes sont choisis correctement :-)

Wikipedia dit Big-O est le pire des cas (-à-dire f (x) est O (N) des moyens de f (x) est "majorée" par N) https://en.wikipedia.org/wiki/Big_O_notation

Voici une belle série de graphiques illustrant les différences entre les diverses fonctions communes: http://science.slc.edu/~jmarshall/courses/2002/spring/cs50/BigO/

La dérivée de log (x) est 1/x. C'est ainsi que log (x) augmente rapidement lorsque x augmente. Ce n'est pas linéaire, bien que cela puisse ressembler à une ligne droite parce qu'elle se courbe si lentement. En pensant à O (log (n)), je pense à O (N^0 +), c'est-à-dire la plus petite puissance de N qui n'est pas constante, puisque toute puissance constante positive de N la dépassera finalement. Ce n'est pas exact à 100%, alors les professeurs vont se mettre en colère contre vous si vous l'expliquez de cette façon.

La différence entre les logs de deux bases différentes est un multiplicateur constant. Recherchez la formule pour convertir les journaux entre deux bases: (sous "changement de base" ici: https://en.wikipedia.org/wiki/Logarithm) L'astuce consiste à traiter k et b comme des constantes.

En pratique, il y a normalement des problèmes de hachage dans les données que vous tracez. Il y aura des différences dans les choses en dehors de votre programme (quelque chose d'échange dans l'unité centrale de traitement de votre programme, manquements de cache, etc.). Il faut beaucoup de courses pour obtenir des données fiables. Les constantes sont le plus grand ennemi de la tentative d'appliquer la notation Big O à l'exécution réelle. Un algorithme O (N) avec une constante haute peut être plus lent qu'un algorithme O (N^2) pour N assez petit.

+0

(Je suppose que vous vouliez dire une ligne droite, et non "ligne" comme un terme général pour la courbe.) J'achèterais que toute fonction à valeur réelle différentiable en continu d'une variable réelle peut être tracée sur une ligne droite si les axes sont choisis correctement avec seulement des manigances modérées comme des valeurs d'axe dupliquées (nécessaire sauf s'il s'agit d'une fonction un-à-un) , mais "des données"? Je pense que c'est un étirement. Que diriez-vous de la fonction qui est zéro pour tous les nombres rationnels mais un pour tous les nombres irrationnels. (Il est connu comme la fonction de Dirichlet, et c'est une vraie fonction mathématique.) –