C言語での単方向リスト:先頭へのノード挿入実装

連結リストのノード構造体定義

C言語における単方向リストの各要素は、データを保持するフィールドと、次の要素へのメモリアドレスを持つ構造体として定義されます。

typedef struct ListItem {
    int value;
    struct ListItem* link;
} ListItem;

リスト先頭へのノード挿入ロジック

リストを新規作成する際、最初は要素が存在しないため、先頭ポインタはNULLを指します。

ListItem* start = NULL;

新しいノードをリストの先頭に追加するには、ヒープ領域にメモリを割り当て、データを設定した後、その新しいノードをリストの新しい先頭として繋ぎ替えます。ここでは、呼び出し元で先頭ポインタを直接更新できるよう、ポインタへのポインタ(ダブルポインタ)を引数に取る設計を採用します。

void addFront(ListItem** startRef, int val) {
    ListItem* freshNode = (ListItem*)malloc(sizeof(ListItem));
    freshNode->value = val;
    freshNode->link = *startRef;
    *startRef = freshNode;
}

リストが空の状態では、*startRefNULLです。freshNode->linkNULLが代入され、*startReffreshNodeを指すようになります。これにより、最初のノードが正しく設定されます。

既存のノードが存在する場合は、freshNode->linkが現在の先頭ノードを指すように設定され、その後*startReffreshNodeのアドレスに更新されます。結果として、新しいノードがリストの先頭に配置されます。

実装の全体像

先頭への挿入処理に加え、リストの全要素を順番に出力する関数displayListを実装し、動作確認を行えるようにした完全なコードは以下の通りです。

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

typedef struct ListItem {
    int value;
    struct ListItem* link;
} ListItem;

void addFront(ListItem** startRef, int val) {
    ListItem* freshNode = (ListItem*)malloc(sizeof(ListItem));
    freshNode->value = val;
    freshNode->link = *startRef;
    *startRef = freshNode;
}

void displayList(ListItem* current) {
    printf("List: ");
    while (current != NULL) {
        printf("%d ", current->value);
        current = current->link;
    }
    printf("\n");
}

int main() {
    ListItem* start = NULL;
    int count, i, val;

    printf("How many elements to add?\n");
    scanf("%d", &count);

    for (i = 0; i < count; i++) {
        printf("Enter value: \n");
        scanf("%d", &val);
        addFront(&start, val);
        displayList(start);
    }
    
    return 0;
}

タグ: C言語 連結リスト データ構造 ポインタ 動的メモリ割り当て

7月9日 00:46 投稿