線形リストは、同じ特性を持つデータ要素の有限シーケンスです。実際の応用で広く使用されるデータ構造であり、順序リスト、リンクリスト、スタック、キューなどが含まれます。
ここでは、連続リスト(順序リスト)を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;
}