双方向リスト実装編《連結リスト》

連結リストメニュー【双方向リスト実装編  step 1 〜 全8問】

【双方向リスト実装編全9問のまとめ】

reader.on('close', () => {
   const max_size = 1024;
   const end_ptr = 1023;
   let start_ptr = 0;
   let empty_min_idx = 1;  // 空要素のindex
   const Value = new Array(max_size);
   const Next_Ptr = new Array(max_size);
   const Prev_Ptr = new Array(max_size);
   [Value[start_ptr], Value[end_ptr]] = [-1, -1];
   [Next_Ptr[start_ptr], Next_Ptr[end_ptr]] = [end_ptr, -1];
   [Prev_Ptr[start_ptr], Prev_Ptr[end_ptr]] = [-1, start_ptr];

   function push_back(val) {  // step 1
      const new_ptr = empty_min_idx;  // Value[empty_min_idx] = a;
      Value[new_ptr] = val;
      Next_Ptr[Prev_Ptr[end_ptr]] = new_ptr;
      Next_Ptr[new_ptr] = end_ptr;  // 配列 Next_Ptr を変更
      Prev_Ptr[new_ptr] = Prev_Ptr[end_ptr]; // 配列 Prev_Ptr を変更
      Prev_Ptr[end_ptr] = new_ptr;  // 配列 Prev_Ptr を変更
      empty_min_idx++;
   }

   function push_front(val) {  // step 2 
      const new_ptr = empty_min_idx;
      Value[new_ptr] = val;
      Next_Ptr[new_ptr] = Next_Ptr[start_ptr];
      Next_Ptr[start_ptr] = new_ptr;
      Prev_Ptr[Next_Ptr[new_ptr]] = new_ptr;
      Prev_Ptr[new_ptr] = start_ptr;
      empty_min_idx++;
   }

   function Remove_from_end() {  // step 3
      const back_ptr = Prev_Ptr[end_ptr];
      if (back_ptr !== start_ptr) {
         Next_Ptr[Prev_Ptr[back_ptr]] = end_ptr;
         Prev_Ptr[end_ptr] = Prev_Ptr[back_ptr];
      }
   }

   function Remove_from_front() {  // step 4
      if (Next_Ptr[start_ptr] != end_ptr) {
         const back_ptr = Next_Ptr[start_ptr];
         Next_Ptr[start_ptr] = Next_Ptr[back_ptr];
         Prev_Ptr[Next_Ptr[back_ptr]] = start_ptr;
      }
   }

   // 位置 pos に値 val を挿入する
   function insert(pos, val) {  // step 5
      pos--;
      const new_ptr = empty_min_idx;  // Valueval を保存する場所
      Value[new_ptr] = val;  // Valueval を追加
      let current_ptr = start_ptr;  // 現在のノード
      for (let i = 0; i < pos; i++) {
          // pos がリストのサイズより大きい場合
         if (current_ptr === end_ptr) {
            break;
         }
          current_ptr = Next_Ptr[current_ptr];
      }
      // 挿入したい箇所の直前までたどり着いた場合
      if (current_ptr != end_ptr) {
         Next_Ptr[new_ptr] = Next_Ptr[current_ptr];
         Prev_Ptr[Next_Ptr[new_ptr]] = new_ptr;
         Prev_Ptr[new_ptr] = current_ptr;
         Next_Ptr[ current_ptr] = new_ptr;
      }
      empty_min_idx++;
   }

   function Remove_from_pos(pos) {  // step 6
      let current_ptr = start_ptr;
      for (let i = 0; i <= pos - 1; i++) {
         // pos がリストのサイズより大きい場合
         if ( current_ptr === end_ptr) {
            break;
         }
         // 削除したい箇所の直前までたどり着いた場合
         if (i === pos - 1) {
            Next_Ptr[Next_Ptr[Next_Ptr[current_ptr]]] = current_ptr;
            Next_Ptr[ current_ptr] = Next_Ptr[Next_Ptr[current_ptr]];
            break;
         }
         current_ptr = Next_Ptr[current_ptr];
      }
   }

   function Remove_from_pos_to_pos(left, right) {
      let left_ptr = start_ptr;  // 削除したい区間の直前のインデックス
      for (i = 0; i < left - 1; i++) {
       // left がリストのサイズより大きい場合
         if (left_ptr === end_ptr) {
            break;
         }
         left_ptr = Next_Ptr[left_ptr];
      }
      let right_ptr = start_ptr;  // 削除したい区間の直後のインデックス
      // 削除したい区間の直後まで移動する
      for (let i = 0; i < right; i++) {
      // right_ptrend_ptr でも良いが、end_ptr の次のノードにはならない
         if (i < right && right_ptr === end_ptr) {
            right_ptr = -1;
            break;
         }
         right_ptr = Next_Ptr[right_ptr];
      }
      if (left_ptr !== end_ptr && right_ptr !== -1) {
          Next_Ptr[left_ptr] = right_ptr;
          Prev_Ptr[right_ptr] = left_ptr;
      }
   }
    
   function erase(pos) {
      let current_ptr = start_ptr;
      for (let i = 0; i <= pos; i++) {
         // pos がリストのサイズより大きい場合
         if (current_ptr === end_ptr) {
            break;
         }
         // 削除したい箇所の直前までたどり着いた場合
         if (i === pos) {
            Prev_Ptr[Next_Ptr[Next_Ptr[current_ptr]]] = current_ptr;
            Next_Ptr[current_ptr] = Next_Ptr[Next_Ptr[current_ptr]];
            break;
         }
          current_ptr = Next_Ptr[current_ptr];
      }
   }

   function display() {
      let current_ptr = start_ptr;
      while (current_ptr !== end_ptr) {
         if (current_ptr !== start_ptr) {
            console.log(Value[current_ptr]);
         }
          current_ptr = Next_Ptr[current_ptr];
      }
   }
   /* step 1
   const N = Number(lines[0]);
   for (let i = 1; i <= N; i++) {
      const n = Number(lines[i]);
      push_back(n);
   }
   */
   /* step 2
   const N = Number(lines[0]);
   for (let i = 1; i <= N; i++) {
      const n = Number(lines[i]);
      push_front(n);
   }
   */
   /* step 3
   const [N, K] = lines[0].split(' ').map(Number);
   for (let i = 1; i <= N; i++) {
      const n = Number(lines[i]);
      push_back(n);
   }
   for (let i = 0; i < K; i++) {
      Remove_from_end();
   }
   */
   /* step 4
   const [N, K] = lines[0].split(' ').map(Number);
   for (let i = 1; i <= N; i++) {
      const n = Number(lines[i]);
      push_back(n);
   }
   for (let i = 0; i < K; i++) {
      Remove_from_front();
   }
   */
   /* step 5
   const [N, P, X] = lines[0].split(' ').map(Number);
   for (let i = 1; i <= N; i++) {
      const n = Number(lines[i]);
      push_back(n);
   }
   insert(P, X);
   */
   /* step 6
   const [N, P] = lines[0].split(' ').map(Number);
   for (let i = 1; i <= N; i++) {
      const n = Number(lines[i]);
      push_back(n);
   }
   Remove_from_pos(P);
   */
   /* step 7
   const [N, L, R] = lines[0].split(' ').map(Number);
   for (let i = 1; i <= N; i++) {
      const n = Number(lines[i]);
      push_back(n);
   }
   Remove_from_pos_to_pos(L, R );
   */
   /* 完成
   const [N, Q] = lines[0].split(' ').map(Number);
   for (let i = 1; i <= N; i++) {
      const n = Number(lines[i]);
      push_back(n);
   }
   for (let i = N + 1; i <= N + Q; i++) {
      const q = lines[i].split(' ').map(Number);
      // console.log(q);
      switch (q[0]) {
      case 1:
         insert(q[1], q[2]);
         break;
      case 2:
         erase(q[1] - 1);
         break;
      }
   }
   */
   // console.log(Value);
   // console.log(Next_Ptr);
   // console.log(Prev_Ptr);
   display();
});
hogeちゃんの画像

ポインタと値を 区別して 出力値を制御…!!?? 解説の動画も公開されています。

【step 1 〜 完成 の function 】

reader.on('close', () => {
   const max_size = 1024;
   const end_ptr = 1023;
   let start_ptr = 0;
   let empty_min_idx = 1;  // 空要素のindex
   const Value = new Array(max_size);
   const Next_Ptr = new Array(max_size);
   const Prev_Ptr = new Array(max_size);
   [Value[start_ptr], Value[end_ptr]] = [-1, -1];
   [Next_Ptr[start_ptr], Next_Ptr[end_ptr]] = [end_ptr, -1];
   [Prev_Ptr[start_ptr], Prev_Ptr[end_ptr]] = [-1, start_ptr];
 
  function push_back(val) {
      const new_ptr = empty_min_idx; //Value[empty_min_idx] = a;
      Value[new_ptr] = val;
      Next_Ptr[Prev_Ptr[end_ptr]] = new_ptr;
      Next_Ptr[new_ptr] = end_ptr;  // 配列 Next_Ptr を変更
      Prev_Ptr[new_ptr] = Prev_Ptr[end_ptr];  // 配列 Prev_Ptr を変更
      Prev_Ptr[end_ptr] = new_ptr;  // 配列 Prev_Ptr を変更
      empty_min_idx++;
   }

   function push_front(val) {  // step 2 
      const new_ptr = empty_min_idx;
      Value[new_ptr] = val;
      Next_Ptr[new_ptr] = Next_Ptr[start_ptr];
      Next_Ptr[start_ptr] = new_ptr;
      Prev_Ptr[Next_Ptr[new_ptr]] = new_ptr;
      Prev_Ptr[new_ptr] = start_ptr;
      empty_min_idx++;
   }

   function Remove_from_end() {  // step 3
      const back_ptr = Prev_Ptr[end_ptr];
      if (back_ptr !== start_ptr) {
         Next_Ptr[Prev_Ptr[back_ptr]] = end_ptr;
         Prev_Ptr[end_ptr] = Prev_Ptr[back_ptr];
      }
   }

   function Remove_from_front() {  // 先頭の要素を表示しない
      if (Next_Ptr[start_ptr] != end_ptr) {
         const back_ptr = Next_Ptr[start_ptr];
         Next_Ptr[start_ptr] = Next_Ptr[back_ptr];
         Prev_Ptr[Next_Ptr[back_ptr]] = start_ptr;
      }
   }

   function insert(pos, val) {
      pos--;
      const new_ptr = empty_min_idx;  // Valueval を保存する場所
      Value[new_ptr] = val;  // Valueval を追加
      let current_ptr = start_ptr;  // 現在のノード
      for (let i = 0; i < pos; i++) {
         if ( current_ptr === end_ptr) {
            break;
         }
          current_ptr = Next_Ptr[ current_ptr];
      }
      if ( current_ptr != end_ptr) {
         Next_Ptr[new_ptr] = Next_Ptr[ current_ptr];
         Prev_Ptr[Next_Ptr[new_ptr]] = new_ptr;
         Prev_Ptr[new_ptr] =  current_ptr;
         Next_Ptr[ current_ptr] = new_ptr;
      }
      empty_min_idx++;
   }

   function Remove_from_pos(pos) {  // step 6
      let current_ptr = start_ptr;
      for (let i = 0; i <= pos - 1; i++) {
         if ( current_ptr === end_ptr) {
            break;
         } 
         if (i === pos - 1) {
            Prev_Ptr[Next_Ptr[Next_Ptr[ current_ptr]]] =  current_ptr;
            Next_Ptr[ current_ptr] = Next_Ptr[Next_Ptr[ current_ptr]];
            break;
         }
          current_ptr = Next_Ptr[ current_ptr];
      }
   }

   function Remove_from_pos_to_pos(left, right) {
      let left_ptr = start_ptr;  // 削除したい区間の直前のインデックス
      for (i = 0; i < left - 1; i++) {
      // left がリストのサイズより大きい場合
         if (left_ptr === end_ptr) {
            break;
         }
         left_ptr = Next_Ptr[left_ptr];
      }
      let right_ptr = start_ptr;  // 削除したい区間の直後のインデックス
      // 削除したい区間の直後まで移動する
      for (let i = 0; i < right; i++) {
      // right_ptrend_ptr でも良いが、end_ptr の次のノードにはならない
         if (i < right && right_ptr === end_ptr) {
            right_ptr = -1;
            break;
         }
         right_ptr = Next_Ptr[right_ptr];
      }
      if (left_ptr !== end_ptr && right_ptr !== -1) {
          Next_Ptr[left_ptr] = right_ptr;
          Prev_Ptr[right_ptr] = left_ptr;
      }
   }

   function erase(pos) {
      let current_ptr = start_ptr;
      for (let i = 0; i <= pos; i++) {    
         if ( current_ptr === end_ptr) {
            break;
         }
         if (i === pos) {
            Prev_Ptr[Next_Ptr[Next_Ptr[ current_ptr]]] =  current_ptr;
            Next_Ptr[ current_ptr] = Next_Ptr[Next_Ptr[ current_ptr]];
            break;
         }
          current_ptr = Next_Ptr[ current_ptr];
      }
   }

   function display() {
      let current_ptr = start_ptr;
      while ( current_ptr !== end_ptr) {
         if ( current_ptr !== start_ptr) {
            console.log(Value[ current_ptr]);
         }
          current_ptr = Next_Ptr[ current_ptr];
      }
   }  
});
hogeちゃんの画像

各問 の function のみ抜き出しました。アルゴリズムの問題なので 使いまわせるかも…。

コメント