#顺序表# 顺序表
文章目录
一.顺序表简单的说明
-
本质:顺序表是通过开辟一个连续的空间来存储数据。即通过数组存储数据。
-
特性:2.1 中间/头部的插入删除,时间复杂度为O(N)
2.2 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
2.3 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,
再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。
-
顺序表的存储结构
3.1顺序表静态存储结构
#define N 7 typedef int SLdataType; typedef struct SeqList { SLdataType array[N];//创建一个定长数组; size_t size;//有效数据个数 ,即数组的下标 }SL;
静态存储结构数组大小是定值,数据存满后无法扩容。#difine 将标识符 N 的值 定义为7
typedef 是类型重定义 就是给一个东西取个外号,让这个外号可以被编译器识别
3.2顺序表动态存储结构
typedef int SLdataType; typedef struct SeqList { SLdataType* arrayPointer;//记录数组地址,数组大小可以通过内存函数进行调整. size_t size;//有效数据个数 size_t capacity;//记录数组的最大容量,通过 与有效数据个数 进行比较 来 判断数组 是否 还有 空间 存储数据 }SL;
二.动态顺序表的实现
1.动态顺序表的功能
功能包含:1.顺序表的初始化,即
1.1 在栈空间malloc一个数组并将地址信息保存与顺序表结构中。
1.2 将有效数组个数 初始化为0.
1.3 记录数组的最大容量,申请的数组空间所能存储的最大元素个数
2.顺序表空间容量检查: 检查是否还有空间存储数据,不够时进行扩容。
3.头插 :在下标为0的位置插入数据
4.尾插 : 在下标为 size 的的地方插入数据(size是数组当前的有效数据个数,即当前存储了多少个数,
下标是从0 开始所以比元素个数小1.)
5.在指定下标位置插入数据
6.头删:将下标为0的位置数据删除
7.尾删:将下标为 size 的位置数据删除
8.删除指定下标的数据
9.查找数据所在下标
10.修改指定位置的数据
11.顺序表数数据打印
12.顺序表销毁 : 在栈空间上储存的数据需要手动释放
2.顺序表初始化
void SLInit(SL*ps)
{
assert(ps);
ps->arrayPointer=(SLdataType*)malloc(sizeof(SLdataType)*4);//为数组申请4个元素空间
if(ps->arrayPointer==NULL)
{
perror("arrayPointer malloc fail");
return NULL;
}
ps->size=0;
ps->capacity=4;
}
3.顺序表的容量检查
void SLCapacityCheck(SL*ps)
{
assert(ps);
if(ps->size==ps->capacity)
{
SLdataType*p=(SLdataType*)realloc(ps->arrayPointer,sizeof(SLdataType)*ps->capacity*2);
if(p==NULL)
{
perror("realloc fail");
return ;
}
ps->arrayPointer=p;
ps->capacity*=2;//最大容量重新记录
}
}
4.头插
void SLPushFront(SL*ps,SLdataType x)
{
assert(ps);//指针为空检查
SLCapacityCheck(ps);//容量检查
int i=0;
int size=ps->size;
for(i=size;i>0;i--)
{
ps->arrayPointer[i]= ps->arrayPointer[i-1];
}
ps->arrayPointer[0]=x;
ps->size++;
}//时间复杂度为o(N)
5.尾插
void SLPushBack(SL*ps,SLdataType x)
{
assert(ps);//指针为空检查
SLCapacityCheck(ps);//容量检查
ps->arrayPointer[ps->size]=x;
ps->size++;
}//时间复杂度为o(1)
6.在pos位置之前插入数据
void SLInsert(SL*ps,int pos,SLdataType x)
{
assert(ps);//指针为空检查
SLCapacityCheck(ps);//容量检查
int moveDataNum=ps->size-1-pos+1;//ps->size是当前存储的元素个数,与下标一起进行计算须先自减1;
int i=0;
int size=ps->size;
for(i=0;i<moveDataNum;i++)//挪数据循环,挪 moveDataNum 次
{
ps->arrayPointer[size-i]=ps->arrayPointer[size-i-1];
}
ps->arrayPointer[pos]=x;
ps->size++;
}
7.头删
void SLPopFront(SL*ps)
{
assert(ps);//指针为空检查
assert(ps->size);//顺序表为空检查
int i=0;
int size=ps->size;
for(i=1;i<size;i++)//挪数据循环,挪 size-1 次
{
ps->arrayPointer[i-1]=ps->arrayPointer[i];//数据覆盖,变相删除
}
ps->size--;
}
8.尾删
void SLPopback(SL*ps)
{
assert(ps);//指针为空检查
assert(ps->size);//顺序表为空检查
int i=0;
int size=ps->size;
ps->size--;
}
9.删除指定下标的数据
void SLErase(SL*ps,int pos)
{
assert(ps);//指针为空检查
assert(ps->size);//顺序表为空检查
int moveDataNum=ps->size-1-pos+1;//ps->size是当前存储的元素个数,与下标一起进行计算须先自减1;
int i=0;
int size=ps->size;
for(i=0;i<moveDataNum;i++)//挪数据循环,挪 moveDataNum 次
{
ps->arrayPointer[pos+i]=ps->arrayPointer[pos+i+1];
}
ps->size--;
}
10.查找数据所在下标
int SLFind(SL*ps,SLdataType x)
{
assert(ps);//指针为空检查
int i=0;
for(i=0;i<ps->size;i++)
{
if(ps->arrayPointer[i]==x);
//printf("第一个值为 %d 的数据下标为 %d\n",x,i);
return i;
}
printf("未发现该数据\n");
return -1;
}
11.修改下标为pos位置的数据
void SLModify(SL*ps,int pos,SLdataType x)
{
assert(ps);
assert(pos<=ps->size||pos>=0)
if(pos==ps->size)
{
SLPushBack(ps,x);//尾插
return;
}
ps->arrayPointer[pos]=x;
}
12.顺序表数据打印
void SLprint(SL*ps)
{
int i = 0;
printf("\n 下标:>");
for (i = 0; i < ps->size; i++)
{
printf(" %-3d ", i);
}
printf("\n 数据:>");
for (i = 0; i < ps->size; i++)
{
printf(" %-3d ", ps->arrayPointer[i]);
}
printf("\n");
}
13.顺序表销毁
void SLDestory(SL*ps)
{
assert(ps);
free(ps->arrayPointer);
ps->arrayPointer=NULL;
ps->capacity=0;
ps->size=0;
}
14代码汇总SL.c
#define _CRT_SECURE_NO_WARNINGS
#include"SL.h"
void SLInit(SL* ps)
{
assert(ps);
ps->arrayPointer = (SLdataType*)malloc(sizeof(SLdataType) * 4);//为数组申请4个元素空间
if (ps->arrayPointer == NULL)
{
perror("arrayPointer malloc fail");
return NULL;
}
ps->size = 0;
ps->capacity = 4;
}
void SLCapacityCheck(SL* ps)
{
assert(ps);
if (ps->size == ps->capacity)
{
SLdataType* p = (SLdataType*)realloc(ps->arrayPointer, sizeof(SLdataType) * ps->capacity * 2);
if (p == NULL)
{
perror("realloc fail");
return;
}
ps->arrayPointer = p;
ps->capacity *= 2;//最大容量重新记录
}
}
// 4.头插
void SLPushFront(SL * ps, SLdataType x)
{
assert(ps);//指针为空检查
SLCapacityCheck(ps);//容量检查
int i = 0;
int size = ps->size;
for (i = size; i > 0; i--)
{
ps->arrayPointer[i] = ps->arrayPointer[i - 1];
}
ps->arrayPointer[0] = x;
ps->size++;
}//时间复杂度为o(N)
// 5.尾插
void SLPushBack(SL * ps, SLdataType x)
{
assert(ps);//指针为空检查
SLCapacityCheck(ps);//容量检查
ps->arrayPointer[ps->size] = x;
ps->size++;
}//时间复杂度为o(1)
// 6.在pos位置之前插入数据
void SLInsert(SL * ps, int pos, SLdataType x)
{
assert(ps);//指针为空检查
SLCapacityCheck(ps);//容量检查
int moveDataNum = ps->size - 1 - pos + 1;//ps->size是当前存储的元素个数,与下标一起进行计算须先自减1;
int i = 0;
int size = ps->size;
for (i = 0; i < moveDataNum; i++)//挪数据循环,挪 moveDataNum 次
{
ps->arrayPointer[size - i] = ps->arrayPointer[size - i - 1];
}
ps->arrayPointer[pos] = x;
ps->size++;
}
// 7.头删
int SLPopFront(SL * ps)
{
assert(ps);//指针为空检查
if (ps->size == 0)//顺序表为空检查
{
printf("\n顺序表已经删空了\n");
return 1;
}
int i = 0;
int size = ps->size;
for (i = 1; i < size; i++)//挪数据循环,挪 size-1 次
{
ps->arrayPointer[i - 1] = ps->arrayPointer[i];//数据覆盖,变相删除
}
ps->size--;
return 0;
}
// 8.尾删
int SLPopback(SL * ps)
{
assert(ps);//指针为空检查
if (ps->size == 0)//顺序表为空检查
{
printf("\n顺序表已经删空了\n");
return 1;
}
int i = 0;
int size = ps->size;
ps->size--;
}
// 9.删除指定下标的数据
void SLErase(SL * ps, int pos)
{
assert(ps);//指针为空检查
assert(ps->size);//顺序表为空检查
int moveDataNum = ps->size - 1 - pos + 1;//ps->size是当前存储的元素个数,与下标一起进行计算须先自减1;
int i = 0;
int size = ps->size;
for (i = 0; i < moveDataNum; i++)//挪数据循环,挪 moveDataNum 次
{
ps->arrayPointer[pos + i] = ps->arrayPointer[pos + i + 1];
}
ps->size--;
}
// 10.查找数据所在下标
int SLFind(SL * ps, SLdataType x)
{
assert(ps);//指针为空检查
int i = 0;
for (i = 0; i < ps->size; i++)
{
if (ps->arrayPointer[i] == x)
{
printf("第一个值为 %d 的数据的下标为 %d\n", x, i);
return i;
}
}
printf("未发现该数据\n");
return -1;
}
// 11.修改下标为pos位置的数据
void SLModify(SL * ps, int pos, SLdataType x)
{
assert(ps);
assert(pos <= ps->size || pos >= 0);
if (pos == ps->size)
{
SLPushBack(ps, x);//尾插
return;
}
ps->arrayPointer[pos] = x;
}
//12.顺序表数据打印
void SLprint(SL * ps)
{
int i = 0;
printf("\n 下标:>");
for (i = 0; i < ps->size; i++)
{
printf(" %-3d ", i);
}
printf("\n 数据:>");
for (i = 0; i < ps->size; i++)
{
printf(" %-3d ", ps->arrayPointer[i]);
}
printf("\n");
}
// 13.顺序表销毁
void SLDestory(SL * ps)
{
assert(ps);
free(ps->arrayPointer);
ps->arrayPointer = NULL;
ps->capacity = 0;
}
15测试代码text.c
#define _CRT_SECURE_NO_WARNINGS
#include"SL.h"
int main()
{
SL s;
SLInit(&s);
SLPopFront(&s);
SLPopback(&s);
SLPushFront(&s, 1);
SLPushFront(&s, 2);
SLPushFront(&s, 3);
SLPushFront(&s, 4);
SLPushFront(&s, 5);
SLPushBack(&s, 6);
SLPushBack(&s, 7);
SLPushBack(&s, 8);
SLPushBack(&s, 9);
SLPushBack(&s, 10);
SLprint(&s);
int pos = SLFind(&s, 10);
SLModify(&s, pos, 20);
SLModify(&s, --pos, 20);
SLInsert(&s, pos, 100);
SLErase(&s, 4);
SLprint(&s);
SLDestory(&s);
return 0;
}