シングルリンクリストの詳細な実装(C言語)

シングルリンクリストとは

シングルリンクリスト(Singly Linked List)は、データをノードとして格納し、各ノードが次のノードへのポインタを持つ線形データ構造です。配列や順序リスト(シーケンシャルリスト)と異なり、データの挿入・削除が柔軟で、必要に応じて動的にメモリを確保できます。

シングルリンクリストの構造

シングルリンクリストは、各ノードが2つの部分から成ります:

  • データ部: 実際のデータを格納
  • ポインタ部: 次のノードへの参照(アドレス)を保持

リストの末尾のノードは、NULLを指して終了します。

ノード構造体の定義

#pragma once

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int SLLDataType;

typedef struct SLLNode {
    SLLDataType data;
    struct SLLNode* next;
} Node;

基本操作の実装

ノードの作成

新しいノードを動的に確保し、初期値を設定します。

static Node* createNode(SLLDataType value) {
    Node* newNode = (Node*)malloc(sizeof(Node));
    if (!newNode) {
        exit(EXIT_FAILURE);
    }
    newNode->data = value;
    newNode->next = NULL;
    return newNode;
}

先頭への挿入(ヘッドインサート)

void pushFront(Node** head, SLLDataType value) {
    assert(head);
    Node* newNode = createNode(value);
    newNode->next = *head;
    *head = newNode;
}

末尾への挿入(テールインサート)

void pushBack(Node** head, SLLDataType value) {
    assert(head);
    Node* newNode = createNode(value);

    if (*head == NULL) {
        *head = newNode;
        return;
    }

    Node* current = *head;
    while (current->next != NULL) {
        current = current->next;
    }
    current->next = newNode;
}

先頭からの削除(ヘッドリムーブ)

void popFront(Node** head) {
    assert(head && *head);
    Node* temp = *head;
    *head = (*head)->next;
    free(temp);
}

末尾からの削除(テールリムーブ)

void popBack(Node** head) {
    assert(head && *head);
    if ((*head)->next == NULL) {
        free(*head);
        *head = NULL;
        return;
    }

    Node* current = *head;
    while (current->next->next != NULL) {
        current = current->next;
    }
    free(current->next);
    current->next = NULL;
}

リストの表示

void printList(const Node* head) {
    const Node* current = head;
    while (current) {
        printf("%d -> ", current->data);
        current = current->next;
    }
    printf("NULL\n");
}

指定位置への挿入

void insertAfter(Node* prevNode, SLLDataType value) {
    assert(prevNode);
    Node* newNode = createNode(value);
    newNode->next = prevNode->next;
    prevNode->next = newNode;
}

指定位置の削除

void erase(Node** head, Node* target) {
    assert(head && *head && target);
    if (*head == target) {
        *head = target->next;
        free(target);
        return;
    }

    Node* current = *head;
    while (current->next != target) {
        current = current->next;
    }
    current->next = target->next;
    free(target);
}

リストの破棄

void destroyList(Node** head) {
    assert(head);
    Node* current = *head;
    while (current) {
        Node* next = current->next;
        free(current);
        current = next;
    }
    *head = NULL;
}

シングルリンクリストの利点と欠点

  • 利点: データの挿入・削除が柔軟で高速
  • 欠点: ランダムアクセス不可、末尾の操作に時間がかかる

テストコード

int main() {
    Node* head = NULL;

    pushBack(&head, 10);
    pushBack(&head, 20);
    pushFront(&head, 5);
    printList(head);  // 出力: 5 -> 10 -> 20 -> NULL

    popBack(&head);
    printList(head);  // 出力: 5 -> 10 -> NULL

    insertAfter(head, 7);
    printList(head);  // 出力: 5 -> 7 -> 10 -> NULL

    erase(&head, head->next);
    printList(head);  // 出力: 5 -> 10 -> NULL

    destroyList(&head);
    return 0;
}

タグ: C言語 データ構造 シングルリンクリスト ポインタ 動的メモリ管理

5月15日 14:09 投稿