顺序表其实大家都早就接触过了,大家可能会想我什么时候学过了?我这里就不卖关子了,我们在学习c语言时学习的数组就是顺序表的一种。由于顺序表大家都比较熟悉我就不再进行解释说明了。接下来我来为大家讲解一下顺序表的一些常用操作!
顺序表结构体
typedef int DATA;
//创建顺序表结构体
typedef struct
{
DATA* base;//指向顺序表的指针
int capacity;//顺序表的容量
int size;//顺序表已使用的内存
}SeqList;
可以使用typedef去为数据类型起一个别名DATA方便后续修改,使用typedef为顺序表起一个别名SeqList方便后续的使用。顺序表由三个部分组成:1.指向顺序表的指针(可以类比数组的名字) 2. 顺序表的容量 3.顺序表已经使用的内存。
顺序表的初始化
#define INIT_SEQLIST_SIZE 10
//对顺序表进行初始化
void InitSeqList(SeqList* L)
{
L->base = (DATA*)calloc(L->capacity, sizeof(DATA));
assert(L->base != NULL);
L->capacity = INIT_SEQLIST_SIZE;
L->size = 0;
}
使用顺序表首先要对顺序表进行初始化,L->base为一个指针变量我们为其分配动态内存。对于calloc有的同学可能会感到陌生,其实它与malloc的作用是一样的都是为变量分配动态内存(向堆区申请内存),第一个参数是所需分配内存的个数,第二个参数就是所需分配的内存。assert可能有的同学可能也感到陌生,它作用其实就是断言,如果assert中的表达式如果成立它就会报错对你进行警示,它对应的头文件是<assert.h>。顺序表的初始容量我们用define进行起别名,也是为了方便我们后续修改。
顺序表的插入
头部插入
头部插入就是将所有元素向后移动一个位置,将头部的位置留给新的数据。具体实现代码如下:
void push_head(SeqList* L, DATA data)
{
if(L->size >= L->capacity)
{
return;
}
for(int i = 0; i < L->size; i++)
{
L->base[i + 1] = L->base[i];
}
L->base[0] = data;
L->size++;
}
我们用for循环将所有元素向后移动一个位置,当然最后不要忘记了将L->size进行加加操作。至于所存的元素大于容量后怎么处理我们后续再讲。
尾部插入
尾部插入顾名思义就是在顺序表的后面插入新的数据,这个就比较简单了,直接将尾部的位置进行赋值就行,当然size也要进行加加操作。具体实现代码如下:
void push_tail(SeqList* L, DATA data)
{
if(L->size >= L->capacity)
{
return;
}
L->base[L->size] = data;
L->size++;
}
任意位置插入数据
想要实现在任意位置插入数据我们就需要三个形参,一个记录顺序表,一个记录数据,一个记录想要插入的位置,我们只需要将想要插入的位置后面的元素都向后移动一个位置,将想要移动的位置空出来,给新的数据使用。具体实现代码如下:
void push_appoint(SeqList* L, DATA data, int location)
{
if(L->size >= L->capacity || location < 0)
{
return;
}
for(int i = location; i < L->size; i++)
{
L->base[i + 1] = L->base[i];
}
L->base[location] = data;
L->size++;
}
当然插入的位置也要进行限定。
扩容
我们在插入的时候可能遇到的情况是顺序表的容量不能存储下我们所有的信息。这时我们就需要重新为顺序表分配一个更大的内存空间来存储我们的信息。具体实现代码如下:
void dilatation(SeqList* L)
{
DATA* ptemp = (DATA*)calloc(L->capacity * 2, sizeof(DATA));
assert(ptemp != NULL);
ptemp = L->base;
L->base = ptemp;
L->capacity *= L->capacity;
}
顺序表的删除
头部删除
将头部的数据删除,然后将后面的数据向前移动一格最后对size进行减减操作。具体实现代码如下:
void pop_head(SeqList* L)
{
if(empty(L))
{
return;
}
//free(L->base[0]);
for(int i = 0; i < L->size; i++)
{
L->base[i] = L->base[i + 1];
}
L->size--;
}
empty函数为判断顺序表是否为空,具体实现如下:
bool empty(SeqList* L)
{
if(L->size == 0)
{
return 1;
}
return 0;
}
尾部删除
尾部删除就是将尾部的数据删除然后将size进行减减操作。具体实现代码如下:
void pop_tail(SeqList* L)
{
if(empty(L))
{
return;
}
L->base[L->size - 1] = 0;
L->size--;
}
任意位置删除
想要实现任意位置删除需要将该位置的数据删除后将后面的数据向前移动一位,然后将size进行减减操作即可。具体实现代码如下:
void pop_appoint(SeqList* L, int location)
{
if(empty(L) || location < 0 || location > L->size - 1)
{
return;
}
for(int i = location; i < L->size; i++)
{
L->base[i] = L->base[i + 1];
}
L->size--;
}
输出顺序表的内容
代码实现如下:
void SearchSeqList(SeqList* L)
{
for(int i = 0; i < L->size; i++)
{
printf("%d", L->base[i]);
}
}
修改顺序表的数据
想要修改顺序表的数据直接将新数据赋值给该位置即可。具体实现代码如下:
void modification(SeqList* L, DATA data, int location)
{
if(empty(L) || location >= L->size)
{
return;
}
L->base[location] = data;
}
以上就是顺序表的全部基础操作了,如有错误的地方希望各位大佬指正,我会继续更新所学内容的感悟,希望能够帮助到大家,让我们共同努力,早日成为编程高手!