連続リストの初期化と基本操作

線形リストは、同じ特性を持つデータ要素の有限シーケンスです。実際の応用で広く使用されるデータ構造であり、順序リスト、リンクリスト、スタック、キューなどが含まれます。

ここでは、連続リスト(順序リスト)をC言語で実装し、初期化、追加、削除、検索、更新といった基本操作を行います。

1. 連続リストの初期化

以下のように、連続リストの構造体と関数を定義します。この構造体には、データ配列へのポインタ、要素数、容量が含まれます。

#define SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int ListElement;

#define DEFAULT_CAPACITY 5

typedef struct ContinuousList {
    ListElement* array;
    int elementCount;
    int maxCapacity;
} CL;

// 初期化関数
void CLInit(CL* list);
// 破棄関数
void CLDestroy(CL* list);
// 印刷関数
void CLPrint(CL* list);
// リスト末尾に追加
void CLAppend(CL* list, ListElement value);
// 容量チェック関数
void CLCheckSpace(CL* list);
// 指定位置に挿入
void CLInsert(CL* list, int index, ListElement value);

次に、初期化関数を以下のように実装します:

void CLInit(CL* list) {
    list->array = (ListElement*)malloc(sizeof(ListElement) * DEFAULT_CAPACITY);
    if (list->array == NULL) {
        perror("メモリ割り当て失敗");
        return;
    }
    list->elementCount = 0;
    list->maxCapacity = DEFAULT_CAPACITY;
}

2. リストの破棄

リストの使用が終わったら、メモリを解放する必要があります:

void CLDestroy(CL* list) {
    free(list->array);
    list->array = NULL;
    list->elementCount = 0;
    list->maxCapacity = 0;
}

3. リストの印刷

リストの内容を表示するための簡単な関数です:

void CLPrint(CL* list) {
    for (int i = 0; i < list->elementCount; ++i) {
        printf("%d ", list->array[i]);
    }
    printf("\n");
}

4. 要素の追加

リストの末尾に新しい要素を追加します。必要に応じて、容量の拡張も行います。

void CLAppend(CL* list, ListElement value) {
    CLInsert(list, list->elementCount, value);
}

void CLInsert(CL* list, int pos, ListElement value) {
    assert(pos >= 0 && pos <= list->elementCount);
    CLCheckSpace(list);

    for (int i = list->elementCount - 1; i >= pos; --i) {
        list->array[i + 1] = list->array[i];
    }

    list->array[pos] = value;
    ++list->elementCount;
}

5. 容量チェックと拡張

リストが満杯になった場合、容量を拡張します:

void CLCheckSpace(CL* list) {
    if (list->elementCount == list->maxCapacity) {
        ListElement* temp = (ListElement*)realloc(list->array, sizeof(ListElement) * list->maxCapacity * 2);
        if (temp == NULL) {
            perror("メモリ再割り当て失敗");
            return;
        }
        list->array = temp;
        list->maxCapacity *= 2;
    }
}

6. リスト先頭への追加

リストの先頭に要素を追加する場合、全ての要素を後方に一つずらす必要があります:

void CLPrepend(CL* list, ListElement value) {
    CLInsert(list, 0, value);
}

7. リスト末尾からの削除

リストの最後の要素を削除します:

void CLRemoveLast(CL* list) {
    if (list->elementCount > 0) {
        --list->elementCount;
    }
}

8. データの検索

指定された値がリスト内にあるかどうかを確認し、そのインデックスを返します:

int CLFind(CL* list, ListElement value) {
    for (int i = 0; i < list->elementCount; ++i) {
        if (list->array[i] == value) {
            return i;
        }
    }
    return -1;
}

タグ: C データ構造 連続リスト メモリ管理

6月28日 02:57 投稿