顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改等基本操作。
换而言之通常来说就是一个用malloc在堆上申请空间的数组,用来保存数据,并且可以增删查改各种骚操作的功能性产品.
#pragma once
typedef int DataType;
// 动态顺序表: 底层的空间从堆上动态申请出来的
typedef struct SeqList
{
DataType* arr; // 指向存储元素空间的起始位置
int capacity; // 表示空间总的大小
int size; // 有效元素的个数
}SeqList;
// typedef struct SeqList SeqList;
//以下是函数声明
//检查容量是否已满
void Checkcapacity(SeqList* ps);
//初始化,mollic出capacity
void SeqListInit(SeqList* ps, int initcapacity);
//销毁
void SeqListDestroy(SeqList* ps);
// 尾插
void SeqListPushBack(SeqList* ps, DataType data);
// 尾删
void SeqListPopBack(SeqList* ps);
// 头插
void SeqListPushFront(SeqList* ps, DataType data);
// 头删
void SeqListPopFront(SeqList* ps);
// 在顺序表的pos位置插入元素data
// 注意:pos的范围必须在[0, ps->size]
void SeqListInsert(SeqList* ps, int pos, DataType data);
// 顺序表删除pos位置的值
// 注意:pos的范围必须在[0, ps->size)
void SeqListErase(SeqList* ps, int pos);
// 有效元素个数
int SeqListSize(SeqList* ps);
// 空间总的大小
int SeqListCapacity(SeqList* ps);
//查找某个数据
int SeqListFind(SeqList* ps, DataType data);
// 检测顺序表是否为空
int SeqListEmpty(SeqList* ps);
// 获取顺序表中任意位置的元素
int SeqListGet(SeqList* ps, int pos);
///
// 测试顺序表
void TestSeqList();
以下是源文件分段解析:(完整代码在最后,需要自取,标明出处,侵权必究)
//检查容量满了没,满了就扩容,搬移数据到新数组,释放旧数组空间
void Checkcapacity(SeqList* ps)
{
assert(ps);
//检查容量满了没,满了就扩容
if (ps->capacity == ps->size){
int newCapacity = (ps->capacity << 1);
DataType* arrnew= (DataType*)malloc(sizeof(DataType)*newCapacity);
//检查新数组申请成功
if (NULL == arrnew)
{
exit(0);
return;
}
//搬移数据到新数组
for (int i=0; i <= ps->size; i++)
{
arrnew[i] = ps->arr[i];
}
//释放旧数组空间
free(ps->arr);
//新数据赋值
ps->arr = arrnew;
ps->capacity = newCapacity;
}
}
//初始化,检验用户输入的初始容量是不是合理的,不合理就初始化成3,然后对arr在堆上申请空间以保存数据
//注意申请空间后需要检验是否申请成功,最后将容量数值与有效数据个数值更新
void SeqListInit(SeqList* ps, int initcapacity)
{
assert(ps);
//检验用户输入的初始容量是不是合理的,不合理就初始化成3
initcapacity = initcapacity <= 0 ? 3 : initcapacity;
//对arr在堆上申请空间以保存数据
ps->arr = (DataType*)malloc(initcapacity*sizeof(DataType));
//申请空间后需要检验是否申请成功
if (ps->arr==NULL){
return;
}
//容量数值与有效数据个数值更新
ps->capacity = initcapacity;
ps->size = 0;
}
void SeqListDestroy(SeqList* ps)
{
assert(ps);
free(ps->arr);
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
void SeqListPushBack(SeqList* ps, DataType x){
//检查顺序表是否存在
assert(ps);
//检查容量
Checkcapacity(ps);
//把x放到数组size位置,意味着在最后一个元素后面插入x,注意不是size-1
ps->arr[ps->size] = x;
ps->size++;
}
// 尾删,要考虑顺序表有没有元素,元素个数为零就直接返回,删除操作只需要size--
void SeqListPopBack(SeqList* ps){
//检查顺序表是否存在
assert(ps);
//顺序表有没有元素,元素个数为零就直接返回
if (ps->size==0){
return;
}
ps->arr[ps->size-1] = NULL;
ps->size--;
}
// 头插,先检验空间是否足够,将顺序表所有元素整体往后移,然后插入元素x
void SeqListPushFront(SeqList* ps, DataType x)
{
assert(ps);
// 1. 检测空间是否足够
Checkcapacity(ps);
//2.顺序表所有元素整体往后移
for (int i = ps->size; i > 0;i--)
{
ps->arr[i] = ps->arr[i-1];
}
//3.插入元素
ps->arr[0] = x;
ps->size++;
}
// 头删,先判断元素个数是否为零,所有元素前移,size--
void SeqListPopFront(SeqList* ps)
{
//判断元素个数是否为零
if (ps->size==0){
return;
}
for (int i = 0; i < ps->size-1 ; i++){
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
//打印
void SeqListPrint(SeqList* ps)
{
assert(ps);
for (int i = 0; i < ps->size; i++){
printf("%d ", ps->arr[i]);
}
printf("\n");
}
//有限元素个数size
int SeqListSize(SeqList* ps)
{
assert(ps);
return ps->size;
}
//空间总大小
int SeqListCapacity(SeqList* ps)
{
assert(ps);
return ps->capacity;
}
//随意查找
int SeqListFind(SeqList* ps, DataType x){
assert(ps);
for (int i = 0; i < ps->size; i++){
if (ps->arr[i] == x)
{
return i;
}
}
return -1;
}
// 检测顺序表是否为空
int SeqListEmpty(SeqList* ps)
{
assert(ps);
if (ps->size == 0)
{
return 0;
}
else
{
return -1;
}
}
// 获取顺序表中pos位置元素
int SeqListGet(SeqList* ps,int pos)
{
assert(ps);
return ps->arr[pos];
}
注意:pos的范围必须在[0, ps->size]
ps注释,因为插入元素并不要求插入位置一定有元素,如果pos一开始就在arr[ps->size]位置,也是可以插入的,相当于操作了尾插,所以范围包含ps->size
第二点要注意,插入元素时必须检测容量
// 在顺序表的pos位置插入元素data
// 注意:pos的范围必须在[0, ps->size]
void SeqListInsert(SeqList* ps, int pos, DataType data)
{
//1.检测pos是否合理
assert(ps);
if (pos<0 || pos>ps->size){
printf("位置有问题");
return;
}
//2.检测容量
Checkcapacity(ps);
//3.插入元素
for (int i = ps->size - 1; i >= pos; i--)
{
ps->arr[i + 1] = ps->arr[i];
}
ps->arr[pos] = data;
ps->size++;
}
注意:pos的范围必须在[0, ps->size)
ps:删除时不用检查容量,但删除位置要求本来就存在值才可以删除,所以对pos位置合理性的判断就不可以允许arr[ps->size],在这个位置不可以删除
pps:
对于非尾位置操作的功能,我们要注意前移后移的问题,整体前移时先移第一个,整体后移的时候先移最后一个,这里写代码注意一下循环条件
void SeqListErase(SeqList* ps, int pos)
{
//1.检测位置是否合理
assert(ps);
if (pos < 0 || pos > ps->size)
{
printf("位置有问题");
return;
}
//删除pos位置元素
for (int i = pos + 1; i < ps->size; i++)
{
ps->arr[i - 1] = ps->arr[i];
}
ps->size--;
}
void TestSeqList1(){
SeqList s;
int*ps = &s;
SeqListInit(ps, 10);//初始化10个容量
SeqListPushBack(ps, 1);//尾插1
SeqListPushBack(ps, 2);//尾插2
SeqListPushBack(ps, 3);//尾插3
SeqListPushBack(ps, 4);//尾插4
SeqListPushBack(ps, 5);//尾插5
SeqListPrint(ps);//打印,期待结果12345
SeqListPushFront(ps, 0);//头插0
SeqListPrint(ps);//打印,期待结果012345
SeqListPopFront(ps);//头删
SeqListPrint(ps);//打印,期待结果12345
SeqListPopBack(ps);//尾删
SeqListPrint(ps);//打印,期待结果1234
printf("%d\n", SeqListSize(ps));//打印size值,期待结果4
printf("%d\n", SeqListFind(ps,4));//找4,期待结果3
printf("%d\n", SeqListEmpty(ps));//判断顺序表是否空,期待结果-1
printf("%d\n", SeqListGet(ps, 3));//找arr[3],期待结果4
printf("%d\n", SeqListGet(ps, 4));//找arr[4],期待结果"位置有问题"
SeqListInsert(ps, 4, 999);//(任意位置插入)在arr[4]插入999
SeqListPrint(ps);//打印,期待结果1234999
SeqListInsert(ps, 2, 999);//在arr[2]插入999
SeqListPrint(ps);//打印,期待结果129993999
SeqListErase(ps,4);//(任意位置删除)删除arr[4]
SeqListPrint(ps);//打印,期待效果129993999
SeqListDestroy(ps);//销毁,释放内存
#include"SeqList.h"
#include
#include
#include
#include
int main()
{
TestSeqList1();
system("pause");
return 0;
}
#include"SeqList.h"
#include
#include
#include
//检查容量满了没,满了就扩容,搬移数据到新数组,释放旧数组空间
void Checkcapacity(SeqList* ps)
{
assert(ps);
//检查容量满了没,满了就扩容
if (ps->capacity == ps->size){
int newCapacity = (ps->capacity << 1);
DataType* arrnew= (DataType*)malloc(sizeof(DataType)*newCapacity);
//检查新数组申请成功
if (NULL == arrnew)
{
exit(0);
return;
}
//搬移数据到新数组
for (int i=0; i <= ps->size; i++)
{
arrnew[i] = ps->arr[i];
}
//释放旧数组空间
free(ps->arr);
//新数据赋值
ps->arr = arrnew;
ps->capacity = newCapacity;
}
}
//初始化,检验用户输入的初始容量是不是合理的,不合理就初始化成3,然后对arr在堆上申请空间以保存数据
//注意申请空间后需要检验是否申请成功,最后将容量数值与有效数据个数值更新
void SeqListInit(SeqList* ps, int initcapacity)
{
assert(ps);
//检验用户输入的初始容量是不是合理的,不合理就初始化成3
initcapacity = initcapacity <= 0 ? 3 : initcapacity;
//对arr在堆上申请空间以保存数据
ps->arr = (DataType*)malloc(initcapacity*sizeof(DataType));
//申请空间后需要检验是否申请成功
if (ps->arr==NULL){
return;
}
//容量数值与有效数据个数值更新
ps->capacity = initcapacity;
ps->size = 0;
}
//销毁
void SeqListDestroy(SeqList* ps)
{
assert(ps);
free(ps->arr);
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
// 尾插x
void SeqListPushBack(SeqList* ps, DataType x){
//检查顺序表是否存在
assert(ps);
//检查容量
Checkcapacity(ps);
//把x放到数组size位置,意味着在最后一个元素后面插入x,注意不是size-1
ps->arr[ps->size] = x;
ps->size++;
}
// 尾删,要考虑顺序表有没有元素,元素个数为零就直接返回,删除操作只需要size--
void SeqListPopBack(SeqList* ps){
//检查顺序表是否存在
assert(ps);
//顺序表有没有元素,元素个数为零就直接返回
if (ps->size==0){
return;
}
ps->arr[ps->size-1] = NULL;
ps->size--;
}
// 头插,先检验空间是否足够,将顺序表所有元素整体往后移,然后插入元素x
void SeqListPushFront(SeqList* ps, DataType x)
{
assert(ps);
// 1. 检测空间是否足够
Checkcapacity(ps);
//2.顺序表所有元素整体往后移
for (int i = ps->size; i > 0;i--)
{
ps->arr[i] = ps->arr[i-1];
}
//3.插入元素
ps->arr[0] = x;
ps->size++;
}
// 头删,先判断元素个数是否为零,所有元素前移,size--
void SeqListPopFront(SeqList* ps)
{
//判断元素个数是否为零
if (ps->size==0){
return;
}
for (int i = 0; i < ps->size-1 ; i++){
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
//打印
void SeqListPrint(SeqList* ps)
{
assert(ps);
for (int i = 0; i < ps->size; i++){
printf("%d ", ps->arr[i]);
}
printf("\n");
}
//有限元素个数size
int SeqListSize(SeqList* ps)
{
assert(ps);
return ps->size;
}
//空间总大小
int SeqListCapacity(SeqList* ps)
{
assert(ps);
return ps->capacity;
}
//随意查找
int SeqListFind(SeqList* ps, DataType x){
assert(ps);
for (int i = 0; i < ps->size; i++){
if (ps->arr[i] == x)
{
return i;
}
}
return -1;
}
// 检测顺序表是否为空
int SeqListEmpty(SeqList* ps)
{
assert(ps);
if (ps->size == 0)
{
return 0;
}
else
{
return -1;
}
}
// 获取顺序表中pos位置元素
int SeqListGet(SeqList* ps,int pos)
{
assert(ps);
if (pos<0 || pos>=ps->size){
printf("位置有问题");
return;
}
assert(ps);
return ps->arr[pos];
}
// 在顺序表的pos位置插入元素data
// 注意:pos的范围必须在[0, ps->size]
void SeqListInsert(SeqList* ps, int pos, DataType data)
{
//1.检测pos是否合理
assert(ps);
if (pos<0 || pos>ps->size){
printf("位置有问题");
return;
}
//2.检测容量
Checkcapacity(ps);
//3.插入元素
for (int i = ps->size - 1; i >= pos; i--)
{
ps->arr[i + 1] = ps->arr[i];
}
ps->arr[pos] = data;
ps->size++;
}
// 顺序表删除pos位置的值
// 注意:pos的范围必须在[0, ps->size)
void SeqListErase(SeqList* ps, int pos)
{
//1.检测位置是否合理
assert(ps);
if (pos < 0 || pos > ps->size)
{
printf("位置有问题");
return;
}
//删除pos位置元素
for (int i = pos + 1; i < ps->size; i++)
{
ps->arr[i - 1] = ps->arr[i];
}
ps->size--;
}
//
void TestSeqList1(){
SeqList s;
int*ps = &s;
SeqListInit(ps, 10);//初始化10个容量
SeqListPushBack(ps, 1);//尾插1
SeqListPushBack(ps, 2);//尾插2
SeqListPushBack(ps, 3);//尾插3
SeqListPushBack(ps, 4);//尾插4
SeqListPushBack(ps, 5);//尾插5
SeqListPrint(ps);//打印,期待结果12345
SeqListPushFront(ps, 0);//头插0
SeqListPrint(ps);//打印,期待结果012345
SeqListPopFront(ps);//头删
SeqListPrint(ps);//打印,期待结果12345
SeqListPopBack(ps);//尾删
SeqListPrint(ps);//打印,期待结果1234
printf("%d\n", SeqListSize(ps));//打印size值,期待结果4
printf("%d\n", SeqListFind(ps, 4));//找4,期待结果3
printf("%d\n", SeqListEmpty(ps));//判断顺序表是否空,期待结果-1
printf("%d\n", SeqListGet(ps, 3));//找arr[3],期待结果4
printf("%d\n", SeqListGet(ps, 4));//找arr[4],期待结果"位置有问题"
SeqListInsert(ps, 4, 999);//(任意位置插入)在arr[4]插入999
SeqListPrint(ps);//打印,期待结果1234999
SeqListInsert(ps, 2, 999);//在arr[2]插入999
SeqListPrint(ps);//打印,期待结果129993999
SeqListErase(ps, 4);//(任意位置删除)删除arr[4]
SeqListPrint(ps);//打印,期待效果129993999
SeqListDestroy(ps);//销毁,释放内存
}