顺序表(Sequential List)_顺序表的基本操作
一、概述
在学习数据结构时,顺序表(Sequential List) 是我们接触到的第一个线性结构。
它是线性表的一种顺序存储形式——即:所有元素依次存放在一段连续的内存空间中。
通俗点说:
顺序表就像一排座位,座位一个挨着一个。
每个座位只能坐一个人(存放一个数据),
想插队(插入)或离开(删除)时,后面的人都得动一动!
二、顺序表的定义与特点
1.定义
顺序表是一种用数组实现的线性表。
它通过元素的下标(索引) 来快速访问任意位置的数据。
在C语言中可以用结构体来表示:
#define MAXSIZE 100
typedef struct {
int data[MAXSIZE]; // 存放元素的数组
int length; // 当前表的长度(有效元素个数)
} SqList;
2.特点
特质 | 阐释 |
存储模式 | 采用连续的内存空间进行存储 |
访问速率 | 访问速度极快,时间复杂度为 O(1) |
插入与删除操作 | 操作速度迟缓,需对元素进行移动 |
内存利用效率 | 容量固定,可能出现空间浪费或不足的情况 |
三、顺序表的基本操作
1.初始化顺序表
void InitList(SqList *L) {
L->length = 0;
}
初始化后,表为空,但数组空间已准备好。
2. 插入元素
int ListInsert(SqList *L, int i, int e) {
if (i < 1 || i > L->length + 1) return 0; // 位置非法
if (L->length >= MAXSIZE) return 0; // 空间已满
for (int j = L->length; j >= i; j--) {
L->data[j] = L->data[j - 1]; // 元素后移
}
L->data[i - 1] = e;
L->length++;
return 1;
}
例子:在 [10, 20, 30, 40] 的第3个位置插入 99
执行后变为 [10, 20, 99, 30, 40]
3.删除元素
int ListDelete(SqList *L, int i, int *e) {
if (i < 1 || i > L->length) return 0; // 位置非法
*e = L->data[i - 1]; // 保存删除的元素
for (int j = i; j < L->length; j++) {
L->data[j - 1] = L->data[j]; // 元素前移
}
L->length--;
return 1;
}
例子:删除 [10, 20, 99, 30, 40] 中第3个元素
输出 删除元素 = 99
结果 [10, 20, 30, 40]
4.查找元素
int LocateElem(SqList L, int e) {
for (int i = 0; i < L.length; i++) {
if (L.data[i] == e)
return i + 1; // 返回逻辑位置
}
return 0;
}
查找 30 → 返回位置 3
5.遍历顺序表
void PrintList(SqList L) {
for (int i = 0; i < L.length; i++) {
printf("%d ", L.data[i]);
}
printf("\n");
}
四、综合示例:学生成绩表
假设我们要管理一个班级的成绩,数据如下:
学号 | 分数 |
101 | 85 |
102 | 90 |
103 | 78 |
我们要实现:
- 初始化成绩表
- 插入新学生成绩
- 删除一名学生
- 查找特定学号
- 打印全部成绩
完整代码示例:
#include <stdio.h>
#define MAXSIZE 100
typedef struct {
int data[MAXSIZE];
int length;
} SqList;
void InitList(SqList *L) {
L->length = 0;
}
int ListInsert(SqList *L, int i, int e) {
if (i < 1 || i > L->length + 1) return 0;
if (L->length >= MAXSIZE) return 0;
for (int j = L->length; j >= i; j--)
L->data[j] = L->data[j - 1];
L->data[i - 1] = e;
L->length++;
return 1;
}
int ListDelete(SqList *L, int i, int *e) {
if (i < 1 || i > L->length) return 0;
*e = L->data[i - 1];
for (int j = i; j < L->length; j++)
L->data[j - 1] = L->data[j];
L->length--;
return 1;
}
int LocateElem(SqList L, int e) {
for (int i = 0; i < L.length; i++)
if (L.data[i] == e) return i + 1;
return 0;
}
void PrintList(SqList L) {
for (int i = 0; i < L.length; i++)
printf("%d ", L.data[i]);
printf("\n");
}
int main() {
SqList scoreList;
InitList(&scoreList);
// 初始化数据
ListInsert(&scoreList, 1, 85);
ListInsert(&scoreList, 2, 90);
ListInsert(&scoreList, 3, 78);
printf("初始成绩表:");
PrintList(scoreList);
// 插入新成绩
ListInsert(&scoreList, 2, 95);
printf("插入新成绩后:");
PrintList(scoreList);
// 删除成绩
int deleted;
ListDelete(&scoreList, 3, &deleted);
printf("删除第3个成绩(%d)后:", deleted);
PrintList(scoreList);
// 查找成绩
int pos = LocateElem(scoreList, 90);
if (pos)
printf("成绩90在第%d个位置\n", pos);
else
printf("未找到成绩90\n");
return 0;
}
运行结果示例:
初始成绩表:85 90 78
插入新成绩后:85 95 90 78
删除第3个成绩(90)后:85 95 78
成绩90在第0个位置
五、时间与空间复杂度分析
操作 | 时间复杂度 | 说明 |
按位访问 | O(1) | 可直接通过下标访问 |
查找 | O(n) | 需遍历 |
插入 | O(n) | 平均需移动一半元素 |
删除 | O(n) | 平均需移动一半元素 |
六、应用场景
顺序表常用于:
- 存储固定数量的数据(如成绩表、学生名单)
- 频繁访问、较少插入/删除的场景
- 简单结构、性能要求不高的系统
七、总结
优点 | 缺点 |
支持随机访问,查找快 | 插入删除慢 |
存储结构简单 | 容量固定,不可动态扩展 |
内存连续,易于管理 | 内存浪费或越界风险 |
八、附:封装好的C++数据结构代码
//#include <iostream.h>
//using namespace std;
#ifndef List2
#define List2
template<class ElemType>
class List{
public:
virtual int GetLen()=0;/*求线性表长度*/
virtual ElemType &GetElem(int i)=0;/*取第i个元素,i=1~n*/
ElemType &operator[](int i){return GetElem(i);}//下标重载
virtual int Locate(ElemType x)=0;
virtual int InsElem(int i,ElemType x)=0;
virtual int DelElem(int i)=0;
virtual void DispList(char c=',',char c2='\n')=0;
};
#endif
#ifndef sq_List2
#define sq_List2
template<typename ElemType>
class sqList:public List<ElemType>{
ElemType *data,X; //定义存储表中元素的数组
int Length,MaxLen; //线性表的实际长度
public://构造函数初始化顺序表
sqList(int n=100):MaxLen(n),Length(0),X(0){data=new ElemType[n];}
int GetLen(){return Length;}//求线性表长度
ElemType &GetElem(int i)//取第i个元素值,i=1~n
{if(i<1||i>Length)return X;//返回随机数
return data[i-1];}
//ElemType &operator[](int i){return GetElem(i);}//下标重载
int Locate(ElemType x)//查找值为x元素的位置,没找到返回a0
{int i;
for(i=0;i<Length;i++)if(!(data[i]!=x))return i+1;
return 0;}
int InsElem(int i,ElemType x)//第i位置插入结点x,i=1~n
{int j;
if(Length==MaxLen)return 0;//表已满
if(i<1||i>Length+1)return 0;//插入位置出错
for(j=Length;j>=i;j--)data[j]=data[j-1];//数据元素后移
data[i-1]=x;Length++; //插入x,表长度加1
return 1;}
int DelElem(int i)//删除线性表中第i个位置上的元素
{int j;
if(i<1||i>Length)return 0;//检查空表及删除位置的合法性
for(j=i;j<=Length-1;j++)data[j-1]=data[j];//向前移动元素
Length--;return 1;}
void DispList(char c=',',char c2='\n')//输出线性表中每个元素值
{int i;
if(Length==0){cout<<"空表";if(c2)if(c2=='\n')cout<<endl;else cout<<c2;return;}
for(i=0;i<Length;i++){cout<<data[i];if(c)cout<<c;}
if(c2)if(c2=='\n')cout<<endl;else cout<<c2;
}
};
#endif
相关文章
- Spring Boot中对接Twilio以实现发送验证码和验证短信码
- Spring Boot 3.5:这次更新让你连配置都不用写了,惊不惊喜?
- Spring Boot+Pinot实战:毫秒级实时竞价系统构建
- SpringBoot敏感配置项加密与解密实战
- SpringBoot 注解最全详解,建议收藏!
- Spring Boot 常用注解大全:从入门到进阶
- SpringBoot启动之谜:@SpringBootApplication如何让配置化繁为简
- Springboot集成Kafka原理_spring集成kafka的原理
- Spring Boot中@Data注解的深度解析与实战应用
- 大佬用1000字就把SpringBoot的配置文件讲的明明白白!