記事ディレクトリ
1. リニアテーブル
線形リストは、同じプロパティを持つ n データ要素の有限シーケンスです。
線形テーブルは、実際に広く使用されているデータ構造です。一般的な線形テーブル: シーケンス テーブル、リンク リスト、スタック、キュー、文字列... 線形テーブルは、論理的には線形構造、つまり連続した直線です
。しかし、物理的な構造は必ずしも連続的であるとは限らず、線形テーブルを物理的に保存する場合、通常は配列や連鎖構造の形で保存される。
2. シーケンステーブル
1.コンセプト
順序テーブルは、データ要素を連続した物理アドレスで記憶装置に順次格納する線形構造であり、一般的には配列で格納される。アレイ上のデータを追加、削除、確認、変更します。
シーケンス テーブルは次のように分割できます。
- 静的シーケンス テーブル: 要素を格納するために固定長配列を使用します。
//顺序表静态存储
#define N 5
//这样写方便后期将int改为其他数据类型
typedef int SLDataType;
typedef struct SeqList
{
SLDataType arr[N];//定长数组
int size; //有效数据的个数
}SeqList;
- 動的シーケンス テーブル: 動的に開かれた配列ストレージを使用します。
//顺序表动态存储
typedef int SLDataType;
typedef struct SeqList
{
SLDataType* a;//指向动态开辟的数组
int size; //有效数据个数
int capicity;//空间的容量
}SeqList;
2. インターフェースの実装
静的シーケンス テーブルは、保存する必要があるデータの量がわかっているシナリオにのみ適しています。静的シーケンステーブルの固定長配列ではNが固定されるため、開きすぎるとスペースが無駄になり、開きすぎると不十分になります。したがって、実際に使用されるのは基本的にはダイナミックシーケンステーブル、スペース サイズを動的に割り当てる必要があるため、以下では動的シーケンス テーブルを実装します。
#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
//这样写方便后期将int改为其他数据类型
typedef int SLDateType;
//用一个结构体存放顺序表
typedef struct SeqList
{
SLDateType* a;//指向动态开辟的数组
int size; //有效数据个数
int capicity;//空间的容量
}SeqList;
// 对数据的管理:增删查改
//初始化顺序表
void SeqListInit(SeqList* ps);
//操作结束后释放空间
void SeqListDestroy(SeqList* ps);
//打印顺序表
void SeqListPrint(SeqList* ps);
//尾插
void SeqListPushBack(SeqList* ps, SLDateType x);
//头插
void SeqListPushFront(SeqList* ps, SLDateType x);
//头删
void SeqListPopFront(SeqList* ps);
//尾删
void SeqListPopBack(SeqList* ps);
// 顺序表查找
int SeqListFind(SeqList* ps, SLDateType x);
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* ps, int pos, SLDateType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* ps, int pos);
1>初期化シーケンス表
void SeqListInit(SeqList* ps)
{
//动态开辟内存
ps->a = (SLDateType*)malloc(sizeof(SLDateType) * 5);
if (ps->a == NULL)
{
perror("malloc failed");
exit(-1);
}
ps->size = 0;
ps->capacity = 5;
}
2> 操作後にスペースを解放する
void SeqListDestroy(SeqList* ps)
{
free(ps->a);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
3>印刷順序表
void SeqListPrint(SeqList* ps)
{
for (int i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
4> テールプラグ
順序表にデータを挿入する際、順序表が一杯かどうかを判定し、一杯の場合は容量を拡張する必要がありますが、拡張確認の動作を関数にカプセル化します。
//检查是否已满
void SeqListCheck(SeqList* ps)
{
//当数据个数与容量相等时代表顺序表满了
if (ps->size == ps->capacity)
{
//因为可能会异地扩容,先用另一个指针接收
//这里扩容到原来的2倍
SLDateType* tmp = (SLDateType*)realloc(ps->a, ps->capacity * 2 * (sizeof(SLDateType)));
if (tmp == NULL)
{
perror("realloc failed");
exit(-1);
}
ps->a = tmp;
ps->capacity *= 2;
}
}
末尾挿入では、シーケンス テーブルの最後にデータを追加し、サイズに 1 を加算するだけで済みます。
//尾插
void SeqListPushBack(SeqList* ps, SLDateType x)
{
SeqListCheck(ps);
ps->a[ps->size] = x;
ps->size++;
}
5>プラグ
ヘッド挿入では、最初にシーケンス テーブルがいっぱいかどうかを確認し、次にすべての要素を 1 つ右に移動してから、挿入する要素を最初の場所に配置する必要があります。ここでは、最後の要素から開始して右に移動する必要があります。そうでない場合、データは上書きされ、変更されます。
void SeqListPushFront(SeqList* ps, SLDateType x)
{
SeqListCheck(ps);
for (int i = ps->size - 1; i >= 0; i--)
{
ps->a[i + 1] = ps->a[i];
}
ps->a[0] = x;
ps->size++;
}
6> ヘッド削除
先頭を削除するには、すべての要素を 1 ビットだけ左に移動して、最初の要素 size-1 をカバーします。左に移動するには、要素が上書きされないように最初に左端の要素を移動する必要があります。
void SeqListPopFront(SeqList* ps)
{
//判断顺序表是否为空
assert(ps->size>0);
for (int i = 0; i < ps->size - 1; i++)
{
ps->a[i] = ps->a[i + 1];
}
ps->size--;
}
7> 末尾削除
末尾の削除はサイズ 1 にするだけでアクセスできなくなります
void SeqListPopBack(SeqList* ps)
{
//判断顺序表是否为空
assert(ps->size>0);
ps->size--;
}
8> シーケンステーブルの検索
シーケンス テーブルで x を検索し、その添字を返します。見つからない場合は、-1 を返します。
int SeqListFind(SeqList* ps, SLDateType x)
{
for (int i = 0; i < ps->size - 1; i++)
{
if (ps->a[i] == x)
{
return i;
}
}
return -1;
}
9>シーケンス テーブルの pos の位置に x を挿入します
pos 添え字と後続の要素を右に移動し (上書きを防ぐために最後の要素から右に移動する必要があります)、添え字 pos の位置に x を挿入します。
void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
//检查下标pos是否合法
assert(pos >= 0 && pos <= ps->size);
SeqListCheck(ps);
for (int i = ps->size - 1; i >= pos; i--)
{
ps->a[i + 1] = ps->a[i];
}
ps->a[pos] = x;
ps->size++;
}
10>シーケンステーブルのpos位置の値を削除
pos 添字の後ろの要素を 1 ビット左に移動し (上書きされないように左端の要素から開始します)、pos 添字の要素を削除します。
void SeqListErase(SeqList* ps, int pos)
{
//检查pos的合法性
assert(pos >= 0 && pos < ps->size);
for (int i = pos; i < ps->size - 1; i++)
{
ps->a[i] = ps->a[i + 1];
}
ps->size--;
}