顺序表的基础结构
顺序表在创建时,我们需要知道,在顺序表中我们要插入数据,在插入数据之后有当前的有效空间,因此我们便能得到顺序表的结构如下
typedef int SLDateType;//这里使用typedef是因为我们不知道以后插入的数据是什么类型,
//若是要对插入的数据类型作出修改时,只需要在此修改即可
typedef struct SeqList
{
SLDateType* a;//定义一个插入数据类型的数组
int size;//决定插入数据后的有效空间
int capacity;//定义一个有效空间的上限
}SeqList;
顺序表的数据操作
对顺序表进行实际操作应使用指针,不然函数之中改变的只是形参。
①顺序表的初始化
#define CAPACI_MAX 1000//用宏定义方便修改有效空间最大容量
void SeqListInit(SeqList* ps)
{
assert(ps);
//使用malloc将a置为动态数组
ps->a = (SLDateType*)malloc(sizeof(SLDateType)*CAPACI_MAX);
if (NULL == ps->a)
{
printf("malloc fail");
return;
}
ps->size = 0;
ps->capacity = CAPACI_MAX;
}
②顺序表的空间释放
void SeqListDestroy(SeqList* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
③顺序表的数值打印
void SeqListPrint(SeqList* ps)
{
assert(ps);
int i = 0;
for (i = 0; i < (ps->size); i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
④顺序表的头部数值插入
void SeqListPushFront(SeqList* ps, SLDateType x)
{
assert(ps);
SeqListCapCheck(ps);//在插入数据前需要判断当前有效空间是否已经到了上限,
//如果到了需要进行扩容操作
int end = ps->size;
while (end != 0)
{
ps->a[end] = ps->a[end - 1];
end--;
}
ps->a[end] = x;
ps->size++;
}
⑤顺序表的头部数值删除
void SeqListPopFront(SeqList* ps)
{
assert(ps);
int tail = 0;
while (tail != ps->size)
{
ps->a[tail] = ps->a[tail + 1];
tail++;
}
ps->a[tail] = 0;
ps->size--;
}
⑥顺序表的尾部数值插入
void SeqListPushBack(SeqList* ps, SLDateType x)
{
assert(ps);
SeqListCapCheck(ps);
ps->a[ps->size] = x;
(ps->size)++;
}
⑦顺序表的尾部数值删除
void SeqListPopBack(SeqList* ps)
{
assert(ps);
ps->a[ps->size-1] = 0;
ps->size--;
}
⑧顺序表的指定数值查找
int SeqListFind(SeqList* ps, SLDateType x)
{
assert(ps);
int i = 0;
for (i = 0; i < (ps->size); i++)
{
if (ps->a[i] == x)
{
return i;
}
}
return -1;
}
⑨顺序表的指定位置数值插入
void SeqListInsert(SeqList* ps, int pos, SLDateType x)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
SeqListCapCheck(ps);
int end = ps->size;
while (end != pos)
{
ps->a[end] = ps->a[end - 1];
end--;
}
ps->a[end] = x;
ps->size++;
}
⑩顺序表的指定位置数值删除
void SeqListErase(SeqList* ps, int pos)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
ps->a[pos] = 0;
int end = ps->size - 1;
while (pos != end)
{
ps->a[pos] = ps->a[pos + 1];
pos++;
}
ps->size--;
ps->a[ps->size] = 0;
}
⑪顺序表的内存检测是否足够
void SeqListCapCheck(SeqList* ps)
{
assert(ps);
if (ps->size == ps->capacity)
{
SLDateType* tmp = (SLDateType*)realloc(ps->a, sizeof(SLDateType) * (ps->capacity) * 2);
if (NULL == tmp)
{
printf("realloc fail");
return;
}
ps->a = tmp;
ps->capacity *= 2;
}
}
3.顺序表的优势与劣势
①优势:
⑴随机访问:由于顺序表中的元素在内存中是连续存储的,因此可以通过元素的下标值(索引)来直接访问和操作元素,这样可以实现O(1)的随机访问效率。
⑵缓存友好:顺序表的存储结构使得它更容易被计算机的缓存系统所利用,这样可以提高访问速度。
⑶内存占用:由于顺序表使用一段连续的存储空间来存储元素,因此相比链式数据结构,顺序表更加紧凑,占用的内存空间更小。
②劣势:
⑴插入和删除:在顺序表中插入和删除元素时,需要将插入或删除点后的所有元素向后或向前移动,这样会导致操作的时间复杂度为O(n),其中n是表中元素的个数。
⑵动态扩容:当顺序表的存储空间不足时,需要进行动态扩容。这涉及到重新分配一段更大的内存空间,并将原来的元素复制到新的内存空间中。这样会导致操作的时间复杂度为O(n),其中n是表中元素的个数。
⑶内存浪费:由于有些顺序表是静态的,即其大小在创建时已经确定,因此如果表中元素的数量不够多,就会导致内存的浪费。同时,如果元素的数量超过了顺序表的大小,就需要进行动态扩容,这也会导致一定的内存浪费。