-
简介
- 特点:连续内存空间,元素通过索引访问。
- 时间复杂度:访问元素为O(1),插入/删除元素平均为O(n)(需要移动元素)。
- 应用场景:随机访问频繁,数据大小已知的情况。
-
顺序表和普通数组的区别主要有以下两点:
-
1.顺序表的长度可以动态增长,普通数组的长度是固定的。
2.顺序表要求插入的数据在内存中是连续的,普通数组的数据存放可以不连续。 -
实现顺序表
- 创建SeqList.h,
- SeqList.c,
- test.c文件
-
创建动态顺序表
-
//定义动态顺序表结构 typedef int SLDatatype; typedef struct SeqList { SLDatatype* arr; int capacity; //空间大小 int size; //有效数据个数 }SL; //typedef struct SeqList SL;
-
初始化
-
//初始化 void SLInit(SL* ps);
-
//初始化 void SLInit(SL* ps) { ps->arr = NULL; ps->size = ps->capacity = 0; }
-
销毁
-
//销毁 void SLDestroy(SL* ps);
-
void SLDestroy(SL* ps) { if (ps->arr)//相当于ps->arr != NULL { free(ps->arr); } ps->arr = NULL; ps->size = ps->capacity = 0; }
-
打印
-
//打印 void SLPrint(SL* ps);
-
void SLPrint(SL* ps) { for (int i = 0; i < ps->size; i++) { printf("%d ", ps->arr[i]); } printf("\n"); }
-
扩容
-
void SLCheckCapacity(SL* ps) { //判断空间是否充足 if (ps->size == ps->capacity) { //增容//0*2 = 0 //若capacity为0,给个默认值,否则×2倍 int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity; SLDatatype* tmp = (SLDatatype*)realloc(ps->arr, newCapacity * sizeof(SLDatatype)); if (tmp == NULL) { perror("realloc fail!"); exit(1); } ps->arr = tmp; ps->capacity = newCapacity; }
插入
-
尾插
-
//尾部插入数据 void SLPushBack(SL* ps, SLDatatype x);
-
//尾部插入数据 void SLPushBack(SL* ps, SLDatatype x) { //粗暴的解决方法---断言 assert(ps);//等价于assert(ps != NULL) 温柔的解决方式 //if (ps == NULL) //{ // return; //} SLCheckCapacity(ps); ps->arr[ps->size++] = x; }
-
头插
-
//头部插入数据 void SLPushFront(SL* ps, SLDatatype 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]; } //下标为0的位置空出来 ps->arr[0] = x; ps->size++; }
-
在指定位置之前插入数据
-
//在指定位置之前插入数据 void SLInsert(SL* ps, SLDatatype x, int pos);
-
//在指定位置之前插入数据(空间足够才能直接插入数据) void SLInsert(SL* ps, SLDatatype x, int pos) { assert(ps); assert(pos >= 0 && pos <= ps->size); SLCheckCapacity(ps); //pos及之后的数据整体向后移动一位 for (int i = ps->size; i > pos ; i--) { ps->arr[i] = ps->arr[i - 1]; //pos+1 -> pos } ps->arr[pos] = x; ps->size++; }
删除
-
尾删
-
//尾部删除 void SLPopBack(SL* ps);
-
//尾部删除 void SLPopBack(SL* ps) { assert(ps); assert(ps->size); //ps->arr[ps->size - 1] = -1;//多余了 ps->size--; }
-
头删
-
//头部删除 void SLPopFront(SL* ps);
-
头部删除 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];//i = size-2 } ps->size--; }
-
删除指定位置的数据
-
//删除指定位置的数据 void SLErase(SL* ps, int pos);
-
//删除指定位置的数据 void SLErase(SL* ps, int pos) { assert(ps); assert(pos >= 0 && pos < ps->size); //还有更多的限制:如顺序表不能为空.... //pos之后的数据整体向前挪动一位 for (int i = pos; i < ps->size-1; i++) { 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; }
测试 -
#include "SeqList.h" void SLtest01() { SL s; SLInit(&s); //SLPushBack(&s, 1); //SLPushBack(&s, 2); //SLPushBack(&s, 3); //SLPushBack(&s, 4); //SLPushBack(&s, 5); //SLPushBack(&s, 6); //SLPushBack(NULL , 6); //SLPushFront(&s, 1); //SLPushFront(&s, 2); //SLPushFront(&s, 3); //SLPushFront(&s, 4); //SLPrint(&s); //4 3 2 1 //SLPopBack(&s); //SLPrint(&s); //SLPopBack(&s); //SLPrint(&s); //SLPopBack(&s); //SLPrint(&s); //SLPopBack(&s); //SLPrint(&s); //SLPopBack(&s); //SLPrint(&s); // //SLPopFront(&s); //SLPrint(&s); //SLPopFront(&s); //SLPrint(&s); //SLPopFront(&s); //SLPrint(&s); //SLPopFront(&s); //SLPrint(&s); //SLPopFront(&s); //SLPrint(&s); SLInsert(&s, 11, 0); SLPrint(&s); SLInsert(&s, 22, s.size); SLPrint(&s); SLInsert(&s, 33, 1); SLPrint(&s); SLDestroy(&s); } int main() { SLtest01(); return 0; }
数据结构---顺序表Sequence List(数组Array)
于 2024-09-07 17:10:08 首次发布