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

C++で双方向リンクリストの指定位置にあるノードを削除する方法

このチュートリアルでは、C++を使って双方向リンクリスト(doubly linked list)から、指定された位置にあるノードを削除する方法を解説します。

問題を解くための手順

まずは、全体の流れを確認しましょう。

  • データ本体と prev(前)・next(次)の2つのポインタを持つ構造体を定義します。
  • 双方向リンクリストにノードを挿入する関数を作成します。
  • ダミーデータを使ってリンクリストを初期化します。
  • 削除対象となるノードの位置(position)を設定します。
  • リンクリストを先頭から走査し、指定位置に該当するノードを見つけます。
  • ノードを削除する関数を実装します。削除時には、以下の3つのケースを考慮する必要があります。
  • 先頭ノードの場合: headポインタを次のノードへ移動させます。
  • 中間ノードの場合: 前のノードと次のノード同士を直接連結します。
  • 末尾ノードの場合: 前のノードからのリンクを解除します。

実装例

それでは、実際のコードを見てみましょう。

#include <bits/stdc++.h>
using namespace std;

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

// 指定ノードを削除する関数
void deleteNode(struct Node** head_ref, struct Node* del) {
    if (*head_ref == NULL || del == NULL) {
        return;
    }
    // 先頭ノードの場合
    if (*head_ref == del) {
        *head_ref = del->next;
    }
    // 中間ノードの場合
    if (del->next != NULL) {
        del->next->prev = del->prev;
    }
    // 末尾ノードの場合
    if (del->prev != NULL) {
        del->prev->next = del->next;
    }
    free(del);
}

// 指定位置のノードを削除する関数
void deleteNodeAtGivenPosition(struct Node** head_ref, int n) {
    if (*head_ref == NULL || n <= 0) {
        return;
    }
    struct Node* current = *head_ref;
    // n番目のノードまで移動
    for (int i = 1; current != NULL && i < n; i++) {
        current = current->next;
    }
    if (current == NULL) {
        return;
    }
    deleteNode(head_ref, current);
}

// リンクリストの先頭にノードを挿入する関数
void insertNode(struct Node** head_ref, int new_data) {
    struct Node* new_node = (struct 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 printLinkedList(struct Node* head) {
    while (head != NULL) {
        cout << head->data << "->";
        head = head->next;
    }
}

int main() {
    struct Node* head = NULL;
    insertNode(&head, 5);
    insertNode(&head, 2);
    insertNode(&head, 4);
    insertNode(&head, 8);
    insertNode(&head, 10);

    cout << "削除前の双方向リンクリスト" << endl;
    printLinkedList(head);

    int n = 2;
    deleteNodeAtGivenPosition(&head, n);

    cout << "\n削除後の双方向リンクリスト" << endl;
    printLinkedList(head);

    return 0;
}

実行結果

上記のプログラムを実行すると、以下のような出力が得られます。

削除前の双方向リンクリスト
10->8->4->2->5->
削除後の双方向リンクリスト
10->4->2->5->

コードのポイント

このプログラムでは、insertNode関数が常にリストの先頭に新しいノードを挿入するため、挿入順序とは逆の「10→8→4→2→5」という並びになります。位置 n = 2 を指定して削除すると、2番目のノードである「8」が取り除かれ、「10→4→2→5」という結果になります。

削除処理では、del->next や del->prev がNULLかどうかを必ずチェックすることで、先頭・中間・末尾のどの位置のノードでも安全に削除できるようになっています。

まとめ

本チュートリアルについて不明な点や質問がある場合は、コメント欄でお気軽にお知らせください。

  1. C++でマルチレベル連結リストをフラット化する方法を解説

    この記事では、マルチレベル連結リスト(Multilevel Linked List)をフラット化するプログラムをC++で作成する方法について解説します。フラット化とは、第1レベルのノードをすべて先に並べ、その後に第2レベルのノードが続くように、階層構造を持つリストを1本の直線的な連結リストへ変換する操作のことです。マルチレベル連結リストとはマルチレベル連結リストとは、多次元的なデータ構造の一種です。各ノードは2つのポインタを持ちます。1つは次のノードを指す「next」ポインタ、もう1つは1つ以上のノードからなる子リストを指す「child」ポインタです。この子ポインタは、他のリストのノードを指す

  2. C++で循環双方向リンクリスト(Circular Doubly Linked List)を実装する方法

    データ構造におけるリンクリスト(連結リスト)とは、データ要素を線形に格納するコレクションです。リストの各要素(ノード)は「データ本体」と「次のノードへの参照(ポインタ)」という2つの項目で構成され、最後のノードは null への参照を持ちます。また、リンクリストの入口となるノードは「ヘッド(head)」と呼ばれます。循環双方向リンクリスト(Circular Doubly Linked List)では、隣り合う2つの要素が previous(前)ポインタと next(次)ポインタによって相互に接続されています。さらに特徴的なのは、末尾のノードが next ポインタで先頭ノードを指し、先頭のノード