データ構造の複雑さの分析
序文
データ構造を学習するプロセスでは、コードの複雑さを分析する必要があることがよくあります。複雑さの分析には、時間の複雑さと空間の複雑さの 2種類があります。これら2つを分析する前に、最初にそれについて話しましょう、なぜ私たちは空間と時間の複雑さを分析する必要があるのですか?
なぜ複雑性分析を行うのか
コードを1回実行し、統計と監視により、アルゴリズムの実行時間と占有されているメモリの量を取得できます。時間と空間の複雑さを分析する必要があるのはなぜですか?この種類の分析方法は、実際の実行から取得できるデータよりも正確ですか?なぜ自分でその複雑さを分析するのですか?
1.テスト結果はテスト環境に大きく依存します
テスト環境におけるハードウェアの違いは、テスト結果に大きな影響を与えます。たとえば、同じコードを取得して、Intel Core i9プロセッサとIntel Core i3プロセッサで実行した場合、言うまでもなく、i9プロセッサはi3プロセッサよりもはるかに高速に実行されます。また、たとえば、このマシンの元のコードaはコードbよりも高速に実行されます。別のマシンに切り替えると、まったく逆の結果になる場合があります。
2.テスト結果はデータの規模に大きく影響されます
たとえば、並べ替えアルゴリズムの場合、同じ並べ替えアルゴリズムの場合、並べ替えるデータの順序が異なると、並べ替えの実行時間は大きく異なります。極端なケースでは、データがすでに正しい場合、並べ替えアルゴリズムは何もする必要がなく、実行時間は非常に短くなります。また、テストデータのサイズが小さすぎる場合、テスト結果はアルゴリズムのパフォーマンスを正確に反映していない可能性があります。たとえば、小規模なデータの並べ替えでは、挿入による並べ替えの方がクイックによる並べ替えよりも速い場合があります。
このことから、アルゴリズムの効率を知りたい場合は、自分で複雑さを分析する必要があることがわかります。
複雑さ分析法
- 単一セグメントのコードは、ループなどの高周波を調べます。
- 最大数のコードを取り上げます。たとえば、1つのコードに単一のループと複数のループがある場合、複数のループの複雑さを考慮してください。
- ネストされたコードの乗算:再帰、複数のループなど
- マルチスケールの追加:たとえば、メソッドには2つのループの数を制御する2つのパラメーターがあり、このとき2つのループの複雑さが追加されます。
時間の複雑さの分析
Big Oこの複雑さの表現方法は、変化の傾向を示すだけです。通常、式の定数、低次、および係数を無視し、最大次数の大きさを記録するだけで済みます。したがって、アルゴリズムとコードの時間の複雑さを分析するときは、ループ実行時間が最も長いコードにのみ注意を払います。このコアコードの実行回数の大きさは、分析されるコード全体の時間の複雑さです。
一般的なものは次のとおりです。
O(1)についてお話したいのですが、nの増加に伴ってコードの実行時間が増加しない限り、コードの時間の複雑さはO(1)として記録されます。つまり、一般に、アルゴリズムにループステートメントまたは再帰ステートメントがない限り、数千行のコードがあっても、時間の複雑さはΟ(1)のままです。
O(logn)について少し触れますが、以下は
2 ^ i = n ----> i = log2nの複雑さです。
i=1;
while (i <= n)
{
i = i * 2;
}
時間の複雑さを分解
- 最良の場合の時間の複雑さ:最も理想的な場合のコード実行の時間の複雑さ。
- 最悪の場合の時間の複雑さ:最悪の場合のコード実行の時間の複雑さ。
- 平均時間の複雑さ:すべてのケースでコードが実行された回数の加重平均で表されます。
- 償却時間の複雑さ:コード実行の複雑さのほとんどは低レベルの複雑度であり、個々のケースは高レベルの複雑度であり、タイミング関係が発生し、個々の高レベルの複雑度は低レベルの複雑度に償却できます。程度。基本的に償却結果は、低レベルの複雑さと同等です。
平均時間の複雑さと償却時間の複雑さを使用する方法
- 平均時間の複雑さ
コードの複雑さは、状況によって大きさが異なります。これは、考えられるすべての状況でのコードの実行時間の加重平均によって表されます。 - 償却時間の複雑度
は、2つの条件が満たされた場合に使用されます。1)ほとんどの場合、コードは低レベルの複雑度であり、高レベルの複雑度はほんのわずかです。2)低レベルおよび高レベルの複雑度はタイミング法則で表示されます。償却後の結果は、一般に低レベルの複雑さと同等です。
スペースの複雑さ
3つの一般的なものがあります:
O(1)
O(n)
O(n ^ 2)
分析:
void print(int n)
{
int i = 0;
int[] a = new int[n];
for (i; i = 0; --i)
{
print out a[i]
}
}
コードの2行目では、変数iを格納するスペースを適用しますが、これは一定の順序であり、データサイズnとは関係がないため、無視できます。3行目は、サイズnのint型配列に適用されます。さらに、コードの残りの部分はより多くのスペースをとらないため、コード全体のスペースの複雑さはO(n)です。
この時点で、複雑さの分析は終了しました。複雑さの分析を完全に把握したい場合は、自分でさらに分析を行う必要があります。それが役に立てば幸いです。便利な場合は、気に入っていただければ幸いです。