片头
嗨! 小伙伴们,大家好! 哈哈,今天我们来一起学习顺序表,本篇超级详细,一定可以教会你!
一、线性表
1.1是线性表呢?
线性表(linear list)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构。常见的线性表:顺序表、链表、栈、队列、字符串......
线性表在逻辑上是线性结构,就像一串珠子穿在一根绳上。但是线性表在物理结构上不一定是连续的,线性表以数组的形式存储时和以链式结构存储时在物理内存上的布局是不一样的。
线性表以数组的形式存储时在内存中是连续的,而线性表以链式结构存储时在内存中不一定连续。
二、顺序表
2.1 顺序表的定义
线性表的顺序存储又称为顺序表,顺序表是用一段地址连续的存储单元来依次存储数据元素的线性结构,从而使得逻辑上相邻的两个元素在物理位置上也相邻,也就是说我们可以通过下标来依次访问结构中的内容。平时我们使用的数组也是顺序表的一种实现方式。
2.2 顺序表的种类
顺序表一般可以分为:(1)静态顺序表:使用定长数组存储元素
我们先来试一下创建一个静态顺序表
#define N 10
typedef int ElemType;
typedef struct SeqList {
ElemType arr[N]; //定长数组
int size; //有效数据个数
}SL;
我们可以看到,静态顺序表中定义了一个定长数组,也就是说数组一旦开辟就无法再更改大小了。
所以静态顺序表只适用于已知需要存储多少数据的场景,如果定长数组过大,就会浪费空间,如果过小,又不够用。所以一般情况下,我们都使用动态顺序表,可以根据需要来动态分配空间,接下来我们认识一下动态顺序表。
(2)动态顺序表:使用动态开辟的数组存储
typedef int ElemType;
typedef struct SeqList {
ElemType* arr; //指向动态数组开辟的空间
int capacity; //开辟空间的容量大小
int size; //有效数据个数
}SL;
动态顺序表中存储数据的空间需要我们进行动态内存开辟,以上便是动态顺序表的结构。
2.3 顺序表的增删改查接口实现
接下来我们一步一步来实现顺序表的增删改查接口,当然此处使用的是动态顺序表。
本次演示的是vs2019,我们先创建一个新项目,并新建头文件"SeqList.h"和两个源文件"SeqList.c" 和"test.c",它们的作用分别是:
SeqList.h | 顺序表的定义,头文件的引用和接口函数的声明 |
SeqList.c | 具体实现顺序表里定义的接口/方法 |
test.c | 测试各个函数 |
首先我们展示"SeqList.h"的完整代码,不要忘了在两个源文件中引用"SeqList.h"
#pragma once//防止头文件被二次引用
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
//静态顺序表
//#define N 10
//typedef struct SeqList {
// ElemType arr[N]; //定长数组
// int size; //有效数据个数
//}SL;
//动态顺序表
typedef int ElemType; //如果要修改存储的数据类型可直接在此修改
typedef struct SeqList {
ElemType* arr; //指向动态数组开辟的空间
int capacity; //开辟空间的容量大小
int size; //有效数据个数
}SL;
//顺序表的增删改查接口
//顺序表的初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestroy(SL* ps);
//顺序表的打印
void SLPrint(SL* ps);
//检查顺序表的容量,如果满了,进行扩容
void SLCheckCapacity(SL* ps);
//顺序表的尾插
void SLPushBack(SL* ps, ElemType x);
//顺序表的头插
void SLPushFront(SL* ps, ElemType x);
//顺序表的尾删
void SLPopBack(SL* ps);
//顺序表的头删
void SLPopFront(SL* ps);
//顺序表指定位置插入数据
void SLInsert(SL* ps, int pos, ElemType x);
//顺序表删除指定位置的数据