顺序表
顺序表是一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用的数组存储。在数组上完成数据的增删查改;
顺序表一般可以分为:
- 静态顺序表:使用定长数组存储;
- 动态顺序表:使用动态开辟的数组存储;
静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致了N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小;
顺序表:物理上和逻辑上都线性连续
实现(代码)
定义结构
typedef int SLDataType;//存储单元类型
typedef struct
{
SLDataType* a;//存储空间基地址,类似于数组首地址
size_t size;//顺序表长度
size_t capacity;//当前分配的存储容量
}SeqList;
初始化、销毁
void SeqListInit(SeqList* ps)//顺序表初始化
{
assert(ps);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
void SeqListDestory(SeqList* ps)//销毁顺序表
{
assert(ps);
free(ps->a);//释放存储空间
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
顺序表的扩容及打印
void CheckCapacity(SeqList* ps)//扩容
{
assert(ps);
if (ps->size == ps->capacity)//判断是否需要扩容
{
size_t newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;//若当前空间为空,则给它4个空间,否则给他的空间扩张一倍
ps->a = (SLDataType*)realloc(ps->a, newcapacity*sizeof(SLDataType));
ps->capacity = newcapacity;
}
}
void SeqListPrint(SeqList* ps)//打印顺序表
{
assert(ps);
for (size_t i = 0; i < ps->size; i++)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
顺序表尾插,尾删,头插,头删
void SeqListPushBack(SeqList* ps, SLDataType x)//尾插
{
assert(ps);
CheckCapacity(ps);
ps->a[ps->size] = x;
ps->size++;
}
void SeqListPopBack(SeqList* ps)//尾删
{
assert(ps);
ps->size--;
}
void SeqListPushFront(SeqList* ps, SLDataType x)//头插
{
assert(ps);
CheckCapacity(ps);
size_t end = ps->size;
while (end)//将顺序表中的数据都往后移动一格,留出了第一个位置
{
ps->a[end] = ps->a[end - 1];
end--;
}
ps->a[0] = x;
ps->size++;
}
void SeqListPopFront(SeqList* ps)//头删
{
assert(ps);
size_t start = 0;
while (start < ps->size-1)//直接顺序表数据往前移动一个,覆盖前一个数据
{
ps->a[start] = ps->a[start + 1];
start++;
}
ps->size--;
}
顺序表查找某个数
int SeqListFind(SeqList* ps, SLDataType x)//顺序表查找某个数
{
assert(ps);
for (size_t i = 0; i < ps->size; i++)//从第一个位置开始往后遍历寻找
{
if (ps->a[i] == x)
{
return 1;//找到了
}
}
return -1;//没找到
}
顺序表在pos位置插入x
int SeqListInsert(SeqList* ps, size_t pos, SLDataType x)//顺序表在pos位置插入x
{
assert(ps);
assert(pos < ps->size);//检查输入pos位置是否合适
CheckCapacity(ps);
size_t end = ps->size;
while (end > pos)//将pos以及后面的数据向后移动,将pos位置空出
{
ps->a[end] = ps->a[end-1];
end--;
}
ps->a[pos] = x;
ps->size++;
}
删除顺序表pos位置上的数
int SeqListErase(SeqList* ps, size_t pos)//删除顺序表pos位置上的数
{
assert(ps);
assert(pos < ps->size);
while (pos < ps->size-1)//直接从pos后一个位置开始,向前移动一格,覆盖住前一个
{
ps->a[pos] = ps->a[pos + 1];
pos++;
}
ps->size--;
}
头文件
#pragma once
#include<stdio.h>
#include<stdlib.h>
typedef int SLDataType;//存储单元类型
typedef struct
{
SLDataType* a;//存储空间基地址,类似于数组首地址
size_t size;//顺序表长度
size_t capacity;//当前分配的存储容量
}SeqList;
void SeqListInit(SeqList* ps);//初始化
void SeqListDestory(SeqList* ps);//清理空间
void CheckCapacity(SeqList* ps);//扩容
void SeqListPrint(SeqList* ps);//打印顺序表
void SeqListPushBack(SeqList* ps, SLDataType x);//尾插
void SeqListPopBack(SeqList* ps);//尾删
void SeqListPushFront(SeqList* ps, SLDataType x);//头插
void SeqListPopFront(SeqList* ps);//头删
int SeqListFind(SeqList* ps, SLDataType x);//顺序表查找某个数
int SeqListInsert(SeqList* ps, size_t pos, SLDataType x);//顺序表在pos位置插入x
int SeqListErase(SeqList* ps, size_t pos);//删除顺序表pos位置上的数
主函数
#include"SeqList.h"
int main()
{
SeqList s;
SeqListInit(&s);
SeqListDestory(&s);
system("pause");
return 0;
}
顺序表存在的问题:
- 中间/头部的插入删除,时间复杂度为O(N);
- 增容需要申请新空间,拷贝数据,释放旧空间,会有不小的消耗;
- 增容一般是呈2倍的增长,势必会有一定的空间浪费;