1.顺序表的概念
1.1线性表
要知道顺序表之前我们要知道线性表是什么
线性表(Linear List)是一种常见的数据结构,它用来储存具有线性关系的数据元素的集合
线性表的逻辑性是连续的
这意味着数据元素之间都存在着一对一的关系,即除了第一个元素外,每个元素都有且仅有一个前驱元素,除了最后一个元素都有后继元素。这种关系在逻辑上可以抽象为一条直线结构。
就好比排队结账:
顾客的结账都是有顺序的,顾客一到顾客二....你通过顾客一可以找到顾客二,通过顾客二可以找到顾客三与顾客一,这种行为在逻辑上是连续的
线性表的物理性不一定连续
这指的是线性表在内存中的存储方式可以是不连续的。它可以采用链式储存或者顺序储存,所以说线性表的数据在内存中的地址既可以是分散的也可以是连续的,即物理上不一定连续
1.2 顺序表
而我们的顺序表就是线性表的一种,它的逻辑上是连续的物理上也是连续的。
顺序表的本质就是经过封装的数组,它实现了对素组的增删查改
2.顺序表的分类
2.1 静态顺序表
静态顺序表缺陷:空间给少了不够⽤,给多了造成空间浪费
2.2 动态顺序表
3.动态顺序表的实现
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int SLDataType;
//顺序列表结构体
typedef struct SeqList {
SLDataType* arr;
int size; //有效数据
int capacity; //空间大小
}SL;
//初始化顺序表
void SLInit(SL* ps);
//销毁顺序表
void SLDestroy(SL* ps);
//打印顺序表
void PrintfSL(SL ps);
//扩容
void SLCheckCapacity(SL* ps);
//尾部插入
void SLPushBack(SL* ps, SLDataType x);
//尾部删除
void SLPopBack(SL* ps);
//头部插入
void SLPushFront(SL* ps, SLDataType x);
//头部删除
void SLPopFront(SL* ps);
//指定位置插入数据
void SLInsert(SL* ps, int pos, SLDataType x);
//指定位置删除数据
void SLErase(SL* ps, int pos);
//查找数据
int SLFind(SL* ps, SLDataType x);
#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
//初始化顺序表
void SLInit(SL* ps) {
assert(ps);
ps->arr = NULL;
ps->capacity = ps->size = 0;
}
//销毁顺序表
void SLDestroy(SL* ps) {
assert(ps);
if(ps->arr)
{
free(ps->arr);
}
ps->arr = NULL;
ps->capacity = ps->size = 0;
}
//打印顺序表
void PrintfSL(SL ps) {
for (int i = 0; i < ps.size; i++)
{
printf("%d ", ps.arr[i]);
}
printf("\n");
}
//扩容
void SLCheckCapacity(SL* ps) {
assert(ps);
//有效数据和空间大小一样,就代表空间满了
if (ps->size == ps->capacity)
{
int newcapacity;
SLDataType* newps;
//如果一开始没有空间,就给它一个空间,否则空间就*2倍增长
newcapacity = ps->capacity == 0 ? 4 : ps -> capacity * 2;
//开辟新的空间
newps = (SLDataType*)realloc(ps->arr, newcapacity*sizeof(SLDataType));
//判断新的空间有没有开辟成功
if (newps == NULL)
{
perror("realloc");
exit (1);
}
ps->arr = newps;
ps->capacity = newcapacity;
}
}
//尾部插入
void SLPushBack(SL* ps, SLDataType x) {
assert(ps);
//先判断空间是不是满了,要不要扩容
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);
//增加数据pos无所谓等不等于size,pos = size 就相当于尾插
assert(pos >= 0 && pos <= ps->size);
SLCheckCapacity(ps);
for (int i = ps->size; i > pos; i--)//从最后面的数据开始放到,size的位置
{
ps->arr[i] = ps->arr[i - 1];//最后一次执行arr[pos + 1] = arr[pos]
} //要点:还要注意i最后要到哪里,这里的i最后要到pos的位置,所以我们以pos为基准
//看它最后一次直线什么语句
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++)//从最前面的数据放到pos的位置
{
ps->arr[i] = ps->arr[i + 1];//最后一次执行size - 2 = size - 1
}
ps->size--;
}
//查找数据
int SLFind(SL* ps, SLDataType x) {
assert(ps);
for (int i = 0; i < ps->size; i++)
{
if (ps->arr[i] == x)
{
return i; //找到了返回数组下标
}
}
return -1; //找不到返回负数
}
//查找数据并且打印
int SLFindPrint(SL* ps, SLDataType x) {
int find = SLFind(ps, x);
if (find)
printf("找到了!您要查找的'%d',下标为:%d", x, find);
else
printf("很遗憾没有找到");
}