プログラマーは、アルゴリズムの時間の複雑さについてよく話します。 O(log n)またはO(n ^ 2)。
入力サイズが無限大になると、時間の複雑さの分類が行われますが、皮肉なことに、計算での無限の入力サイズは使用されません。
別の言い方をすれば、アルゴリズムの分類は、アルゴリズムが存在しない状況に基づいています。ここで、n =無限大です。
また、指数が巨大である多項式時間アルゴリズムは、小さな基数(1.00000001 ^ nなど)の指数時間アルゴリズムが役立つのと同じくらい役に立たないことを考慮してください。
これを踏まえると、アルゴリズムの選択をアドバイスするためにBig-O時間の複雑さにどれだけ依存できますか?
小さいn
Big Oを使用すると、ほとんど役に立たなくなります。アルゴリズムが優れている決定要因となる可能性が高いのは、隠された定数または実際の実装です。これが、標準ライブラリのほとんどの並べ替え関数が、最後の5つの要素のより高速な挿入並べ替えに切り替わる理由です。どちらが優れているかを判断する唯一の方法は、現実的なデータセットを使用してベンチマークすることです。
Big Oは大規模なデータセットに適しています。アルゴリズムのスケーリング方法については、将来的にデータが増加すると予想される場合は、O(n log n)
よりもO(n^2)
アルゴリズムの方が適しています。しかし、O(n^2)
が正常に機能し、入力サイズが一定のままである可能性がある場合は、アップグレードできるが、そのままにしておくと、他に心配する必要がある可能性があることに注意してください。今。
(前の段落のすべての「大きい」と「小さい」は相対的に解釈されることを意図していることに注意してください。小さい場合は数百万、大きい場合は100になる可能性があります。すべて特定のケースに依存します)
多くの場合、時間とスペースの間でトレードオフが発生します。たとえば、クイックソートはO(log n)
の追加のメモリを必要としますが、ヒープソートはO(1)
の追加のメモリを使用できますが、ヒープソートの隠された定数はそれを少なくします魅力的(追加のメモリコストを払わなくても差し支えなければ、mergesortをより魅力的にする安定性の問題もあります)。
考慮すべきもう1つのことは、データベースインデックスです。これらは、レコードが追加、削除、または変更されたときに更新にlog(n)
時間を必要とする追加のテーブルですが、検索をはるかに高速に実行できます(O(log n)
の代わりにO(n)
)。追加するかどうかを決定することは、ほとんどのデータベース管理者にとって常に頭痛の種です。インデックスの更新に費やす時間と比較して、インデックスのルックアップは十分ですか?
最後に覚えておくべきことは、より効率的なアルゴリズムは、ほとんどの場合、単純な単純なアルゴリズムよりも複雑です(そうでなければ、最初から使用していたアルゴリズムになります)。これは、バグとコードの表面積が大きく、追跡が困難であることを意味します。どちらも対処するのは重要な問題です。
私の経験では非常に意味があります。多くのパフォーマンス問題の根本で、私はこれらの原因をよく見つけます...
これは、ビジネスソフトウェアの開発の日常的な場所で発生します。といった...
Nが小さいことがわかっているほとんどの場合、複雑さに多くの時間を費やす価値はありません。
予想されるnの範囲について考え、複雑さを評価することは、アルゴリズムやアーキテクチャーに疑問を投げかける価値がある時期を知るための実証済みの方法です。私はこれを主に「頭の中」または「カクテルナプキンの裏側」のレベル計算のための直感的なツールとして使用します。時間の節約になります。
ソフトウェア設計に欠かせないツールです。
重要なのは、Oが制限する値ではなく、Oが制限する値の増加率です。これが微積分学の出番です。
たとえばlog(n)の導関数を使用すると、変化率として1/nが得られます。これは、log(n)アルゴリズムにかかる時間が1/nの割合で増加することを意味し、セットに値を追加するにつれて、f(1/n)の値が小さくなります。 n '= 1、n ^ c'(cは定数= cn、c ^ n '= c ^ n(log(c))の場合も同様です。したがって、高い次数よりも低い次数の場合の方が、成長速度ははるかに遅くなります。指数関数的にヒットすると、成長率はベース関数よりも大きく成長し始めます。
したがって、Big Oを理解すると、入力が「無限」にならない場合でも、入力ごとのアルゴリズム時間を簡単に比較できます。ちなみに、実際のコンピュータは有限のデバイスであるため、ソフトウェア開発またはCSの無限は、技術的、数学的な無限大ではなく、「任意に大きい」を意味することがよくあります。
漸近的な複雑さは確かに非常に意味があります。チェスの発明者が王に彼に報酬として小麦の2 ^ 65-1粒を与えるように頼んだ話を知っていますか? :)
あなたは正しい、高度の多項式アルゴリズムは役に立たない可能性があります。そして、アルゴリズムの時間の複雑さが高度な多項式であることを知るには、big-Oを調べる必要があります。また、O(1.00000001 ^ n)の時間の複雑さはまれです。ただし、ブール充足可能性問題などでは、常にO(2 ^ n)が表示されます。
アルゴリズムの複雑さを理解していない場合、プログラムがテスト入力で正常に機能するのに、顧客が2倍の大きさの入力を与えるとハングすることがあります。
Big-O分析はあなたが何かをするものではないと思いますrelyオン、それは一種のパフォーマンス警告です。
何かがO(2 ^ n)である場合、それが遅いという意味ではありませんが、それに注意を払う必要があるという意味です。
アルゴリズムを最適化すると、ボトルネックになる可能性が高いため、big-O分析で最初に測定する場所が示される場合があります。
他の人が言ったように、nが大きくなる可能性がある場合、big-Oは重要です。問題は、それが非常に多くのことを教えられているほどの学術的関心事であるので、学生はそれが問題であるのみ事柄であると考える傾向があります。
したがって、定数係数が必要以上に桁違いに大きいプロジェクトに参加した場合、準備ができていないため、その可能性を認識できないこともありますbe 問題。
一定の要因は無関係な後付けとして扱われ、学生は「プロファイラを使用する」(通常は gprof )と言われますが、実際のスピードアップの実績は乏しい。
意味がある?はい。しかし、それは完全な物語ではありません。
漸近的な複雑さからわかるのは、プログラムが入力サイズに対してどれだけ適切にスケーリングするかです。たとえば、小さな入力で当面許容時間内に実行されるプログラムがあるとします。次に、複雑さから、いくつかの大きな要素の処理にかかる時間の概算がわかります。
2つの重要な情報がまだ不足しているため、実際に実行される速度はわかりません。
O(1)
であるが、係数がenormousの場合、 等しい巨大な入力で作業しない限り、おそらくあまりメリットはありません。漸近的な複雑さは、大きな入力の粗雑な「ゼロ次推定」としては問題ありませんが、本当に重要なのは、重要な入力で何かが問題なく動作するかどうかです。これには、より複雑な数学的計算やプロファイリングが含まれます。