一、静态顺序表
#define N 100
typedef int SLDataType;
struct SeqList
{
SLDataType a[N];//定长数组
int size;//有效数据个数
};
为什么使用typedef ?
--直接写成int不便于更改,如果代码中有很多int需要改成char ,但又不是所有的int都要改成char
静态顺序表缺陷:空间给少了不够⽤,给多了造成空间浪费
二、动态顺序表
typedef struct SeqList
{
SLDataType* arr;//存储数据的底层结构
int capacity;//记录数据表的空间大小
int size;//记录顺序表当前有效的数据个数
}SL;
typedef struct SeqList SL;
以上两种typedef都可以
1.初始化
void SLInit(SL* ps);
void SLInit(SL* ps)
{
ps->arr = NULL;
ps->size = ps->capacity = 0;
}
为什么使用指针?传值调用不会改变实参,所以需要传址调用
2.打印
void SLPrint(SL* ps);
void SLPrint(SL* ps)
{
int i;
for (i = 0; i < ps->size; i++)
{
printf("%d ", ps->arr[i]);
}
printf("\n");
}
3.顺序表的头部/尾部插入
尾插
void SLPushBack(SL* ps, SLDataType x);
void SLPushBack(SL * ps, SLDataType x)
{
//断言--粗暴的解决方式
//assert(ps!=NULL);
assert(ps);
//if判断--温柔的解决方式
/*if (ps == NULL)
return;*/
//空间不够,扩容
SLCheckCapacity(ps);
//空间足够,直接插入
/*ps->arr[ps->size] = x;//对一个数组,下标size是当前位置
ps->size++;*/
ps->arr[ps->size++] = x;//插入之后,size要更新
}
扩容
void SLCheckCapacity(SL* ps)
{
//空间不够,扩容
if (ps->size == ps->capacity)
{
int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
SLDataType* tmp = (SLDataType*)realloc(ps->arr, newCapacity * sizeof(SLDataType));
if (tmp == NULL)
{
perror("realloc fail!\n");
exit(1);//扩容失败,直接中断程序
}
//扩容成功
//free(ps->arr);//error,不需要释放,realloc自己会做这件事
ps->arr = tmp;
ps->capacity = newCapacity;
}
}
扩容最好是成倍扩容,1.5倍或者2倍
因为初始化capacity为0,所以用一个条件操作符先给capacity一个4个大小的空间,后续倍增
测试尾插
void slTest01()
{
SL sl;
SLInit(&sl);
//测试尾插
SLPushBack(&sl, 1);
SLPushBack(&sl, 2);
SLPushBack(&sl, 3);
SLPushBack(&sl, 4);
SLPrint(&sl);
SLPushBack(&sl, 5);//此时需要扩容了
SLPrint(&sl);
//SLPushBack(NULL, 6);//error,需要判断不是NULL
}
int main()
{
slTest01();
return 0;
}
头插
void SLPushFront(SL* ps, SLDataType x);
void SLPushFront(SL* ps, SLDataType x)
{
assert(ps);
//判断是否扩容
SLCheckCapacity(ps);
//旧数据往后挪动一位
int i;
for (i = ps->size; i > 0; i--)//i = 1
{
ps->arr[i] = ps->arr[i - 1];//ps->arr[1] = ps->arr[0]
}
ps->arr[0] = x;
ps->size++;
}
测试头插
void slTest01()
{
SL sl;
SLInit(&sl);
SLPushBack(&sl, 1);
SLPushBack(&sl, 2);
SLPushBack(&sl, 3);
SLPushBack(&sl, 4);
//头插
SLPushFront(&sl, 5);
SLPushFront(&sl, 6);
SLPushFront(&sl, 7);
SLPrint(&sl);//7 6 5 1 2 3 4
}
4.顺序表的头部/尾部删除
尾刪
void SLPopBack(SL* ps);
void SLPopBack(SL* ps)
{
assert(ps);
assert(ps->size);
//顺序表不为空
/*ps->arr[ps->size - 1] = -1;//不能这么写,这个-1是无用的还是赋值的?
//直接让size--,不对后续操作产生影响,此时size-1位置的数据会被后续操作直接覆盖
ps->size--;*/
ps->size--;
}
测试尾刪
void slTest01()
{
SL sl;
SLInit(&sl);
SLPushBack(&sl, 1);
SLPushBack(&sl, 2);
SLPushBack(&sl, 3);
SLPushBack(&sl, 4);
//尾删 1 2 3 4
SLPopBack(&sl);
SLPopBack(&sl);
SLPrint(&sl); //1 2
}
头删
void SLPopFront(SL* ps);
void SLPopFront(SL* ps)
{
assert(ps);
assert(ps->size);
//不为空执行挪动操作
int i;
for (i = 0; i < ps->size-1; i++)
{
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
测试头删
void slTest01()
{
SL sl;
SLInit(&sl);
SLPushBack(&sl, 1);
SLPushBack(&sl, 2);
SLPushBack(&sl, 3);
SLPushBack(&sl, 4);
//头删 1 2 3 4
SLPopFront(&sl);
SLPopFront(&sl);
SLPrint(&sl); //3 4
}
5.指定位置插入数据
void SLInsert(SL* ps, int pos, SLDataType x);
void SLInsert(SL* ps, int pos, SLDataType x)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size);
SLCheckCapacity(ps);
//pos及之后的数据往后挪动一位,pos空出来
int i;
for (i = ps->size; i > pos; i--)
{
ps->arr[i] = ps->arr[i - 1];//ps->arr[pos+1] = ps->arr[pos] 把pos空出来
}
ps->arr[pos] = x;
ps->size++;
}
测试
void slTest01()
{
SL sl;
SLInit(&sl);
SLPushBack(&sl, 1);
SLPushBack(&sl, 2);
SLPushBack(&sl, 3);
SLPushBack(&sl, 4);
//指定位置插入
SLInsert(&sl, 0, 100);
SLPrint(&sl);
SLInsert(&sl, sl.size, 200);
SLPrint(&sl);
//SLInsert(&sl, 100, 200);//error 会出现很奇怪的一个数字,所以需要限制
//SLPrint(&sl);
}
6.删除指定位置数据
void SLErase(SL* ps, int pos);
void SLErase(SL* ps, int pos)
{
assert(ps);
assert(pos >= 0 && pos < ps->size);
//pos以后的数据往前挪动一位
int i;
for (i = pos; i < ps->size - 1; i++)
{
ps->arr[i] = ps->arr[i + 1];//ps->arr[size-2] = ps->arr[size-1]
}
ps->size--;
}
测试
void slTest01()
{
SL sl;
SLInit(&sl);
//测试尾插
SLPushBack(&sl, 1);
SLPushBack(&sl, 2);
SLPushBack(&sl, 3);
SLPushBack(&sl, 4);
/*SLErase(&sl, 0);
SLPrint(&sl);*/
SLErase(&sl, 2);
SLPrint(&sl);
SLErase(&sl, sl.size - 1);
SLPrint(&sl);
}
7.在顺序表中查找x
int SLFind(SL* ps, SLDataType x);
int SLFind(SL* ps, SLDataType x)
{
assert(ps);
int i;
for (i = 0; i < ps->size; i++)
{
if (ps->arr[i] == x)
{
return i;
}
}
return -1;
}
测试
void slTest02()
{
SL sl;
SLInit(&sl);
SLPushBack(&sl, 1);
SLPushBack(&sl, 2);
SLPushBack(&sl, 3);
SLPushBack(&sl, 4);
SLPrint(&sl);//1 2 3 4
int ret = SLFind(&sl, 3);
if (ret < 0)
printf("找不到\n");
else
printf("找到了,在下标为%d位置\n", ret);
}
int main()
{
slTest02();
return 0;
}
8.销毁
void SLDestory(SL* ps);
void SLDestory(SL* ps)
{
assert(ps);
if(ps->arr)
free(ps->arr);
ps->arr = NULL;
ps->size = ps->capacity = 0;
}