目录
线性表的优缺点:
优点:
1,物理空间连续,下表可以直接访问;
2,尾插尾删效率高;
缺点:
1,扩容会有一定的性能消耗;
原因是使用的realloc函数,原地址空间不够,会到新地址重新开辟空间,届时在将原来空间的数据拷贝过来,如果数据多,拷贝就会需要耗费一些性能
2,头部插入和删除或者中间插入和删除效率低下;
原因是需要挪动数组,数据量大的话也是相当耗性能的;
何为顺序表:
物理地址连续的储存单元依次存储数据元素;
说人话就是:是个数组,但是支持扩容.
数据准备:头文件
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLDatatype; //方便后期修改指针的类型
typedef struct SeqList
{
SLDatatype* a; //指向动态数组的指针
int size; //数据个数
int capacity; //容量
}SL;
初始化
///初始化
void SLInit(SL* ps)
{
assert(ps);
ps->a = NULL; //指针指向为NULL
ps->capacity = ps->size = 0;
//容积\大小设置为0
}
柔性报错
//柔性报错,当出现一些极端值或者非法参数,设置对应条件进行拦截;输出函数基本有自己指定
//项目简单文件少还好,代码多了时间长,柑橘会一脸茫然,甚至怀疑
void checkSize(SL* ps,char* str)
{
if (ps->size == 0) //ps->a指针的size为0;
{
printf("%s :: ps->size==0",str);
//输出字符串;
exit(1); //直接退出程序
}
}
硬性报错 - 推荐
assert。满足条件直接打印错误信息(输入的表达式,文件位置,代码行数)
///初始化
void SLInit(SL* ps)
{
assert(ps); //当ps为NULL 也就是表达式子为flase的时候。触发
ps->a = NULL;
ps->capacity = ps->size = 0;
}
打印
///打印
void SLPrint(SL* ps)
{
assert(ps);
//checkSize(ps, "SLPrint"); //柔性
//直接型报错,报错的内容为表达式内容
assert(ps->size >= 0); //表达式为false 触发
for (int i = 0; i < ps->size; ++i)
{
printf("%d ", ps->a[i]);
}
printf("\n");
}
容积判断
///判断容积大小
void SLCheckCapacity(SL* ps)
{
assert(ps);
if (ps->capacity != ps->size) // 当容积(capacity))和大小(size)相等,就说明需要扩容了
return;
SLDatatype newCapacity = ps->capacity == 0 ? 4: ps->capacity * 2; //第一次size为0,扩容4个;后面一次扩容两倍,
SLDatatype* tmp = (SLDatatype*)realloc(ps->a, newCapacity*sizeof(SLDatatype)); // realloc第一次使用,等同malloc
if (tmp == NULL) //判断空间是否创建成功,
{
perror("realloc :: SL");
exit(1);
}
ps->a = tmp; //把新的空间赋予结构体指针
ps->capacity = newCapacity;
//将容积(capacity)改写
}
头插
///头部追加
void SLPushFront(SL* ps, SLDatatype x)
{
assert(ps);
SLCheckCapacity(ps); //追加检查容积大小能不能放下.
for (int i = ps->size; i >= 0; --i)
{
ps->a[i + 1] = ps->a[i];
}
ps->a[0] = x;
++ps->size;
}
实现构图
尾插
///尾部追加
void SLPushBack(SL* ps,SLDatatype x)
{
assert(ps);
SLCheckCapacity(ps);
ps->a[ps->size] = x;
++ps->size;
}
头删
///头部删除
void SLPopFront(SL* ps)
{
assert(ps);
//checkSize(ps, "SLPopFront"); //柔性
assert(ps->size >= 0);
for (int i = 0; i < ps->size; ++i)
{
ps->a[i] = ps->a[i + 1];
}
--ps->size;
}
头删实现构图
尾删
///尾部删除
void SLPopBack(SL* ps)
{
assert(ps);
//checkSize(ps, "SLPopBack"); //柔性
assert(ps->size >= 0);
if (ps->size>=0)
--ps->size;
}
按位插入
///按位插入
void SLInsert(SL* ps, int pos, SLDatatype x)
{
assert(ps);
assert(pos >= 0 && pos <= ps->size); //检测pos和ps->size的值为合法
SLCheckCapacity(ps);
for (int i =ps->size; i >= pos; --i)
{
ps->a[i + 1] = ps->a[i];
}
ps->a[pos] = x;
++ps->size;
}
按位插入实现构图
销毁
///销毁
void SLDestroy(SL* ps)
{
assert(ps);
free(ps->a);
ps->a = NULL;
ps->size = 0;
ps->capacity = 0;
}
查找
///查找
int SLFind(SL* ps, SLDatatype x)
{
assert(ps);
//assert(ps->size >= 0); //表达式为0 触发
推荐
checkSize(ps,"SLFind"); //柔性报错;
for (int i = 0; i < ps->size - 1; ++i)
{
if (x == ps->a[i])
{
return i;
}
}
return -1;
}
main
void test4()
{
SL sl;
//初始化
SLInit(&sl);
SLPushBack(&sl, 5);
SLPushBack(&sl, 5);
SLPushBack(&sl, 5);
SLPushBack(&sl, 5);
SLPushBack(&sl, 5);
SLPrint(&sl);
SLDestroy(&sl);
SLPrint(&sl);
int pos = 0;
printf("请输入要查找的数:>");
scanf("%d", &pos);
printf("%d", SLFind(&sl, pos));
}
int main()
{
test4();
return 0;
}
练习
移除元素
https://leetcode-cn.com/problems/merge-sorted-array/