顺序表和链表
文章目录
数据结构中有两种结构:
- 物理结构:真实内存的结构,比如,数组,就是在内存中真的开辟了一块连续的空间
- 逻辑结构:是一种想象出来的结构
可以大概理解为一个程序运行起来的准备工作比较多,在准备阶段,把一个完整的程序会拆开,分成一段一段或者一页一页的内容,让他们独立完成,最后组装
之前讲过的数据存储的位置,即栈、堆、静态区啥的,他们都有自己的存储方式,因此他们就有自己的数据结构
对于栈来说,会先使用高地址,再使用低地址,从高到低,也就是所谓的向下生长
可以创建一个main函数,再创建test1函数,其内部再调用test2函数,那么这个程序里面的函数,创建的顺序就是main->test1->test2,每个函数里面放一个变量,再打印这个变量的地址就会发现,这个地址会一直减小
也就印证了,栈是向下生长的结论
对于堆来说,本应该是向上生长的,也就是从低地址到高地址
用malloc申请空间存放变量a,再打印a的地址即可,但是有很大的可能,是乱序的,因为对于malloc来说,只需要找到合适的空间即可,
那么假如在程序运行的时候,堆上的空间突然被释放了一块,malloc就会看看合适不,哪怕这个空间跟之前申请的空间相隔很远也会使用
总之,堆不一定按顺序使用的
线性表
在物理结构中,只有两种形式:
- 数组
- 链表
顺序表(SeqList)
就是一个数组,既然是数组,里面的数据就是连续的,学会使用这个结构,以后使用vector会得心应手一些
静态顺序表(挫!)
这种顺序表,就是一个结构体,结构体里面有个固定大小的数组,还有一个记录当前数据个数的变量
struct SeqList
{
int array[10];//存数的
int sz;//记录个数的
};
// 这种定义的方式比较土
// 下面这种方式是以后常用的,因为融合了很多知识点,使用起来也更方便
typedef int SeqListDataType;// 这里是类型重定义,为了以后修改结构体里面数组的类型,现在是int,以后项改double,只需要改int就可以了,其他接口不用改
#define N 10//常量重定义//方便修改数组大小
typedef struct SeqList
{
SeqListDataType array[N];
size_t size;//因为数组的个数不可能是负数,就用无符号整型size_t
}SeqList;
//从现在开始要规范变量的命名,为了对接以后将会学习的STL库函数啥的
动态顺序表(vector的原型)
typedef int SeqListDataType;
typedef struct SeqList
{
SeqListDataType*a;//一个指针维护着申请的类型空间
size_t size; // 当前顺序表中存着几个数
size_t capacity;// 容量 的意思,也是vector里面用的
}SeqList,SL;
以上就是顺序表的结构体原型了,下面要开始设计接口了
顺序表的各种接口的实现
基本增删查改接口
顺序表初始化
void SeqListInit(SeqList* psl)
{
//要玩就玩动态的 vector
psl->a = NULL;
psl->sz = 0;
psl->capacity = 4;
psl->a = (SLDataType*)malloc(sizeof(SLDataType) * psl->capacity);
if (psl->a == NULL)//申请失败
{
perror("a");
exit(-1);// 这是一种特别粗暴的方式去结束程序,就像一个人发烧直接就埋了
}
}
顺序表销毁
void SeqListDestory(SeqList* psl)
{
free(psl->a);
psl->a = NULL;
psl->sz = 0;
psl->capacity = 0;
}
顺序表打印
void SeqListPrint(SeqList* psl)
{
assert(psl);
for (int i = 0; i < psl->sz; i++)
{
printf("%d ", psl->a[i]);
}
printf("\n"