目的:实现顺序表的增删查改
头插
头删
尾插
尾删
中间插
中间删
删除顺序表
什么是顺序表?
其实就是一个结构体里面存个数组
1.那就先创建一个结构体:a是数组,size是数组当前元素个数,capacity是数组元素个数最大容量
typedef struct SeqList
{
SLDateType* a;// 指向动态开辟的数组
int size;// 有效数据个数
int capacity;// 容量空间的大小
}SeqList;
这里用的整形数组所以:
typedef int SLDateType;
2.1 初始化结构体;
void SeqListInit(SeqList* ps);
开辟一个动态内存空间
其中先定义最大元素个数:INIT_CAPACITY
#define INIT_CAPACITY 4
void SeqListInit(SeqList* ps)//初始化顺序表(结构体)
{
ps->a = (SLDateType*)malloc(sizeof(SLDateType) * INIT_CAPACOTY);
if (ps->a == NULL)
{
perror("malloc fail");
return;
}
ps->size = 0;
ps->capacity = INIT_CAPACITY;
}
2.2 先搞简单的:尾插
void SeqListPushBack(SeqList* ps, SLDateType x);
x是尾插的元素
注意:如果size=capacity,表示已经装满了需要扩容。不扩容尾插就越界了
void SeqListPushBack(SeqList* ps, SLDateType x)//尾插
{
if (ps->size == ps->capacity)//判断是否需要扩容
{
SLDateType* tmp = (SLDateType*)realloc(ps->a, sizeof(SLDateType) * ps->capacity * 2);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->capacity *= 2;
ps->a = tmp;
}
ps->a[ps->size] = x;
ps->size++;
}
上图:
还有个打印顺序表:
void SeqListPrint(SeqList* ps);//打印顺序表
void SeqListPrint(SeqList* ps)//打印顺序表
{
int i = 0;
for (i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
2.3 尾删:
void SeqListPopBack(SeqList* ps);//尾删
尾删包括接下来的头删都需要判断数组是否为空
void SeqListPopBack(SeqList* ps)//尾删
{
if (ps->size == 0)
return;
ps->a[ps->size-1] = '\0';
ps->size--;
}
上图:
2.4 头插:
void SeqListPushFront(SeqList* ps, SLDateType x);//头查
头插是从头开始插入,如果输入1 2 3 4,输出4 3 2 1.
逻辑:数组内的元素依次往后挪一个位置,就是覆盖,然后插入数据
void SeqListPushFront(SeqList* ps, SLDateType x)//头插
{
if (ps->size == ps->capacity)//判断是否需要扩容
{
SLDateType* tmp = (SLDateType*)realloc(ps->a, sizeof(SLDateType) * ps->capacity * 2);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->capacity *= 2;
}
for (int i = ps->size - 1; i >= 0; i--)
{
ps->a[i+1] = ps->a[i];
}
ps->a[0] = x;
ps->size++;
}
上图:
2.5 头删
逻辑:把第一个元素覆盖了,然后size--
void SeqListPopFront(SeqList* ps)
注意:这里i<=size,如果只是小于size会越界,下面有i+1
void SeqListPopFront(SeqList* ps)//头删
{
if (ps->size == 0)
return;
int i = 0;
for (i = 0; i <= ps->size; i++)
{
ps->a[i] = ps->a[i+1];
}
ps->a[ps->size-1] = '\0';
ps->size--;
}
上图:
2.6 中间插
这里原理以我的理解是头插和尾插结合,比如要在第五个元素插入数据,那就把第5个包括以后往后挪一个位置,再在尾插到第4个后面
void SeqListInsert(SeqList* ps, int pos, SLDateType x)
这里就要判断是否为空,或者是否满了,两个都要判断
void SeqListInsert(SeqList* ps, int pos, SLDateType x)// 顺序表在pos位置插入x
{
if (ps->size == 0)
return;
if (ps->size == ps->capacity)//判断是否需要扩容
{
SLDateType* tmp = (SLDateType*)realloc(ps->a, sizeof(SLDateType) * ps->capacity * 2);
if (tmp == NULL)
{
perror("realloc fail");
return;
}
ps->capacity *= 2;
}
for (int i = ps->size - 1; i >= pos-1; i--)//找到pos的位置往后移
{
ps->a[i + 1] = ps->a[i];
}
ps->size++;
ps->a[pos-1] = x;//再给pos的位置赋值
}
上图:
这里在第5个位置插入了10
2.7 中间删
void SeqListErase(SeqList* ps, int pos)
原理:比如是第pos个,从pos往后给它覆盖了
void SeqListErase(SeqList* ps, int pos)
{
if (ps->size == 0)
return;
int i = 0;
for (i = pos - 1; i < ps->size; i++)
{
ps->a[i] = ps->a[i + 1];
}
ps->a[ps->size-1] = '\0';
ps->size--;
}
上图:
3. 破环顺序表
void SeqListDestroy(SeqList* ps)
把申请的动态空间还给操作系统,让size和capacity归0
void SeqListDestroy(SeqList* ps)//破坏顺序表
{
free(ps->a);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
还差个查找忘记写了,其实就按照size的下标找到打印就好了
里面的申请动态空间函数可以单独写出了再调用