1. 二重連結リストとは何か単一リンク リストは、先頭から末尾、または末尾から先頭 (一般的には先頭から末尾) の方向のみをたどることができることがわかっています。つまり、リンク リストを接続するプロセスは一方向であり、実装の原則は、前のリンク リストに次のリストを指す参照があることです。さらに明らかな欠点があります: 次のノードへは簡単に到達できますが、前のノードに戻るのは困難です。しかし、実際の開発では、前のノードに戻る必要がある状況に遭遇することが多く、ここで双方向のリンクリストが必要になります。 いわゆる二重リンクリストは、先頭から末尾、末尾から先頭まで走査できるリンクリストです。ただし、二重リンクリストにも欠点があります。たとえば、ノードが挿入または削除されるたびに、2 つではなく 4 つのノード参照を処理する必要があります。単一のリンクリストと比較すると、より多くのメモリを消費します。ただし、これらの欠点は、使用の利便性と比較すると無視できるほど小さいものです。 二重リンクリストの特徴:
これを抽象化すると次のようになります。 二重リンクリストの構造を理解した上で、二重リンクリストのカプセル化を見てみましょう。 2. 二重リンクリストのカプセル化まず、リンク リスト構造を表す 関数DoublyLinkedList(){ this.head = null; this.tail = null; this.length = 0; 関数 Node(データ){ this.data = データ; this.prev = null; this.next = null; } 3. 双方向リンクリストの一般的な操作次に、双方向リンク リストに共通の操作を追加できます。
次に、それらを1つずつ実装します。 1. append(element) メソッド-----リストの末尾に項目を追加するこの方法は、単一リンク リスト メソッドに似ています。まず、新しいリストを作成し、リンク リストが空かどうかを判断します。空の場合は、リンク リストの先頭が、新しく作成されたリンク リストを直接指すようにします。空でない場合は、新しいノードの先行ポインターがリンク リストの末尾を指すようにし、リンク リストの末尾のノードが新しいリンク リストを指すようにします。 Doubly.prototype.append = function(data){ var newNode = 新しいノード(データ); 長さが 0 の場合 ノードを新規作成します。 }それ以外{ newNode.prev = this.tail; this.tail.next = 新しいノード; } this.tail = newNode; this.length += 1; } 2. リンクリストを文字列に変換する1. toString(): 要素の値を順方向に出力する このメソッドは主に各要素を取得するために使用されます。デフォルトでは、リンク リストの要素は最初のノードから始まる必要があるため、先頭ノードから開始し、各ノードをループして要素を取り出し、それを文字列に連結して、文字列を返すことができます。具体的な方法は、一時ノード DoublyLinkedList.prototype.tostring = function(){ var 現在の = this.head; var str = ''; while(現在){ str += 現在のデータ + ' '; 現在の = 現在の.次; } str を返します。 } 2. forwardString(): 前方走査のノード文字列形式を返す このメソッドは双方向リンク リストの順方向印刷と出力も実装しているため、ここで前のメソッドを直接呼び出すことができます。 DoublyLinkedList.prototype.forwardString = function(){ this.toString() を返す } 3. backwardString(): 逆方向のトラバーサルのノード文字列形式を返す このメソッドは、主に後ろから前へトラバースして各要素を取得して印刷するため、末尾のノードから開始し、各ノードをループして要素を取り出し、それを文字列に連結して、文字列を返すことができます。具体的な方法は、一時ノード DoublyLinkedList.prototype.backwardString = function(){ var 現在の値 = this.tail; var str = ''; // 順番に前へ進み、各ノードを取得します while(current){ str += 現在のデータ +' '; 現在の = 現在の.前の; } str を返します。 } 確認する: たとえば、 var リスト = 新しい DoublyLinkedList(); リストに追加します("a"); リストに追加します("b"); リストに追加します("c"); リストに追加します("d"); console.log('toString() メソッド: ' + list.toString()); console.log('forwardString() メソッド: '+list.forwardString()); console.log('backwardString() メソッド: ' + list.backwardString()); 印刷結果は次のとおりです。 検証に成功しました。 3. insert(位置,要素): リスト内の特定の位置に項目を挿入するこの方法は比較的複雑です。まず、挿入する位置が範囲外かどうかを判断します。範囲外ではない場合は、リンク リストの状況に応じて判断します。リンク リストが空の場合、挿入されるノードは最初の要素であり、先頭ノードと末尾ノードのポインタは新しく作成されたノードを直接指します。リンク リストが空でない場合、挿入位置には、最初の位置に挿入、最後に挿入、および中央に挿入の 3 つの状況があります。具体的な操作は以下のとおりです。 DoublyLinkedList.prototype.insert = function(位置,データ){ var newNode = 新しいノード(データ); //範囲外の判定。満たされない場合は false を返す if(位置<0 || 位置>この長さ){ false を返します。 }それ以外{ //再度判断する//リンクリストが空の場合は直接挿入するif(position==0){ ノードを新規作成します。 this.tail = newNode; }それ以外 { //リンクリストが空でない場合 //挿入位置が末尾にある場合 if(position == this.length){ this.tail.next = 新しいノード; newNode.prev = this.tail; this.tail = newNode; }それ以外の場合(位置 == 0){ //挿入位置が最初のノードの場合 this.head.prev = newNode; Node.next = this.head; ノードを新規作成します。 }それ以外{ //挿入位置が中央にある場合 var index = 0; var 現在の = this.head; while(インデックス++ <位置){ 現在の = 現在の.次; } 現在のノードを次に示します。 newNode.prev = current.prev; 現在のノードを新しいノードに変更します。 現在のノードを新しいノードに変更します。 } this.length += 1; } } } 検証: 以下に示すように、位置 1 に リストを挿入(1,'xl') console.log(リスト.toString()); 実行結果は次のとおりです。 検証に成功しました。 4. get(position): 対応する位置にある要素を取得するこのメソッドは、まず位置が範囲外かどうかを判定します。範囲外ではない場合は、一時ノードとインデックスを定義し、一時ノードのポインタが先頭ノードを指すようにします。一時ノードをトラバースし、インデックスを増分します。トラバースしたノードの位置が取得する要素の位置と等しい場合は、一時ノードの対応する位置にある要素が取得する要素になります。 DoublyLinkedList.prototype.get = function(position){ if(位置<0 || 位置>=this.length){ false を返します。 }それ以外{ var インデックス = 0; var 現在の = this.head; while(インデックス++ <位置){ 現在の = 現在の.次; } 現在のデータを返します。 } } 検証: 位置 = 2 の要素をクエリする console.log('list.get(2):'+list.get(2)); 結果は次のとおりです。 検証に成功しました。 ただし、この検索方法には欠点があります。つまり、前から後ろにしか検索できないため、場合によっては非常に非効率的になります。そのため、両端から検索することができます。具体的な検索方法は、検索するノードの位置がリンクリストの長さの半分以下の場合は、前から後ろに検索できます。検索するノードの位置が長さの半分より大きい場合は、後ろから前に検索します。実装コードは次のとおりです。 DoublyLinkedList.prototype.get = function(position){ if(位置<0 || 位置>=this.length){ false を返します。 }それ以外{ var len = Math.floor(this.length/2); if(位置<=長さ){ var インデックス = 0; var 現在の = this.head; while(インデックス++ <位置){ 現在の = 現在の.次; } }それ以外{ var インデックス = this.length-1; var 現在の値 = this.tail; while(インデックス->位置){ 現在の = 現在の.前の; } } 現在のデータを返します。 } } 5. indexOf(要素): リスト内の要素のインデックスを返します一時ノードとインデックスを作成し、一時ノードを先頭ノードに向け、順に逆方向にトラバースして、インデックスを増やします。トラバースした一時ノードによって取得された要素が指定した要素と等しい場合、この時点での一時ノードの位置が目標位置となり、この位置のインデックスが目標値のインデックスとなります。 DoublyLinkedList.prototype.indexOf = function(data){ var 現在の = this.head; var インデックス = 0; while(現在){ (現在のデータ === データ) の場合 { インデックスを返します。 } 現在の = 現在の.次; インデックス++; } -1 を返します。 } 検証に成功しました。 6. update(position, ele): 特定の位置にある要素を変更するまず、変更する位置が範囲外かどうかを判断します。範囲外でない場合は、一時ノードとインデックスを定義し、一時ノードが先頭ノードを指すようにし、インデックス位置を 0 にして、一時ノードをトラバースし、この時点での一時ノードのインデックスが変更する要素の位置と等しいかどうかを判断します。等しい場合は、この時点での一時ノードの位置が変更する要素の位置であり、一時ノードのデータ領域で要素を直接変更できます。 DoublyLinkedList.prototype.update = function(position,newData){ if(位置<0 || 位置>=this.length){ false を返します。 }それ以外{ var インデックス = 0; var 現在の = this.head; while(インデックス++ <位置){ 現在の = 現在の.next; } 現在のデータ = 新しいデータ; true を返します。 } } 検証: 位置0のデータ リストを更新(0,'rc') console.log("list.update(0,'rc') は:"); console.log(リスト.toString()); 検証に成功しました。 7. removeAt(position): リストの指定された位置から項目を削除しますこのメソッドは、まず境界を越えたかどうかを判定する点で DoublyLinkedList.prototype.removeAt = function(position){ if(位置<0 || 位置>=this.length){ null を返します。 }それ以外{ var 現在の = this.head; if(this.length === 1){ //リンクリストの長さは1です this.head = null; this.tail = null }else{//リンクリストの長さが1ではない if(位置 === 0){ // 最初の場所を削除します this.head.next.prev = null; this.head = this.head.next; }そうでない場合(位置 === this.length-1){ this.tail.prev.next = null; this.tail = this.tail.prev; }それ以外{ var インデックス = 0; while(インデックス++ <位置){ 現在の = 現在の.次; } 現在のページを次に示します。 現在の次の前; } } this.length -=1; 現在のデータを返します。 } } 検証: 位置 3 のデータを削除します。 リスト.削除(3) console.log("list.removeAt(3) は:"); console.log(リスト.toString()); 結果は次のとおりです。 検証成功 8. remove(要素): リストから項目を削除する
DoublyLinkedList.prototype.remove = function(data){ var index = this.indexOf(データ); this.removeAt(index) を返します。 } 検証: データが リストを削除します('rc'); console.log("list.remove('rc') は:"); console.log(リスト.toString()); 9. isEmpty(): リンクリストが空かどうかを判定するリンク リスト内の要素数がゼロかどうかを直接判断します。ゼロの場合は空なので true を返します。それ以外の場合は空ではないので false を返します。 DoublyLinkedList.prototype.isEmpty = 関数(){ this.length == 0 を返します。 } 確認する: console.log("リンクリストは空ですか: "+list.isEmpty()); 10. size(): リンクリストに含まれる要素の数を返しますリンクリストの長さは要素の数です。 DoublyLinkedList.prototype.size = function(){ this.length を返します。 } 確認する: console.log("リンクリスト内の要素数は: "+list.size()); 以上がJavaScriptの双方向リンクリストの実装プロセス分析の詳細です。JavaScriptの双方向リンクリストの詳細については、123WORDPRESS.COMの他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
目次1. MySQLをダウンロードする2. 圧縮パッケージを解凍する3. MySQLを初期化する4....
解決策1完全にアンインストールしてすべてのデータを削除します。まず、MySQLに関連するすべてのプロ...
目次1. カスタム指示1. グローバルカスタム指示を登録する2. グローバルカスタム指示を使用する3...
今日ログインページを書いていたとき、個人情報と携帯電話番号を認証する必要がありましたが、ページにボタ...
目次1. コンポーネント2. キープアライブ2.1 問題点2.2 キープアライブを使って解決する2....
皆さんもJDを使ったことがあると思います。ホームページには非常によく見られる機能があります。階段の特...
vue スキャフォールディング -> vue.cli大規模で完全に機能する Vue プロジェク...
アプリケーション例ウェブサイト http://www.uhuigou.net画像の動的読み込みは目新...
効果画像: 1. はじめに独自のアプレットでこのような機能を実装する必要がある1. 核となる考え方ス...
実際の使用では、ミニプログラムを友人や友人サークルと共有する必要があることが多く、通常は一度に 1 ...
画像をダウンロード docker プル openjdkデータボリュームの作成java_appデータボ...
目次環境仮想マシンバージョンMySQL バージョン事前準備MySQLの実行ステータスを確認するルート...
コアコード <!DOCTYPE html> <html lang="ja...
事前に言っておくNodejs はデータベースを非同期操作として読み取るため、データベースがデータを読...
この記事では主に、HTML+CSS で階層化ピラミッドを実装する例を紹介し、皆さんと共有します。詳細...