C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++のリンクリストでM個のノードの後にN個のノードを削除する方法

本記事では、C++におけるリンクリスト(連結リスト)の先頭からM個のノードを残し、その直後のN個のノードを削除するアルゴリズムについて解説します。

リンクリストの定義

まず、データ(data)と次のノードへのポインタ(next)を持つリンクリストの構造体を定義します。

struct Node {
   int data;
   struct Node* next;
};

リスト生成用関数 createList

次に、Nodeへのダブルポインタとint型の値を受け取る createList(Node **headPtr, int new_data) 関数を作成します。関数内では、新しく作成したノードのnextポインタに現在のheadPtrを代入し、その後headPtrに新しいノードを設定することで、リストの先頭にノードを追加していきます。

void createList(Node ** headPtr, int new_data){
   Node* newNode = new Node();
   newNode->data = new_data;
   newNode->next = (*headPtr);
   (*headPtr) = newNode;
}

削除処理 deleteNnodesAfterM

deleteNnodesAfterM(Node *head, int M, int N) メソッドは、先頭ノードとM・Nの値を受け取ります。関数内では、Node* current にheadを代入し、作業用ポインタとして Node *t も宣言します。

void deleteNnodesAfterM(Node *head, int M, int N){
   Node *current = head, *t;
   int nodeCount;

関数の中核となるのは、currentがNULLを指すまで繰り返されるwhileループです。ループ内の最初のforループはM回繰り返され、終了時点でcurrentポインタは「M個目のノード」を指しています。その後、Node *t には current->next、つまり削除対象となる最初のノードが代入されます。

while (current){
   for (nodeCount = 1; nodeCount < M && current!= NULL; nodeCount++)
   current = current->next;
   if (current == NULL)
      return;
   t = current->next;

続く2番目のforループはN回繰り返され、tが指す位置から順にN個のノードをfree()で解放します。削除完了後、current->next にtを再接続してリンクを修復し、current をtへ進めることで、次の区間の処理へ移行します。

for (nodeCount = 1; nodeCount<=N && t!= NULL; nodeCount++){
   Node *temp = t;
   t = t->next;
   free(temp);
}
current->next = t;
current = t;

リスト表示用関数 printList

最後に、先頭ポインタを受け取ってリンクリスト全体を標準出力に表示する printList(Node *head) 関数です。

void printList(Node *head){
   Node *temp = head;
   while (temp != NULL){
      cout<<temp->data<<" ";
      temp = temp->next;
   }
   cout<<endl;
}

実装例

それでは、リンクリストのM個のノードの後にN個のノードを削除する完全な実装を見てみましょう。

#include <iostream>
using namespace std;
struct Node{
   int data;
   Node *next;
};
void createList(Node ** headPtr, int new_data){
   Node* newNode = new Node();
   newNode->data = new_data;
   newNode->next = (*headPtr);
   (*headPtr) = newNode;
}
void printList(Node *head){
   Node *temp = head;
   while (temp != NULL){
      cout<<temp->data<<" ";
      temp = temp->next;
   }
   cout<<endl;
}
void deleteNnodesAfterM(Node *head, int M, int N){
   Node *current = head, *t;
   int nodeCount;
   while (current){
      for (nodeCount = 1; nodeCount < M && current!= NULL; nodeCount++)
      current = current->next;
      if (current == NULL)
      return;
      t = current->next;
      for (nodeCount = 1; nodeCount<=N && t!= NULL; nodeCount++){
         Node *temp = t;
         t = t->next;
         free(temp);
      }
      current->next = t;
      current = t;
   }
}
int main(){
   Node* head = NULL;
   int M=2, N=2;
   createList(&head, 2);
   createList(&head, 4);
   createList(&head, 6);
   createList(&head, 8);
   createList(&head, 10);
   createList(&head, 12);
   createList(&head, 14);
   cout << "M = " << M<< " N = " << N<<endl;
   cout<< "Original linked list :"<<endl;
   printList(head);
   deleteNnodesAfterM(head, M, N);
   cout<<"Linked list after deletion :"<<endl;
   printList(head);
   return 0;
}

実行結果

上記のコードを実行すると、以下のような出力が得られます。M=2、N=2の場合、「2個残して2個削除」をリスト末尾まで繰り返していることが確認できます。

M = 2 N = 2

Original linked list :
14 12 10 8 6 4 2

Linked list after deletion :
14 12 6 4
  1. C++で循環リンクリストのノード数をカウントする方法

    ノードから構成される循環リンクリスト(Circular Linked List)が与えられ、そのリスト内に存在するノードの総数を求めるのが課題です。 循環リンクリストとは、連結リストの一種であり、最初の要素が最後の要素を指し、最後の要素が最初の要素を指すという特徴を持つデータ構造です。片方向リンクリスト(Singly Linked List)でも双方向リンクリスト(Doubly Linked List)でも、この循環リンクリストとして実装することが可能です。 以下のプログラムでは、片方向リンクリストを循環リンクリストとして実装し、その中に含まれるノード数をカウントする方法を紹介します。 具体

  2. Pythonで連結リストのm個のノードを保持した後にn個のノードを削除するプログラム

    始点ノードが「head」である連結リストと、2つの整数 m と n が与えられたとします。リストを走査しながら、先頭から数えて m 個のノードを残した直後の n 個のノードを削除する処理を、連結リストの末尾に到達するまで繰り返します。処理は head ノードから開始し、最後に変更後の連結リストを返します。今回扱う連結リストの構造は次のように定義されています。Node value : <整数値> next : <次のノードへのポインタ>例えば、入力が elements = [1, 2, 3, 4, 5, 6, 7, 8]、m = 3、n = 1 の場合、出