C++で双方向リンクリストから偶数ノードをすべて削除する方法
このチュートリアルでは、C++を使って双方向リンクリスト(二重リンクリスト)から偶数のデータを持つノードをすべて削除する方法を解説します。
解決の手順
問題を解決するための流れは以下の通りです。
- データ(data)、前ポインタ(prev)、次ポインタ(next)を持つ構造体を定義します。
- 双方向リンクリストに新しいノードを挿入する関数を作成します。
- ダミーデータを使って双方向リンクリストを初期化します。
- リンクリストを走査し、現在のノードのデータが偶数かどうかを判定します。
- データが偶数であれば、そのノードを削除します。
- ノードを削除する関数を作成します。削除時には以下の3つの場合分けを考慮する必要があります。
- 先頭ノードの場合: ヘッドポインタを次のノードへ移動させます。
- 中間ノードの場合: 前のノードと次のノードを直接つなぎ合わせます。
- 末尾ノードの場合: 前のノードからのリンクを解除します。
サンプルコード
それでは、実際のコードを見てみましょう。
#include <bits/stdc++.h>
using namespace std;
struct Node {
int data;
Node *prev, *next;
};
// 新しいノードを先頭に挿入する関数
void insertNode(Node** head_ref, int new_data) {
Node* new_node = (Node*)malloc(sizeof(struct Node));
new_node->data = new_data;
new_node->prev = NULL;
new_node->next = (*head_ref);
if ((*head_ref) != NULL) {
(*head_ref)->prev = new_node;
}
(*head_ref) = new_node;
}
// 指定されたノードを削除する関数
void deleteNode(Node** head_ref, Node* del) {
if (*head_ref == NULL || del == NULL) {
return;
}
// 先頭ノードを削除する場合
if (*head_ref == del) {
*head_ref = del->next;
}
// 中間・末尾ノードの場合:次ノードのprevを更新
if (del->next != NULL) {
del->next->prev = del->prev;
}
// 中間・末尾ノードの場合:前ノードのnextを更新
if (del->prev != NULL) {
del->prev->next = del->next;
}
free(del);
return;
}
// 偶数ノードをすべて削除する関数
void deleteEvenNodes(Node** head_ref) {
Node* temp = *head_ref;
Node* next;
while (temp != NULL) {
next = temp->next; // 削除前に次ノードを保存
if (temp->data % 2 == 0) {
deleteNode(head_ref, temp);
}
temp = next;
}
}
// リンクリストを出力する関数
void printLinkedList(Node* head) {
while (head != NULL) {
cout << head->data << " -> ";
head = head->next;
}
}
int main() {
Node* head = NULL;
insertNode(&head, 1);
insertNode(&head, 2);
insertNode(&head, 3);
insertNode(&head, 4);
insertNode(&head, 5);
insertNode(&head, 6);
cout << "Linked List before deletion:" << endl;
printLinkedList(head);
deleteEvenNodes(&head);
cout << "\nLinked List after deletion:" << endl;
printLinkedList(head);
}実行結果
上記のプログラムを実行すると、以下のような出力が得られます。
Linked List before deletion: 6 -> 5 -> 4 -> 3 -> 2 -> 1 -> Linked List after deletion: 5 -> 3 -> 1 ->
ポイントの解説
このアルゴリズムで重要なのは、deleteEvenNodes 関数内でノードを削除する前に次のノードへのポインタを変数 next に保存しておく点です。ノードを削除するとそのメモリが解放されるため、削除後に temp->next にアクセスすると未定義動作を引き起こす可能性があります。
また、deleteNode 関数では先頭・中間・末尾の3パターンすべてに対応できるよう、ポインタの付け替えを慎重に行っています。これにより、どの位置のノードを削除してもリンクリストの整合性が保たれます。
まとめ
本チュートリアルでは、C++における双方向リンクリストから偶数ノードを削除する実装方法を学びました。ノード挿入、ノード削除、条件付き削除という一連の処理は、リンクリスト操作の基礎となる重要なテクニックです。チュートリアルについて質問がある場合は、コメント欄でお気軽にお尋ねください。
-
【C++】循環リンクリストのノード値の合計を求める方法
この記事では、循環リンクリスト(Circular Linked List)が与えられたときに、すべてのノードの値の合計を求めるプログラムをC++で作成する方法を解説します。 やるべきことはシンプルで、リンクリストを構成する全ノードの値を順番に読み取り、それらを加算していくだけです。 前提知識:重要な定義 リンクリストとは リンクリスト(連結リスト)とは、各データ(ノード)をポインタによるリンクで相互に接続したデータ構造の列です。配列と異なり、メモリ上の連続した領域を必要とせず、動的な挿入や削除に強いという特徴があります。 循環リンクリストとは 循環リンクリストはリンクリストの変形の一種で、先
-
【Python】双方向リンクリストの先頭からノードを削除する方法
双方向リンクリスト(二重連結リスト)の先頭からノードを削除するには、まず「Node」クラスを作成する必要があります。このクラスには、ノードが保持するデータ(data)、リンクリスト内の次のノードへの参照(next)、前のノードへの参照(prev)という3つの属性を定義します。 以下に、具体的な実装例を示します。 サンプルコード class Node: def __init__(self, my_data): self.prev = None self.data = my_data self.next = None class doubl