目录
一、顺序表
1.1 什么是顺序表?
顺序表是一种线性表的实现方式,它将元素按照其逻辑顺序依次存储在计算机内存中的连续存储单元中,即数组。顺序表中的元素在内存中是依次相邻存储的,这使得可以通过元素的索引值(下标)来快速访问任意位置的元素。
1.2 顺序表的特点
-
连续存储: 顺序表使用数组作为底层存储结构,元素在内存中是连续存储的,这使得随机访问操作效率高,可以通过下标直接访问任意位置的元素。
-
固定大小: 顺序表的大小在创建时需要指定,且一般无法动态改变大小,即使有些编程语言的动态数组可以自动扩展大小,也会带来一定的性能开销。
-
插入和删除操作慢: 在顺序表中执行插入和删除操作可能会涉及到元素的移动,特别是在中间位置插入或删除元素时,需要将后续元素依次向后或向前移动,因此时间复杂度为O(n),其中n是元素的个数。
-
元素访问效率高: 由于顺序表的元素在内存中是连续存储的,因此可以通过索引直接访问任意位置的元素,时间复杂度为O(1)。
-
适用范围: 顺序表适用于元素数量固定且需要频繁随机访问的场景,例如需要大量查找操作的情况。
二、C语言实现
2.1 SeqList.h
typedef int SLDataType;
//动态顺序表
typedef struct SeqList
{
SLDataType* arr;//数据类型
int size; //有效数据个数
int capacity; //空间大小
}SL;
//顺序表初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestroy(SL* ps);
//顺序表的打印
void SLPrint(SL s);
//头部插入
void SLPushFront(SL* ps, SLDataType x);
//尾部插入
void SLPushBack(SL* ps, SLDataType x);
//头部删除
void SLPopFront(SL* ps);
//尾部插入
void SLPopBack(SL* ps);
//指定位置之前插入数据
void SLInsert(SL* ps, int pos, SLDataType x);
//指定位置擦除数据
void SLErase(SL* ps, int pos);
//寻找数据
int SLFind(SL* ps, SLDataType x);
2.2 SeqList.c
#include"SeqList.h"
void SLPrint(SL s)
{
for (int i = 0; i < s.size; i++)
{
printf("%d ", s.arr[i]);
}
printf("\n");
}
//顺序表的初始化
void SLInit(SL* ps)
{
ps->arr = NULL;
ps->size = 0;
ps->capacity = 0;
}
//顺序表的销毁
void SLDestroy(SL* ps)
{
if (ps->arr != NULL)
{
free(ps->arr);
}
ps->arr = NULL;
ps->size = 0;
ps->capacity = 0;
}
//检查空间是否足够
void SLCheckCapacity(SL* ps)
{
//插入数据之前先看空间够不够
if (ps->capacity == ps->size)
{
int newCapacity = 0;
if (ps->capacity == 0)
{
newCapacity = 4;
}
else
{
newCapacity = 2 * ps->capacity;
}
SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));
if (tmp == NULL)
{
perror("realloc fail!");
exit(1);
}
//空间申请成功
ps->arr = tmp;
ps->capacity = newCapacity;
}
}
//尾插
void SLPushBack(SL* ps, SLDataType x)
{
//温柔的解决方式
if (ps == NULL)
{
return 1;
}
SLCheckCapacity(ps);
ps->arr[ps->size++] = x;
}
//头插
void SLPushFront(SL* ps, SLDataType x)
{
assert(ps);
SLCheckCapacity(ps);
//先让顺序表中已有的数据整体往后挪动一位
for (int i = ps->size; i > 0; i--)
{
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[0] = x;
ps->size++;
}
//尾删
void SLPopBack(SL* ps)
{
assert(ps);
assert(ps->size);
--ps->size;
}
//头删
void SLPopFront(SL* ps)
{
assert(ps);
assert(ps->size);
//数据整体往前挪动一位
for (int i = 0; i < ps->size - 1; i++)
{
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
//指定位置前插入数据
void SLInsert(SL* ps, int pos, SLDataType x)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
SLCheckCapacity(ps);
//向后移动数据
for (int i = ps->size ; i > pos ; i--)
{
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[pos] = x;
ps->size++;
}
//指定位置擦除数据
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
for (int i = pos; i < ps->size - 1; i++)
{
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
//寻找数据
int SLFind(SL* ps, SLDataType x)
{
assert(ps);
int i = 0;
for (; i < ps->size; i++)
{
if (ps->arr[i] == x)
{
return i;
break;
}
}
if (i+1==ps->size )
{
return -1;
}
}