この記事では、アルゴリズムの定義と特徴、時間と空間の複雑さの計算など、アルゴリズムに関連する理論を主に紹介し、この記事では少量のコードを紹介します。
目次
アルゴリズムとデータ構造
データ構造はデータ間の有機的な関係であり、アルゴリズムはデータの操作手順です。データ間の有機的な関係がなければ、プログラムはまったく設計できません。データ構造があるからこそ、アルゴリズムが生まれます。逆に言えば、アルゴリズムはデータ構造を維持するための条件であり、アルゴリズムがなければデータを規則的に扱うことはできず、データは無秩序に衝突するだけであり、データ構造は消滅します。アルゴリズムは完全に動いており、データ構造は比較的静的であり、この 2 つを切り離すことはできません。
アルゴリズムは活発ですが、データ構造は遅い. アルゴリズムの開発にはデータ構造の開発が必要です. そうしないと、アルゴリズムの開発が妨げられます. 遅かれ早かれ, アルゴリズムの開発は必然的にデータ構造の束縛を打ち破ります.ポイントは矛盾した動きを続けます。
2 つのアルゴリズムの比較
デモンストレーションとしてC言語を使用し、1から100までの累積値を計算するプログラムを作成します
最初のサイクルの蓄積
int i, sum = 0, n = 100;
for(i = 1; i <= n; i++)
{
sum = sum + i;
}
printf("%d", sum);
これは非常に単純なサイクルです。1+2+3+...+100 の値を計算しました。これは多くの人々の最初の考えです。これは確かに正解の 1 つですが、次のように書くのは本当に良いことですか?これ?それは十分に効率的ですか?
第 2 種算術数列
有名な数学者ガウスは別の解決策を持っています:
コードで表現すると次のとおりです。
int sum = 0, n = 100;
sum = (1 + n) * n / 2;
printf("%d", sum);
よりシンプルで効率的な方法。最初の種類のループ累積と計算が 100 回であるのに比べて、算術シーケンスを使用するアイデアは 1 回だけ計算されます。10万くらい?100万ってこと?算術計算は、多くのコンピューティング リソースと時間を節約します。
アルゴリズムのプロパティ
アルゴリズムの 5 つの基本的な特性: 入力、出力、有限性、決定論、実現可能性
アルゴリズムは常に、有限数のステップを実行した後に終了する必要があり、各ステップは有限時間内に完了する必要があります。
入出力
アルゴリズムには 0 個以上の入力があり、アルゴリズムには少なくとも 1 つ以上の出力があります。
無限大
アルゴリズムは、無限ループなしで有限数のステップを実行した後に自動的に終了できる必要があり、ステップは許容時間内に完了する必要があります。
確実
アルゴリズムの各ステップには、あいまいさのない明確な意味があります。
実現可能性
アルゴリズムの各ステップは実行可能でなければなりません。つまり、各ステップは有限回の実行によって完了します。
アルゴリズム設計要件
アルゴリズムは一意ではありません. 同じ問題に対して複数の解決策があるかもしれません. アルゴリズムには標準的な答えがありません. アルゴリズムの良し悪しをどのように判断しますか? 優れたアルゴリズムには、いくつかの要件があります。
正しさ
アルゴリズムは、少なくとも明確な入力、出力、および処理を備え、問題のニーズを正しく反映し、問題に対する正しい答えを得ることができる必要があります。
可読性
読みやすく、理解しやすく、コミュニケーションしやすい。
堅牢性
入力データが不正な場合、アルゴリズムは、異常または不可解な結果を生成する代わりに、適切な処理を行うこともできます。
高い時間効率と少ないストレージ
時間効率とは、アルゴリズムの実行時間を指します。ストレージ容量とは、主に、アルゴリズムプログラムが実行中に占有するメモリまたは外付けハードディスクの容量を指します。設計アルゴリズムは、高い時間効率と低いストレージ容量の要件を満たすようにする必要があります。
アルゴリズム効率の測定
事後の統計
この方法は主に、アルゴリズムの効率を判断するために、設計されたテスト プログラムとデータを通じてコンピューター カウンターを使用して、異なるアルゴリズムでコンパイルされたプログラムの実行時間を比較します。
欠点は、プログラムを事前に作成しなければならない、コンピューターのハードウェアとソフトウェアに依存することが多い、テスト データの設計が難しい、などです。
事前見積もり
コンピュータプログラムをコンパイルする前に、統計的手法に従ってアルゴリズムを推定します。
主に次の要因を参照してください。
- アルゴリズムが採用する戦略と方法。
- コンパイルによって生成されたコードの品質。
- 問題の入力サイズ。
- マシンが命令を実行する速度。
例として、前の累積アルゴリズムを見てみましょう。
1 + 2 + 3 + ... + 100 = ?
#循环累加
int i, sum = 0, n = 100; /* 执行1次 */
for(i = 1; i <= n; i++) /* 执行了n+1次 */
{
sum = sum + i; /* 执行n次 n次 n次! */
}
printf("%d", sum); /* 执行1次 */
#等差数列
int sum = 0,n = 100; /* 执行一次 */
sum = (1 + n) * n / 2; /* 执行一次 */
printf("%d", sum); /* 执行一次 */
上位または下位の 2 つのアルゴリズム。
関数の漸近的成長
2 つのアルゴリズム A と B があるとします。
アルゴリズムは 2n+3 操作を計算します
アルゴリズム B は 3n+1 演算を計算します
2 つのアルゴリズムのうち、どちらが高速ですか? もちろん、必ずしもそうとは限りません。
周波数 | A(2n + 3 ) | B( 3n + 1 ) |
---|---|---|
n = 1 |
5 | 4 |
n = 2 | 7 | 7 |
n = 3 | 9 | 10 |
n = 10 | 23 | 31 |
n = 100 | 203 | 301 |
回数が 1 回の場合、アルゴリズム A の効率はアルゴリズム B ほど良くありませんが、n > 2 の場合、アルゴリズム A の効率はアルゴリズム B よりも悪いため、一般的にアルゴリズム A の効率が良いと言えます。アルゴリズム B よりも
高度
実はこれは関数の成長の問題で、ここでは定数を無視しているので、関数の最上位を優先し、次に係数、最後に定数という順番で効率を判断していきます。
つまり、回数 n が増えるにつれて、アルゴリズムは別のアルゴリズムよりも良くなったり悪くなったりします。
アルゴリズム時間の複雑さ
時間複雑度 (時間複雑度とも呼ばれます) は、アルゴリズムの時間複雑度は、アルゴリズムの実行時間を定性的に記述する関数です。これは、アルゴリズムの入力値を表す文字列の長さの関数です。時間計算量は、この関数の下位の項と先頭の係数を除いて、ビッグ O 表記で表されることがよくあります。このアプローチを使用する場合、時間計算量は漸近的であると言えます。つまり、入力値のサイズが無限大に近づく場合を考えます。
時間の複雑さの表現
上で述べたように、n がどんどん大きくなると、式の低レベル、定数、および係数の部分はその成長トレンドに影響を与えないため、それらを直接無視して最大の大きさを記録することができます。したがって、時間計算量を計算するときは、ループ数が最も多いコードにのみ注意を払う必要があります。
int sum = 0; //执行1次,忽略不计
for (int i = 0; i < n; i++) {
sum += i; // 循环内执行次数最多,执行次数为n次,因此时间复杂度记为O(n)
}
return sum; //执行1次,忽略不计
}
いくつかの一般的な時間の複雑さ
通常遭遇する最も一般的な 7 つの例を、運用効率の観点から高いものから低いものへと並べ替えます。
- O(1) — 一定の複雑さ
- O(log n) — 対数の複雑さ
- O(n) — 線形複雑度
- O(n log n) — 対数線形複雑度
- O(nᵏ) — 多項式の複雑さ
- O(kⁿ) — 指数関数的な複雑さ
- O(n!) — 階乗の複雑さ
赤い網掛け部分のアルゴリズムの実行時間は、入力サイズが大きくなるにつれて劇的に増加します。一方、黄色と緑の網掛け部分のアルゴリズムは、入力サイズが大きくなっても実行時間があまり変わらないため、より効率的で、大量のデータを簡単に処理できます。
最悪のケースと平均的なケース
とてもシンプル
最初のステップとして、100 個の数値の配列があり、そのうちの 1 つを見つけたいとします。
第二段階で、第一段階を数え切れないほど繰り返すことができれば、もちろん、最初に見つけたときや、35回、76回、83回など、さまざまな位置でこの数字を見つけることができます。各ラウンドの平均数を見つけます。この数は平均的なケースである 50 回かかります。
もちろん、3 番目のステップでは、この数を 100 回見つけるのが最悪のケースであることもわかります。
平均時間は予想時間ですが、評価アルゴリズムは最悪のケースを取る傾向があります。
アルゴリズム空間の複雑さ
動作中にアルゴリズムによって一時的に占有されるストレージ スペースのサイズの測定については、S(n)=O(f(n)) として記録します。たとえば、直接挿入ソートの時間計算量は O(n^2) で、空間計算量は O(1) です。一般的な再帰アルゴリズムは、再帰ごとに戻り情報を格納する必要があるため、O(n) のスペースの複雑さを持ちます。
アルゴリズムのスペースの複雑さ S(n) は、アルゴリズムによって消費されるストレージ スペースとして定義されます。これは、問題のサイズ n の関数でもあります。漸近空間複雑度は、単に空間複雑度とも呼ばれます。Space Complexity (SpaceComplexity) は、操作中にアルゴリズムによって一時的に占有されるストレージ スペースのサイズの尺度です。コンピューター上のアルゴリズムが占有するストレージ スペースには、アルゴリズム自体が占有するストレージ スペース、アルゴリズムの入力および出力データが占有するストレージ スペース、および動作中にアルゴリズムが一時的に占有するストレージ スペースの 3 つの側面があります。
コードを書くとき、スペースを時間に置き換えることができます. たとえば、特定の年がうるう年かどうかを判断するには、年を与えるたびに、その年がうるう年かどうかを計算する必要があります.
また、2022 要素の配列をあらかじめ作成しておき、数字の付いた年をすべて一致させ、うるう年であればこの配列項目の値を 1、うるう年でなければ値を 0 とする方法もあります。 . このように、ある年が閏年かどうかを判断する、いわゆるこの配列のある項目の値を求める問題になります。
最初のアプローチは、多くの計算時間を必要とします。2 番目の方法では、計算は最小限に抑えられますが、2050 年の 0 と 1 はハードディスクまたはメモリに保存する必要があり、これにはある程度のストレージ スペースが必要です。
いいね、収集、コメント欄へのコメントを歓迎し、ソースを示すために転載してください。
------------------------------
上記のリンク:
アルゴリズムとデータ構造 - データ構造の紹介 データ構造スピードラン。https://blog.csdn.net/qq_52213943/article/details/125676781
以下のリンク: