我们直接切入主题
1.首先这次写的顺序表的动态的,因为静态的弊端较多。
2.顺序表的功能函数有:初始化 丶申请动态内存 顺序表的头部,尾部的插入和删除 丶在特定位置的插入和删除 丶打印顺序表 丶释放动态内存
需要用到的头文件
我们先给 类型 重命名
原因是:以后还需要用到顺序表时,插入的不一定是你当前使用的类型,如果要改还需要一个个改,非常麻烦,为了以后方便,我们需要改类型时,直接给 类型重命名 这里改,就可以了,更加节省时间。
创建一个结构体里面包含
1指向动态开辟数组的指针。*a
2记录有效数据的个数 size
3容量的大小 capacity
前置准备写好了,可以开始实现各个函数功能了。
1 初始化
初始化较为简单 指针置为空,size置为0,需要注意的是容量大小要置为4(或者其他大小)至于为什么,后面讲)(这里不讲是因为和后面函数对应)
2. 内存扩容
这里的newcapacity是给capacity扩容
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
这里的ps->capacity*2跟上面的capacity置为4相对应,如果capacity置为0,那么0*2还是0,无法扩容,导致这个顺序表大小只有4,为什么只有4,原因在ps->capacity == 0 ? 4
if语句是判断realloc会不会申请内存失败(一般是不会的,但是为了安全性还是必须写的)
最后我们直接把 tmp 接收 申请好的内存数组赋给a
再把newcapacity扩容好的值赋给capacity
这里会有点难理解 需要读者慢慢消化
3.顺序表头部插入
这里需要注意 头部插入和尾部插入的顺序可以颠倒
但是在第一个插入的函数 必须直接让扩容函数直接执行,让ps->a申请内存,不然ps->a为空,无法进行插入 会直接报错
代码思路:
让end放在有效数据的前一个数字(简单来说就是让end放在顺序表最后一个位置,向前走,分别想换他们的位置)
while end>=0是判断到 数组开头的数据移动后一位,为要插入的数据腾出空间
ps->a[end+1]=ps->a[end]
把最后一个数据移动到size这个为空的有效位置
移动完后 让end往前走 (++是往后走 --是往前走)
循环结束后 所有的数据都往后移动了一个位置
再把 x (就是你想插入的数据)插入到第一个位置 a[0]就是数组的第一个位置
再让size++ 有效数据有多了一个
4.顺序表的尾部插入
这是第二次插入 不能让扩容直接进入,需要判断有效数据是否达到了容量大小
如果达到就扩容 ,没达到就无需扩容 。
尾部插入比较简单
因为size本身就指向有效数据的后一位,我们直接在size这里添加,再让size往后移一下,就完成了尾部插入。
5.顺序表的头部删除
int end =1 让end放在数组的第二个位置 (数组0是第一个位置 所以1是第二个位置)
while (end < ps->size)第二位置开始 一直到最后的有效数据
先把数组第二的位置覆盖到数组第一个位置 然后就删除了
但是数组第二个位置就为空了 让第三个数据覆盖上来
但是数组第三个位置就为空了 让......依次类推
++end就是让end往后走 持续交换
ps->size-- 有效数据少一个 所以size要--
6.顺序表的尾部删除
因为是尾部删除 而size也是指向有效个数,直接让size--就等于删除了最后一个数据,就是尾部删除了
7.在特定位置插入
只要是插入数据 我们都要进行判断容量的大小是否满了
让end放在size的前一位
把最后一个数据往后移动
让end--(往前移动)
while (end < ps->size)直到pos这个位置的数据也往后移动一位
循环结束后pos后面的数据 包括pos这个位置的数据都往后移动了一位,pos这个位置是空数据,为插入的数据腾出了空间 我们直接插入就可以了
(注意 pos 是数组小标位置 不是数据为几 例如 0 ,1就是数组的第一个和第二个,而不是数字0,1)
size++ 有效数据插入一个 就++
8.在特定位置删除数据
这个函数原理跟头部删除差不多
它是在pos的后一位数据的位置 往前覆盖 ,而头部删除是在头部数据的后一位往前覆盖
9.打印顺序表
这里直接让i从0开始一直到size这里的有效数据都打印一边就可以了。
10.释放申请的动态内存
我们把指针释放 再置为空
然后把有效数据和容量大小都置为0
所有函数功能就实现了
下面是代码(需要可以自取)
#pragma once
#include
#include
#include
//以后要用到顺序表不一定是用到 int 类型 如果要该类型非常麻烦需要一个个改
//给类型重命名 以后需要用到哪种类型 直接在这里改就可以了 更加方便
typedef int SLDataType;
typedef struct SeqList
{
SLDataType* a;//指向动态开辟数组的指针
int size;//有效的数据个数
int capacity;//容量的大小
}SeqList;
//初始化
void SeqListInit(SeqList* ps)
{
ps->a = NULL;
ps->size = 0;
ps->capacity = 4;
}
void Expand(SeqList* ps)
{
int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
SLDataType* tmp = (SLDataType*)realloc(ps->a, ps->capacity * sizeof(SLDataType));
if (tmp == NULL)
{
printf("realloc fail");
exit(-1);
}
else
{
ps->a =tmp;
ps->capacity = newcapacity;
}
}
//顺序表的头部插入元素
void SeqListPushBack(SeqList* ps, SLDataType x)
{
//第一次进行插入 的时候 不管是头 尾 插入 都必须直接进入扩容阶段
Expand(ps);
int end = ps->size - 1;
while (end >= 0)
{
ps->a[end + 1] = ps->a[end];
--end;
}
ps->a[0] = x;
ps->size++;
}
void SeqListPushFront(SeqList* ps, SLDataType x)
{
if (ps->size == ps->capacity)
{
Expand(ps);
}
ps->a[ps->size] = x;
ps->size++;
}
void SeqListPrint(SeqList* ps)
{
int i = 0;
for (i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
}
void SeqListDestory(SeqList* ps)
{
free(ps->a);
ps->a = NULL;
ps->size = ps->capacity = 0;
}
void SeqListPopBack(SeqList* ps)
{
int end = 1;
while (end < ps->size)
{
ps->a[end - 1] = ps->a[end];
end++;
}
ps->size--;
}
void SeqListPopFront(SeqList* ps)
{
assert(ps->size > 0);
ps->size--;
}
int SeqListFind(SeqList* ps, SLDataType x)
{
int i = 0;
for (i = 0; i < ps->size; i++)
{
if (ps->a[i] == x)
{
return i;
}
}
return;
}
//pos不是0这个数字 在现在的元素里是没有0这个数的 0表示的是数组下标
void SeqListInsert(SeqList* ps, int pos, SLDataType x)
{
if (ps->size == ps->capacity)
{
Expand(ps);
}
int end = ps->size-1;
while (end >= pos)
{
ps->a[end +1] = ps->a[end];
--end;
}
ps->a[pos] = x;
ps->size++;
}
void SeqListErase(SeqList* ps, int pos)
{
int end = pos + 1;
while (end < ps->size)
{
ps->a[end - 1] = ps->a[end];
++end;
}
ps->size--;
}
void Inteliode()
{
SeqList st;
//void SeqListInit(SeqList* ps);
SeqListInit(&st);
//void SeqListDestory(SeqList* ps);
//void SeqListPrint(SeqList* ps);
//void SeqListPushBack(SeqList* ps, SLDateType x);
SeqListPushBack(&st, 5);
SeqListPushBack(&st, 4);
SeqListPushBack(&st, 3);
SeqListPushBack(&st, 2);
SeqListPushBack(&st, 1);
//void SeqListPushFront(SeqList* ps, SLDateType x);
SeqListPushFront(&st, 6);
SeqListPushFront(&st, 7);
SeqListPushFront(&st, 8);
SeqListPushFront(&st, 9);
SeqListPushFront(&st, 10);
//void SeqListPopFront(SeqList* ps);
SeqListPopFront(&st);
SeqListPopFront(&st);
SeqListPopFront(&st);
//void SeqListPopBack(SeqList* ps);
SeqListPopBack(&st);
SeqListPopBack(&st);
SeqListPopBack(&st);
顺序表查找
//int SeqListFind(SeqList* ps, SLDateType x);
int pos=SeqListFind(&st, 4);
SeqListInsert(&st, 0, 50);
这里的5不是说数字5 而是数组下标
SeqListErase(&st, 0);
顺序表在pos位置插入x
//void SeqListInsert(SeqList* ps, size_t pos, SLDateType x);
顺序表删除pos位置的值
//void SeqListErase(SeqList* ps, size_t pos);
SeqListPrint(&st);
SeqListDestory(&st);
}
int main()
{
Inteliode();
return 0;
}
有问题可以发表评论。