記事ディレクトリ
シーケンステーブル
シーケンステーブルは一種の線形構造です----シーケンシャルストレージ構造
この構造体は、メモリ内の連続したスペースを占有します(配列と同様)。
シーケンステーブルは、次の2つの方法で実装できます。
- 1つは、静的配列を使用して次のことを実現することです。
#define NUM 100
typedef struct SeqList{
int a[NUM];
int size;//表长
}SeqList;
NUMは配列のサイズであり、シーケンステーブルに配置できる要素の数です。
サイズを使用して、特定の瞬間に配列に配置された要素の数を記録できます。
- 1つは、動的開発を使用して達成することです
typedef struct SeqList {
SeqListType* list;
int size;//表长
int capacity;
}SeqList;
ポインタの使用と動的メモリ開発により、スペースのサイズを柔軟に制御できます
また、サイズを使用して、保存されている要素の数を記録します
容量は静的アレイのNUMに似ていますが、必要に応じて容量を拡張または削減できる点が異なります。
2つの比較:使用する前に実際に使用する必要のあるスペースの量を判断できないため、スペースのサイズを柔軟に制御できる動的開発の方法を使用します。
シーケンステーブルに実装する必要のある関数:
シーケンステーブルは、次の機能を実行できます。
//函数的声明
//顺序表的初始化----SeqListInit
//尾插一个元素----SeqListPushBack
//尾删一个元素----SeqListPopBack
//头插一个元素----SeqListPushFront
//头删一个元素----SeqListPopFront
//任何位置的元素插入----SeqListInsert
//任何位置的元素删除----SeqListErase
//检查容量----SeqListCheckCapacity
//销毁顺序表----SeqListDeStroy
次に、これらの関数を順番に実装します
シーケンステーブルの初期化
void SeqListInit(SeqList* psl)
{
assert(psl);
psl->capacity = 0;
psl->size = 0;
psl->list = NULL;
}
容量の初期値から開始することも、次のように初期値を0に割り当てることもできます。
シーケンステーブルの容量
注:シーケンステーブルを操作するときは、シーケンステーブルの容量がいっぱいかどうかに注意する必要があります。シーケンステーブルの容量がいっぱいの場合は、容量を拡張して、次の要素を追加し続けることができるようにする必要があります。シーケンステーブル。
void SeqListCheckCapacity(SeqList* psl)
{
assert(psl);//判断psl是否为空指针
if (psl->size == psl->capacity)
{
int newcapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;
//如果capacity的值为0(只有初始化的时候才可能为0),那么就将capacity 的值赋为4。
//如果caoacity的值不为0,那么就让容量翻倍。
SeqListType* tmp = (SeqListType*)realloc(psl->list, sizeof(SeqListType) * newcapacity);
if (tmp == NULL)
{
printf("realloc:fail\n");
exit(-1);
}
else
{
psl->list = tmp;
psl->capacity = newcapacity;
}
}
}
サイズと容量の値が同じ場合は、シーケンステーブルの容量がいっぱいであることを意味し、容量を拡張する必要があります
注:展開が成功したかどうかを判断する必要があります(tmpがnullポインターであるかどうかを判断します)。
シーケンスリストに要素を追加します
シーケンスリストの最後に要素を追加します
注:1。シーケンステーブルに要素を追加するたびに、シーケンステーブルの容量を確認する必要があります。
2.要素を追加するたびに、sizeの値を1ずつ増やす必要があります。
void SeqListPushBack(SeqList* psl, SeqListType x)
{
assert(psl);
SeqListCheckCapacity(psl);
psl->list[psl->size] = x;
psl->size++;
}
テールに要素を追加する場合
psl->list[psl->size]
は、割り当てたいアドレスです。サイズの値は簡単に取得できるため、テールに要素を追加する操作は非常に簡単です。
シーケンスリストの先頭に要素を追加します
void SeqListPushFront(SeqList* psl, SeqListType x)
{
assert(psl);
SeqListCheckCapacity(psl);
int begin = psl->size;
while (begin > 0)
{
psl->list[begin] = psl->list[begin - 1];
begin--;
}
psl->list[0] = x;
psl->size++;
}
シーケンステーブルの指定された位置に要素を追加します
void SeqListInsert(SeqList* psl, size_t pos, SeqListType x)
{
assert(psl);
if (pos > psl->size)
{
printf("越界");
}
SeqListCheckCapacity(psl);//检查容量
size_t begin = psl->size;
while (begin > pos)
{
psl->list[begin] = psl->list[begin - 1];
begin--;
}
psl->list[pos] = x;
psl->size++;
}
指定された位置に要素を追加することは、シーケンスリストの先頭に要素を追加することと非常に似ています。
ただし、要素を挿入する前に、渡されたパラメータが条件を満たすかどうかを判断する必要があります
挿入位置が異なれば、結果も異なります。
シーケンスリストから要素を削除します
シーケンステーブルで要素が削除されるたびに、サイズの値を1ずつ減らす必要があることに注意してください。
シーケンスリストの最後にある要素を削除します
//尾删一个元素
void SeqListPopBack(SeqList* psl)
{
assert(psl);
if (psl->size > 0)
{
psl->size--;
}
}
最後に要素を削除するには、テーブルの長さ(size)を1だけ減らす必要があります。これは、sizeを使用してシーケンステーブルにある要素の数を記録するためです。これは、最後の要素を削除することと同じです。
シーケンスリストの先頭にある要素を削除します
//头删一个元素
void SeqListPopFront(SeqList* psl)
{
assert(psl);
int begin = 1;
while (begin < psl->size)
{
psl->list[begin-1] = psl->list[begin];
begin++;
}
psl->size--;
}
要素テーブルの先頭にある要素を削除するには、シーケンステーブルの2番目の要素から開始し、最後の要素の値まで前方にカバーし、最後から2番目の要素の位置をカバーするだけです。テーブルの長さ(サイズ)から1を引いて、head要素の削除を完了します。
シーケンステーブルの指定された位置にある要素を削除します
void SeqListErase(SeqList* psl, size_t pos)
{
assert(psl);
assert(pos < psl->size);
size_t begin = pos+1;
while (begin < psl->size)
{
psl->list[begin-1] = psl->list[begin];
begin++;
}
psl->size--;
}
指定された位置にある要素を削除する方法は、head要素を削除する方法と似ています。
破壊命令表
動的メモリ開発の方法で実装されたシーケンステーブルを使用しているため、最終的に動的に開かれたスペースを解放する必要があります。
void SeqListDeStroy(SeqList* psl)
{
assert(psl);
free(psl->list);
psl->capacity = 0;
psl->size = 0;
psl->list = NULL;
}
シーケンステーブルの完全な実装
ヘッドファイルSeqList.h
#pragma once
//顺序表
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//结构的声明
//有两种顺寻标的声明,一种是静态的---以数组的形式
//另一种是动态的----动态内存开辟,第一种方式开辟出来的空间可能会不足,,也可能会浪费,所以我们采用动态内存开辟的方式
typedef int SeqListType;
typedef struct SeqList {
SeqListType* list;
int size;
int capacity;
}SeqList;
//一个顺序表要实现的功能有:在任何一个位置插入一个元素,
//在任何一个位置删除一个元素,修改元素,查找元素
//函数的声明
//顺序表的初始化
void SeqListInit(SeqList* psl);
//尾插一个元素
void SeqListPushBack(SeqList* psl, SeqListType x);
//尾删一个元素
void SeqListPopBack(SeqList* psl);
//头插一个元素
void SeqListPushFront(SeqList* psl, SeqListType x);
//头删一个元素
void SeqListPopFront(SeqList* psl);
//任何位置的元素插入
void SeqListInsert(SeqList* psl, size_t pos, SeqListType x);
//任何位置的元素删除
void SeqListErase(SeqList* psl, size_t pos);
//检查容量
void SeqListCheckCapacity(SeqList* psl);
//销毁顺序表
void SeqListDeStroy(SeqList* pal);
//打印顺序表的内容
void SeqListPrint(SeqList* psl);
ソースファイルSeqList.c
#define _CRT_SECURE_NO_WARNINGS 1
//函数实现
#include"SeqList.h"
//顺序表的初始化
void SeqListInit(SeqList* psl)
{
assert(psl);
psl->capacity = 0;
psl->size = 0;
psl->list = NULL;
}
//检查容量
void SeqListCheckCapacity(SeqList* psl)
{
assert(psl);
if (psl->size == psl->capacity)
{
int newcapacity = psl->capacity == 0 ? 4 : psl->capacity * 2;
SeqListType* tmp = (SeqListType*)realloc(psl->list, sizeof(SeqListType) * newcapacity);
if (tmp == NULL)
{
printf("realloc:fail\n");
exit(-1);
}
else
{
psl->list = tmp;
psl->capacity = newcapacity;
}
}
}
//尾插一个元素
void SeqListPushBack(SeqList* psl, SeqListType x)
{
assert(psl);
SeqListCheckCapacity(psl);
psl->list[psl->size] = x;
psl->size++;
}
//尾删一个元素
void SeqListPopBack(SeqList* psl)
{
assert(psl);
if (psl->size > 0)
{
psl->size--;
}
}
//头插一个元素
void SeqListPushFront(SeqList* psl, SeqListType x)
{
assert(psl);
SeqListCheckCapacity(psl);
int begin = psl->size;
while (begin > 0)
{
psl->list[begin] = psl->list[begin - 1];
begin--;
}
psl->list[0] = x;
psl->size++;
}
//头删一个元素
void SeqListPopFront(SeqList* psl)
{
assert(psl);
int begin = 1;
while (begin < psl->size)
{
psl->list[begin-1] = psl->list[begin];
begin++;
}
psl->size--;
}
//任何位置的元素插入
void SeqListInsert(SeqList* psl, size_t pos, SeqListType x)
{
assert(psl);
if (pos > psl->size)
{
printf("越界");
}
SeqListCheckCapacity(psl);
size_t begin = psl->size;
while (begin > pos)
{
psl->list[begin] = psl->list[begin - 1];
begin--;
}
psl->list[pos] = x;
psl->size++;
}
//任何位置的元素删除
void SeqListErase(SeqList* psl, size_t pos)
{
assert(psl);
assert(pos < psl->size);
size_t begin = pos+1;
while (begin < psl->size)
{
psl->list[begin-1] = psl->list[begin];
begin++;
}
psl->size--;
}
//销毁顺序表
void SeqListDeStroy(SeqList* psl)
{
assert(psl);
free(psl->list);
psl->capacity = 0;
psl->size = 0;
psl->list = NULL;
}
//打印顺序表的内容
void SeqListPrint(SeqList* psl)
{
assert(psl);
int i = 0;
for (i = 0; i < psl->size; i++)
{
printf("%d ", psl->list[i]);
}
printf("\n");
}
ソースファイルtest.c
void menu()
{
printf("********************************\n");
printf("*** 1.尾插 2.尾删 ***\n");
printf("*** 3.头插 4.头删 ***\n");
printf("*** 5.指定插入 6.指定删除 ***\n");
printf("*** 7.查看 -1.退出 ***\n");
printf("********************************\n");
}
int main()
{
SeqList data;
InitSeqList(&data);
int option = -1;
do {
menu();
printf("请选择您想要进行的操作:>");
scanf("%d", &option);
SeqListType val = 0;
size_t pos = 0;
switch (option)
{
case 1:
printf("请输入您想要插入的数据:>");
scanf("%d", &val);
SeqListPushBack(&data, val);
break;
case 2:
SeqListPopBack(&data);
break;
case 3:
printf("请输入您想要插入的数据:>");
scanf("%d", &val);
SeqListPushFront(&data, val);
break;
case 4:
SeqListPopFront(&data);
break;
case 5:
printf("请输入你想要插入的数据:>");
scanf("%d", &val);
printf("请输入你想要插入的位置:>");
scanf("%d", &pos);
SeqListInsert(&data, pos, val);
break;
case 6:
printf("请输入您想要删除的位置:>");
scanf("%d", &pos);
SeqListErase(&data, pos);
break;
case 7:
SeqListPrint(&data);
break;
case -1:
printf("退出程序\n");
return 0;
break;
default:
printf("请重新选择\n");
break;
}
} while (option);
test2(&data);
return 0;
}
まとめ
- シーケンステーブルを操作するときは、シーケンステーブルの次の3つのプロパティについて明確にする必要があります。
- 保管スペースの開始場所
- シーケンステーブルの最大容量
- シーケンステーブルの現在の長さ
- シーケンステーブルの現在の長さと開始位置を使用して、シーケンステーブルに要素を追加および削除できますが、
各要素を追加するとテーブルの長さが1ずつ増加し、テーブルの長さが1つ減少することに注意してください。各要素が削除された後1。