线性表
线性表是n个具有相同特性的数据元素的有限序列。
常见的有:顺序表、链表、栈、队列、字符串....
线性表在逻辑上是线性结构的,即一条连续的直线
但在物理结构上不一定是连续的,其在物理存储时,通常以数组和链式结构的形式存储
顺序表
使用一段地址连续的存储单元依次存储数据元素的线性结构
ps:顺序表就是数组,但在数组基础上,要求数据从头开始且连续存储,不能跳跃或间隔
顺序表存在的缺陷:
1.空间不够需要扩容,而扩容会付出一定代价
①原地扩容:
 还是原地址,代价低,至少不需要拷贝原数据
②异地扩容:
 已经改变
2.避免频繁扩容:平常空间满了扩2倍,可能会导致一定的空间浪费
 如100->200,但实际我们只需要120个空间,浪费80个
3.要求数据从头开始连续存储,那么我们在头部或中间位置插入数据需要挪动数据,效率低
优点:
1.支持随机访问
 2.对于有些算法,需要结构支持随机访问,如二分查找,优化后的快排等
下面直接创建顺序表
SeqList.h 头文件
1、静态顺序表
#define N 1000
typedef int SLDataType;    // 以后需要存储不同类型的数据,可以直接修改
typedef struct SeqList
{
    SLDataType a[N];
    int size; // 表示数组中存储了多少个数据
}SL;
//    接口函数 - 函数名是根据STL风格
void SeqListInit(SL* ps);    //    初始化数组
//    静态:容量给小则不够用,给大则浪费空间
void SeqListPushBack(SL* ps, SLDataType x);    //尾插
void SeqListPopBack(SL* ps);                //尾删
void SeqListPushFront(SL* ps, SLDataType x);//头插
void SeqListPopFront(SL* ps);                //头删 
2、动态顺序表
typedef int SLDataType;    
//    动态顺序表
typedef struct SeqList
{
    SLDataType* a;
    int size; 
    int capacity;    // 数组实际能存储的空间容量是多少个
}SL;
void SeqListInit(SL *ps);    // 形参 是实参的临时拷贝,不会影响实参 - 传值操作
    //           所以传地址
void SeqListPushBack(SL* ps, SLDataType x);    
void SeqListPopBack(SL* ps);                
void SeqListPushFront(SL* ps, SLDataType x);
void SeqListPopFront(SL* ps);                
SeqList.c源文件
 ```
#pragma once
#include "SeqList.h"
void SeqListInit(SL*ps)
{
    ps->a = NULL;
    ps->size = ps->capacity = 0;
}
void SeqListPushBack(SL* ps, SLDataType x)
{
    //  如果没有空间(0个)或空间不足(满了)
    if (ps->size == ps->capacity)
    {
        int newcapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
        //  三目操作符 是否等于0,是给4,否则给2倍原空间
        SLDataType* tmp = (SLDataType * )realloc(ps->a, sizeof(SLDataType) * newcapacity);
        //    开辟空间
        if (tmp == NULL)
        {
            printf("realloc fail\n");
            exit(-1);
        }
        ps->a = tmp;    //    开辟的空间给结构体
        ps->capacity = newcapacity;// 开辟的大小给原大小
    }
    ps->a[ps->size] = x; // 要传的值给结构体
    ps->size++;
}
void SeqListPushBack(SL* ps, SLDataType x);
void SeqListPopBack(SL* ps);
void SeqListPushFront(SL* ps, SLDataType x);
void SeqListPopFront(SL* ps); 
Source.c文件
#include"SeqList.h"
void TestSeqList1() 
{
    SL sl;
    SeqListInit(&sl);
}
int main()
{
    TestSeqList1();
    return 0;
} 
注意:传结构体不能传值,必须传址,否则无法修改里面内容(形参是实参的临时拷贝,形参的改变不影响实参)
接下来逐个实现接口函数:
①尾删数据
注意此处,未加判断条件,size–将可以为负值(-1,-2…)
 而在–负数后,再增加数据,会造成越界访问

 在销毁时会报错
纵上

法1:加上判断条件,空间大于0才可–
 法2:断言,小于等于0直接报错
②头插数据

 数据向后挪动,空出前面的位置
 同尾删数据,未判断大小,若添加数据过多大于有效空间大小,将造成越界访问,报错

多处用到扩容,这里直接封装成函数

 若空间满了则扩容
③头删数据
和尾插数据类似
 从第二个数据开始一个一个放上去




















