フロントエンド上級編: よく使われるいくつかの JS 検索アルゴリズムの概要とパフォーマンス比較

フロントエンド上級編: よく使われるいくつかの JS 検索アルゴリズムの概要とパフォーマンス比較

[[356180]]

序文

今日は引き続き js アルゴリズムについてお話ししましょう。以下の説明を通じて、検索アルゴリズムの基本的な実装とさまざまな実装方法のパフォーマンスを理解し、for ループ、forEach、While のパフォーマンスの違いを見つけることができます。また、Web ワーカーを介してアルゴリズムをシャーディングして、アルゴリズムのパフォーマンスを大幅に向上させる方法も学習します。

同時に、古典的なバイナリアルゴリズムとハッシュテーブル検索アルゴリズムも簡単に紹介しますが、これらはこの章の焦点では​​ありません。後ほど、これらの高度なアルゴリズムを詳細に紹介する関連記事を公開します。興味のある友人は、私のコラムをフォローしたり、一緒に議論したりすることができます。

アルゴリズムのパフォーマンスについては、前回の章「フロントエンドアルゴリズムシリーズ」の getFnRunTime 関数を引き続き使用して、フロントエンドコードの速度を 60 倍に上げる方法を学習します。興味がある場合は、確認していただければ、ここでは詳しく説明しません。

前回の章「フロントエンドアルゴリズムシリーズ」では、フロントエンドコードの速度を60倍に上げる方法について、19,000個のデータをシミュレートしました。この章では、効果をより明確にするために、テスト用に170万個のデータを偽造しますが、信じてください、これはjsにとって何でもありません。 。 。

1. forループ検索

  • 基本的な考え方は、forループを介して配列を走査し、配列内で検索する値のインデックスを見つけて、それを新しい配列にプッシュすることです。

コードは次のように実装されます。

  1. const getFnRunTime = require( './getRuntime' );
  2.  
  3. /**
  4. * 通常のアルゴリズム - forループバージョン
  5. * @param {*} 引数
  6. * 消費時間: 7~9ms
  7. */
  8. 関数searchBy(arr, 値) {
  9. 結果 = [] とします。
  10. (i = 0, len = arr.length; i < len; i++)の場合{
  11. if(arr[i] === 値) {
  12. 結果.push(i);
  13. }
  14. }
  15. 結果を返す
  16. }
  17. getFnRunTime(検索条件、6)

n 回テストした結果は次のとおりです。

2. forEachループ

基本的な考え方は for ループに似ています。

  1. /**
  2. * 通常のアルゴリズム - forEach ループバージョン
  3. * @param {*} 引数
  4. * 消費時間: 21~24ms
  5. */
  6. 関数searchByForEach(arr, 値) {
  7. 結果 = [] とします。
  8. arr.forEach((item,i) => {
  9. if(項目 === 値) {
  10. 結果.push(i);
  11. }
  12. })
  13. 結果を返す
  14. }

これには 21 ~ 24 ミリ秒かかり、パフォーマンスは for ループほど良くないことがわかります (今のところ、本質も真実であるとだけ言っておきます)。

3. whileループ

コードは次のとおりです。

  1. /**
  2. * 通常のアルゴリズム - whileループバージョン
  3. * @param {*} 引数
  4. * 消費時間: 11ms
  5. */
  6. 関数searchByWhile(arr, 値) {
  7. i = arr.lengthとします。
  8. 結果 = [];
  9. while(i) {
  10. if(arr[i] === 値) {
  11. 結果.push(i);
  12. }
  13. 私 - ;  
  14. }
  15.      
  16. 結果を返す
  17. }

while ループと for ループのパフォーマンスは似ており、どちらも優れていることがわかりますが、forEach のパフォーマンスが低いため使用すべきではないという意味ではありません。 for ループと比較すると、 foreach はコードを削減しますが、 foreach は IEnumerable に依存します。実行時の効率は for ループよりも低くなります。ただし、ループ回数が不明なループを扱う場合や、ループ回数を計算する必要がある場合は、 foreach を使用する方が便利です。さらに、 foreach のコードはコンパイラ システムによって最適化された後、 for ループのループと似たものになります。

4. 二分探索

バイナリ検索は、値が一意で順序付けられている配列でよく使用されます。ここでは、for/while/forEach とのパフォーマンスの比較は行いません。

  • 基本的な考え方: シーケンスの途中から比較を開始します。現在の位置の値が検索対象の値と等しい場合、検索は成功します。検索対象の値が現在の位置の値より小さい場合は、シーケンスの前半で検索します。検索対象の値が現在の位置の値より大きい場合は、見つかるまでシーケンスの後半で検索を続けます。

コードは次のとおりです。

  1. /**
  2. * バイナリアルゴリズム
  3. * @param {*} 引数
  4. * @param {*} 値
  5. */
  6. 関数binarySearch(arr, 値) {
  7. min = 0 とします。
  8. max = arr.length - 1 とします。
  9.      
  10. (最小値<=最大値)の間
  11. 定数mid = Math.floor(( min + max ) / 2);
  12.    
  13. (arr[mid] === 値)の場合{
  14. ミッドに戻ります
  15. }そうでなければ (arr[mid] > 値) {
  16. 最大= 中間 - 1;
  17. }それ以外{
  18. 最小= 中間 + 1;
  19. }
  20. }
  21.    
  22. 戻る  '見つかりません' ;
  23. }

大量のデータを扱うシナリオでは、バイナリ検索は非常に効率的ですが、不安定であるため、大規模なデータクエリでは若干不利になります。

5. ハッシュテーブル検索

  • ハッシュテーブル検索はハッシュテーブル検索とも呼ばれます。キーワードを検索することで、比較せずに必要なレコードの保存場所を取得できます。レコードの保存場所とそのキーワードの間に一定の対応fを確立し、各キーワードキーが保存場所f(キー)に対応します。

ハッシュ テーブル検索の使用シナリオ:

  • ハッシュ テーブルが最も適している問題は、指定された値に等しいレコードを見つけることです。
  • ハッシュ検索は、同じキーワードが複数のレコードに対応する状況には適していません。
  • 18歳から22歳の学生を検索するなどの範囲検索には適していません

ここでは、ハッシュを誰もが理解しやすいように、hashTable の最もシンプルなバージョンを紹介します。

  1. /**
  2. * ハッシュテーブル
  3. * 以下の方法ではデータの上書きの問題が発生する可能性があります
  4. */
  5. 関数ハッシュテーブル() {
  6. varテーブル= [];
  7.  
  8. // ハッシュ関数
  9. var loseloseHashCode =関数(キー) {
  10. var ハッシュ = 0;
  11. ( var i=0; i<キー.length; i++) {
  12. ハッシュ +=キー.charCodeAt(i);
  13. }
  14. ハッシュ% 37を返す
  15. };
  16.  
  17. // 置く
  18. this.put =関数(キー、値) {
  19. var position = loseloseHashCode(キー);
  20. テーブル[位置] = 値;
  21. }
  22.  
  23. // 得る
  24. this.get =関数(キー) {
  25. 戻る テーブル[loseloseHashCode(キー)]
  26. }
  27.  
  28. // 取り除く
  29. this.remove =関数(キー) {
  30. テーブル[loseloseHashCode(キー)] = 未定義;
  31. }
  32. }

この方法ではデータの競合が発生する可能性がありますが、解決策はあります。ここでは多くの知識ポイントが関係しているので、後でそれらを紹介する特別な記事を公開します。

  • オープンアドレス
  • 二次検出
  • ランダムプロービング

Webワーカー最適化を使用する

上記の方法により、さまざまなアルゴリズムのパフォーマンスと適用シナリオがすでにわかっています。アルゴリズムを使用する場合、Web ワーカーを介してアルゴリズムを最適化し、プログラムが並列処理できるようにすることもできます。たとえば、大きな配列を複数のブロックに分割し、Web ワーカー スレッドに計算結果の処理を任せ、最後に結果をマージしてワーカーのイベント メカニズムを介してブラウザーに渡します。その効果は非常に顕著です。

要約する

  1. 複雑な配列クエリの場合、for/whileはforEachや他の配列メソッドよりもパフォーマンスが優れています。
  2. O(logn) の二分探索は非常に効率的なアルゴリズムです。しかし、その欠陥も明らかです。配列は順序付けられる必要があり、配列が順序付けられていることを保証するのは困難です。もちろん、配列を構築するときにソートすることはできますが、その場合、配列でなければならないという 2 番目のボトルネックが発生します。配列の読み取り効率は O(1) ですが、要素の挿入と削除の効率は O(n) です。これにより、順序付けられた配列を構築する際の効率が低下します。
  3. ハッシュ テーブル検索の基本的な使用法とシナリオ。
  4. 条件が許せば、Web ワーカーを使用してアルゴリズムを最適化し、バックグラウンドで並列実行できます。

さて、この記事は比較的シンプルですが、とても重要です。検索アルゴリズムについて、皆さんがより直感的に理解できるようになることを願っています。また、皆さんがより良い方法を見つけ、一緒に議論したり、アイデアを交換したりできるようになることを願っています。

<<:  2020 年の生体認証市場 - パンデミックによる業界の動向の変化

>>:  YouTube でフォローすべき 5 人のデータ サイエンティストと機械学習エンジニア

ブログ    
ブログ    
ブログ    

推薦する

すべての携帯電話にAIが搭載されているのに、なぜそれを軽蔑するのですか?

携帯電話の発表会を見れば、AI機能の追加が目に入ります。しかし、多くのユーザーはこれをやや否定的に捉...

...

フランシス・バーガーは分析をよりスマートにし、難しくしない

[[386714]]北東部に拠点を置くエネルギー会社 Eversource で財務計画および分析 (...

人工知能には関連する専門家の参加も必要です!これはより良く、より速くなります

機械にはハードウェアだけでなくソフトウェアもあります。ハードウェアには材料や電力の問題が必要ですが、...

ディープラーニング入門: オートエンコーダから変分オートエンコーダまで

オートエンコーダ(AE)は、半教師あり学習や教師なし学習で使用される人工ニューラルネットワーク(AN...

今年は人工知能と5Gの急速な共同開発が見られました

RedMonk は初めて言語人気ランキングで Java に取って代わり、Python が 2 位にな...

手書きを模倣するAIが独自のフォントを作成

手書き模倣AIの研究背景諺にあるように、人の筆跡はその人の性格を表す。硬い印刷フォントと比較すると、...

責任あるAIの構築

現在、AI によって完全に有効化されたプロセスを備えている企業はわずか 25% であり、これらの企業...

人工知能がとても人気ですが、機械学習とディープラーニングの違いがわかりますか?

人工知能は最近大きな注目を集めています。人工知能を実装するための技術としてディープラーニングと機械学...

清華大学が世界初のオンチップ学習メモリスタメモリコンピューティング統合チップを開発、その成果がサイエンス誌に掲載された。

10月9日、清華大学の公式Weiboアカウントは、オンチップ学習をサポートする世界初のメモリスタス...

C言語の非数値計算でよく使われる5つの古典的なソートアルゴリズム

概要: ソートとは、一連の「順序付けられていない」レコードシーケンスを「順序付けられた」レコードシー...

知っておくべき人工知能アルゴリズム トップ 10

人工知能 (AI) 技術の人気が高まるにつれ、さまざまなアルゴリズムがこの分野の発展を促進する上で重...

...

我が国の新世代人工知能ガバナンス原則が発表され、立法のための強固な基盤が築かれた

テクノロジーの発展はしばしば諸刃の剣であり、人工知能の商業化も一定の原則に従う必要があります。 6月...

WAVE SUMMIT 2023は8月16日に開催予定です!パドルパドルとウェンシンの大型モデルが最新の技術成果を展示します

今年は国内のテクノロジーメーカーが各分野で続々と大型モデルを発売し、「モデル戦争」が本格化しているが...