概念篇
下图展现了顺序表的概念以及分类
代码篇
1. 顺序表的定义
用结构体把一些属性封装起来表示顺序表
typedef struct sqlist
{
int*elements;
/*指向整数的指针,用于存储顺序表中的元素,指向动态分配的整形数组。*/
size_t size;
//顺序表中当前存储的元素数量
size_t capacity;
//顺序表当前能够存储的最大元素数量
}sqlist;
int*elements指向动态分配的整形数组,需要用malloc函数分配空间,可以用realloc函数扩容,如果已知数组大小可以替换成int elements[n],n表示数组长度。
2. 顺序表的初始化
void sqlist_init(sqlist*list,int capacity)
{
list->elements=(int*)malloc(sizeof(int)*capacity);
//给动态数组分配空间
list->size=0;
//数量初始化为0
list->capacity=capacity;
//容量初始化为函数传入进来的capacity值
}
3.顺序表的摧毁
顺序表的摧毁也就是释放顺序表所占有的内存空间。主要分为下几步:
a.释放数据元素所占用的内存。
b将指针置为NULL。
c重置顺序表的其他属性(容量,长度等)。(可要可不要)
void sqlist_destory(sqlist*list)
{
if(list->elements)
{
free(list->elements);
//释放malloc申请数据元素所用的内存空间
list->elements=NULL;
//确保在后续的程序执行中,不会错误地访问这块已被释放的内存
}
}
4. 顺序表的元素数量
直接返回了顺序表结构体指针list所指向的对象的size成员。
size_t sqlist_size(sqlist*list)
{
return list->size;
}
5. 顺序表的数据插入
1.插入的索引位置是否合法,不合法打印非法索引。
2.顺序表是否已经满了,如果满了,则扩容。
3.顺序表没有满,先将从要插入位置开始到顺序表末尾的所有元素向后移动一位,再插入新元素。
4.更新数据表大小。
void sqlist_insert(sqlist*list,int index,int element)
{
if(index<0||index>list->size)
{
printf("invalid index\n");
return;
}
//如果要插入的位置<0或大于顺序表中的元素个数,则打印非法索引,并返回。
if(list->size==list->capacity)
{
//如果顺序表的元素个数等于顺序表的容量,代表顺序表满了,需要扩容。
int*newelements=(int*)realloc(list->elements,sizeof(int)*list->capacity*2);
//尝试将elements的存储空间扩大到原来的两倍。
if(newelements==NULL)
//如果内存为空,则扩容失败,返回。
{
printf("failed to allocate\n");
return;
}
list->elements=newelements;
list->capacity*=2;
//否则成功, 更新elements指针指向新的内存区域。
}
for(int i=list->size;i>index;i--)
list->elements[i]=list->elements[i-1];
list->elements[index]=element;
//将从index位置开始到顺序表末尾的所有元素向后移动一位,为新元素腾出空间。
list->size++;
//插入后元素个数加一
}
6. 顺序表的元素查找
for循环遍历所有元素,满足条件则返回该元素,否则返回-1.
int sqlist_find(sqlist*list,int element)
{
for(int i=0;i<list->size;i++)
{
if(list->elements[i]==element)
return i;
}
return -1;
}
7. 顺序表的元素删除
数据删除跟数据插入有异曲同工之妙,删除是将该位置之后的所有元素向前移动一位
void sqlist_delete(sqlist*list,int index)
{
if(index<0||index>=list->size)
{
printf("invalid index\n");
return;
}
for(int i=index;i<list->size;i++)
list->elements[i]=list->elements[i+1];
list->size--;
}
8. 顺序表的元素修改
直接通过索引来访问数组进行元素修改。
void sqlist_alter(sqlist*list,int index,int element)
{
if(index<0||index>=list->size)
{
printf("invalid index\n");
return;
}
list->elements[index]=element;
}
9.顺序表索引对应的元素
通过索引直接访问数组,返回对应元素
int sqlist_index(sqlist*list,int index)
{
if(index<0||index>=list->size)
{
printf("invalid index\n");
return -1;
}
return list->elements[index];
}
10.完整代码
#include<stdio.h>
typedef struct sqlist
{
int*elements;
/*指向整数的指针,用于存储顺序表中的元素,指向动态分配的整形数组。*/
int size;
//顺序表中当前存储的元素数量
int capacity;
//顺序表当前能够存储的最大元素数量
}sqlist;
void sqlist_init(sqlist*list,int capacity)
{
list->elements=(int*)malloc(sizeof(int)*capacity);
//给动态数组分配空间
list->size=0;
//数量初始化为0
list->capacity=capacity;
//容量初始化为函数传入进来的capacity值
}
void sqlist_destory(sqlist*list)
{
if(list->elements)
{
free(list->elements);
//释放malloc申请数据元素所用的内存空间
list->elements=NULL;
//确保在后续的程序执行中,不会错误地访问这块已被释放的内存
}
}
size_t sqlist_size(sqlist*list)
{
return list->size;
}
void sqlist_insert(sqlist*list,int index,int element)
{
if(index<0||index>list->size)
{
printf("invalid index\n");
return;
}
//如果要插入的位置<0或大于顺序表中的元素个数,则打印非法索引,并返回。
if(list->size==list->capacity)
{
//如果顺序表的元素个数等于顺序表的容量,代表顺序表满了,需要扩容。
int*newelements=(int*)realloc(list->elements,sizeof(int)*list->capacity*2);
//尝试将elements的存储空间扩大到原来的两倍。
if(newelements==NULL)
//如果内存为空,则扩容失败,返回。
{
printf("failed to allocate\n");
return;
}
list->elements=newelements;
list->capacity*=2;
//否则成功,更新elements指针指向新的内存区域。
}
for(int i=list->size;i>index;i--)
list->elements[i]=list->elements[i-1];
list->elements[index]=element;
//需要插入的位置i后面的所有元素后移,再第i个位置插入元素。
list->size++;
//插入后元素个数加一
}
int sqlist_find(sqlist*list,int element)
{
for(int i=0;i<list->size;i++)
{
if(list->elements[i]==element)
return i;
}
return -1;
}
void sqlist_delete(sqlist*list,int index)
{
if(index<0||index>=list->size)
{
printf("invalid index\n");
return;
}
for(int i=index;i<list->size;i++)
list->elements[i]=list->elements[i+1];
list->size--;
}
void sqlist_alter(sqlist*list,int index,int element)
{
if(index<0||index>=list->size)
{
printf("invalid index\n");
return;
}
list->elements[index]=element;
}
int sqlist_index(sqlist*list,int index)
{
if(index<0||index>=list->size)
{
printf("invalid index\n");
return -1;
}
return list->elements[index];
}
int main()
{
sqlist list;
sqlist_init(&list,1);
for(int i=0;i<10;i++)
sqlist_insert(&list,i,i*10);
//for循环插入分别0、10、20、30、40、50、60
//70 80 90
printf("size=%d\n",sqlist_size(&list));
//size=10
printf("%d\n",sqlist_find(&list,5));
//没有值为5的元素,所以打印-1
printf("%d\n",sqlist_find(&list,10));
//值为10的下标为1,打印1。
sqlist_alter(&list,3,60);
//修改下标为3的值30为60
for(int i=0;i<sqlist_size(&list);i++)
printf("%d %d\n",i,sqlist_index(&list,i));
//调用函数打印每个值以及下标。
sqlist_destory(&list);
//不再访问线性表时销毁。
return 0;
}
综上所述应该打印的结果与下图相一致
效果图
希望能给学习顺序表的同学带来一些启发,如果有路过的大佬提供宝贵的建议,那就最好了,非常感激!!