数据结构——静态顺序表,动态顺序表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是⼀种在实际中⼴泛使 ⽤的 数据结构,常⻅的线性表:顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构,也就说是连续的⼀条直线。但是在物理结构上并不⼀定是连续的, 线性 表在物理上存储时,通常以数组和链式结构的形式存储。
以数组形式存储的线性表又叫做顺序表,以链式结构存储的又叫做链表
顺序表又分为静态顺序表,和动态顺序表;区别在于数组的申请方式,静态方式申请的是静态顺序表,而动态申请的是动态顺序表(malloc或者new)。
静态顺序表的优点是:
1.不需要动态管理内存,代码书写上会比较方便。 2. 没有动态管理内存中申请以及释放空间的时间开销。
缺点是:
1. ⼀旦空间占满,新来的数据就会溢出。 2. 如果为了保险而申请很大的空间,数据量小的情况下,会浪费很多空间。
动态顺序表的优点是:
1.自由的分配空间。数据量小,就只用申请小内存;数据量大,就在原有的基础上扩容。
缺点是:
1.由于需要动态管理内存,代码书写上会比较麻烦。 2. 动态内存的过程中会经常涉及扩容,而扩 容需要申请空间,转移数据,释放空间。 这些操作会有大量的时间消耗。
静态顺序表
顺序表的元素以int类型演示,可以是任何类型
//创建
const int N = 1e6+10;//定义静态顺序表的最大长度
int a[N], n; //直接创建一个大数组表示顺序表,n是当前有多少个元素
//添加一个元素
//尾插
void push_back(int x)
{
a[++n] = x;//空出0,看个人习惯
}
//头插
void push_front(int x)
{
for(int i = n; i >= 1; i--)
{
a[i + 1] = a[i];
}
a[1] = x;
n++;
}
// 任意位置插⼊ - 在位置 p 处,插⼊⼀个 x
void insert(int p, int x)
{
for(int i = n; i >= p; i--) // 注意顺序不要颠倒
{
a[i + 1] = a[i];
}
a[p] = x;
n++;
}
//删除一个元素
// 头删
void pop_front()
{
// 把所有元素向前移动⼀位
for(int i = 2; i <= n; i++) // 顺序不能颠倒
{
a[i - 1] = a[i];
}
n--;
}
//尾删
void pop_back()
{
n--;
}
//任意位置删除
void erase(int p)
{
for(int i = p + 1; i <= n; i++)
{
a[i - 1] = a[i];
}
n--;
}
//查找一个元素
//按值查找
// 查找这个数第⼀次出现的位置,找不到返回 0
int find(int x)
{
for(int i = 1; i <= n; i++)
{
if(a[i] == x) return i;
}
return 0;
}
//按位查找
// 返回 p 位置的数
int at(int p)
{
return a[p];
}
//修改元素
// 把 p 位置的数修改成 x
void change(int p, int x)
{
a[p] = x;
}
// 清空顺序表
void clear()
{
n = 0;
}
当然,上述代码是有问题的,比如增加元素是数组可能会溢出,删除元素是数组可能是空,查找元素时p要合法,清空顺序表时如果里面的元素是动态申请的要释放……
这种由静态数组来模拟实现的数据结构一般都是用在竞赛中,所以都是输入保证不会出现上述问题。
动态顺序表
头文件 SqList.h
#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
typedef int SLDataType;
typedef struct SqList
{
SLDataType* arr;
int size;//当前数组元素个数
int capacity;//数组的长度
}SL;
// 对数据的管理:增删查改
// 初始化顺序表
void SqListInit(SL* ps);
//销毁顺序表
void SqListDestroy(SL* ps);
//打印
void SqListPrint(SL s);
//检查空间是否足够,不够就扩容
void SqListCheck(SL* ps);
//尾插x
void SqListPushBack(SL* ps, SLDataType x);
//头插x
void SqListPushFront(SL* ps, SLDataType x);
//尾部删除
void SqListPopBack(SL* ps);
//头部删除
void SqListPopFront(SL* ps);
//查找元素
int SqListFind(SL s, SLDataType x);
//在下标为pos位置插入x
void SqListInsert(SL* ps, int pos, SLDataType x);
//删除下标为pos位置的元素
void SqListErase(SL* ps, int pos);
源文件 SqList.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"SqList.h"
//初始化
void SqListInit(SL* s)
{
s->arr = NULL;
s->size = s->capacity = 0;
}
//打印
void SqListPrint(SL s)
{
int i = 0;
for (i = 0; i < s.size; i++)
{
printf("%d ", s.arr[i]);
}
printf("\n");
}
//检查空间是否足够,不够就扩容
void SqListCheck(SL* ps)
{
if (ps->size == ps->capacity)//顺序表满了
{
//realloc的大小,单位是字节!!!
//如果原来就为空,那就开1个元素,如果原来不为空,就开为2倍
int newcapacity = (ps->capacity == 0) ? 4 : 2 * (ps->capacity);
SLDataType* tmp = (SLDataType*)realloc(ps->arr, newcapacity*sizeof(SLDataType));//为数组申请空间!!不是结构体
if (tmp == NULL)//开辟失败
{
perror("realloc");
exit(1);
}
//开辟成功
ps->arr = tmp; //扩容后的数组
ps->capacity = newcapacity;//新长度
}
}
//尾插
void SqListPushBack(SL* ps, SLDataType x)
{
SqListCheck(ps);
ps->arr[ps->size++] = x;
}
//头插
void SqListPushFront(SL* ps, SLDataType x)
{
//断言,防止传空指针
assert(ps);
SqListCheck(ps);
//把整个表向后移动一个位置
for (int i = ps->size;i > 0; i--)
{
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[0] = x;
ps->size++;//元素加1
}
//尾部删除
void SqListPopBack(SL* ps)
{
//防止顺序表为空
assert(ps && ps->size);
ps->size--;
}
//头部删除
void SqListPopFront(SL* ps)
{
assert(ps && ps->size);
for (int i = 0; i < ps->size - 1; i++)
{
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
//查找元素
int SqListFind(SL s, SLDataType x)
{
for (int i = 0; i < s.size; i++)
{
if (s.arr[i] == x)
return i;
}
return -1;//没找到就返回-1
}
//在下标为pos位置插入x
void SqListInsert(SL* ps, int pos, SLDataType x)
{
SqListCheck(ps);
assert(pos >= 0 && pos <= ps->size);//取等时是头插或尾插
for (int i = ps->size; i > pos; i--)
{
ps->arr[i] = ps->arr[i - 1];
}
ps->arr[pos] = x;
ps->size++;
}
//删除下标为pos位置的元素
void SqListErase(SL* ps, int pos)
{
assert(pos >= 0 && pos <= ps->size - 1);//取等时是头删和尾删
for (int i = pos; i < ps->size - 1; i++)
{
ps->arr[i] = ps->arr[i + 1];
}
ps->size--;
}
//销毁顺序表
void SqListDestroy(SL* ps)
{
free(ps->arr);
ps->arr = NULL;
ps->size = 0;
ps->capacity = 0;
}