1.含义
顺序表示用一段纹理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储,在数组上完成数据的增删查改。
2.分类
顺序表一般分为:
(1)静态顺序表:使用定长数组存储
(2)动态顺序表:使用动态开辟的数组存储
3.接口函数实现
(0)顺序表的初始化
代码如下(示例):
void initSeqList(seqList* s1)
{
s1->_data = NULL;
s1->_size = s1->_capacity = 0;
}
(1)容量检查
代码如下(示例):
void checkCapacity(seqList* s1)
{
//assert(s1);//debug版本有效,调试版本用if是否为空
if (s1 == NULL){
return;
}
if (s1->_size == s1->_capacity){
int newCapacity = s1->_capacity == 0 ? 1 : 2 * s1->_capacity;
//开辟一个更大的空间,拷贝已有数据,释放原有的空间
SLDataType* tmp = (SLDataType*)malloc(sizeof(SLDataType)*newCapacity);
memcpy(tmp,s1->_data,sizeof(SLDataType)*s1->_size);
free(s1->_data);
//另一种开辟空间拷贝数据释放原空间的代码
//s1->_data = (SLDataType*)realloc(s1->_data,sizeof(SLDataType)*newCapacity)
//更新
s1->_data = tmp;
s1->_capacity = newCapacity;
}
}
(2)顺序表打印
代码如下(示例):
void printSeqList(seqList*s1)
{
for (int i = 0; i < s1->_size; ++i){
printf("%d ",s1->_data[i]);
}
printf("\n");
}
(3)顺序表头插一个元素
代码如下(示例):
void pushFront(seqList* s1, SLDataType val)
{
if (s1 == NULL){
return;
}
//0.检查容量
checkCapacity(s1);
//1.移动元素[0,size)全部向后移动一个位置,
//方向:从后向前依次移动,否则会导致数据被覆盖
int end = s1->_size;
while (end > 0){
s1->_data[end] = s1->_data[end - 1];
--end;
}
//2.头插一个元素
s1->_data[0] = val;
//3.更新size
s1->_size++;
}
(4)顺序表头删一个元素
代码如下(示例):
void popFront(seqList* s1)
{
if (s1 == NULL||s1->_size==0){
return;
}
//1.头删,数据从前往后移动,否则数据会被覆盖
int start = 1;
while (start < s1->_size){
s1->_data[start - 1] = s1->_data[start];
++start;
}
--s1->_size;
}
(5)顺序表尾插一个元素
代码如下(示例):
void pushBack(seqList* s1, SLDataType val)
{
//先检查容量是否可以满足插入一个数据
checkCapacity(s1);
s1->_data[s1->_size] = val;
++s1->_size;
}
(6)顺序表尾删一个元素
代码如下(示例):
void popBack(seqList* s1)
{
if (s1 == NULL){
return;
}
if (s1->_size > 0){
s1->_size--;
}
}
(7)在任意位置pos插入一个元素
代码如下(示例):
void insert(seqList* s1, int pos, SLDataType val)
{
if (s1 == NULL){
return;
}
if (pos >= 0 && pos <= s1->_size){
//检查容量
checkCapacity(s1);
//移动元素:[pos,size),从后向前移动,
int end = s1->_size;
while (end> pos){
s1->_data[end] = s1->_data[end - 1];
--end;
}
//插入数据
s1->_data[pos] = val;
//更新
s1->_size++;
}
}
(8)在任意位置pos删除一个元素
代码如下(示例):
void erase(seqList* s1, int pos)
{
if (s1 == NULL || s1->_size == 0){
return;
}
//有效位置:[0,size)
if (pos >= 0 && pos < s1->_size){
//移动元素:(pos,size)
//从pos+1开始,从前向后移动
int start = pos + 1;
while (start < s1->_size){
s1->_data[start - 1] = s1->_data[start];
++start;
}
--s1->_size;
}
}
4.顺序表的优缺点
优点:
(1)空间连续,支持随机访问。
缺点:
(1)中间或前面部分的插入删除时间复杂度为o(N)。
(2)增容的代价比较大。增容需要申请新空间,拷贝数据,释放旧空间,会有不小的消耗,而且增容一般是呈2倍的增长,务必会有一定的空间浪费。