1. 顺序表的定义与结构
顺序表是用一段地址连续的存储单元依次存储数据元素的线性结构,逻辑上相邻的元素在物理位置上也相邻。顺序表结构如下:
cpp
typedef struct {
ElemType *elem; // 指向存储空间的基地址(动态数组)
int length; // 顺序表当前长度(实际元素个数)
} SqList;
#define MAXSIZE 100 // 顺序表最大容量(最多存储100个元素)
elem
:动态分配的数组,用于存储元素(物理上连续)。length
:记录当前元素个数,初始为 0,最大不超过MAXSIZE
。
2. 初始化算法(InitList)
功能:为顺序表分配存储空间,初始化表长为 0。
实现代码:
cpp
Status InitList(SqList &L) {
L.elem = new ElemType[MAXSIZE]; // 动态分配大小为MAXSIZE的数组
if (!L.elem) exit(OVERFLOW); // 内存分配失败则退出程序
L.length = 0; // 初始长度为0(空表)
return OK;
}
关键细节:
- 用
new
动态分配数组空间,避免静态数组的固定大小限制。 - 若内存分配失败(
L.elem
为NULL
),通过exit(OVERFLOW)
终止程序,防止后续错误。 - 初始化后,顺序表为 "空表"(
length=0
),但已占用MAXSIZE*sizeof(ElemType)
的存储空间。
3. 取值算法(GetElem)
功能 :获取顺序表中第i
个位置(位序)的元素值。
实现代码:
cpp
Status GetElem(SqList L, int i, ElemType &e) {
if (i < 1 || i > L.length) return ERROR; // 位置i不合法
e = L.elem[i - 1]; // 第i个元素对应数组下标i-1
return OK;
}
关键细节:
- 顺序表的 "位序" 从 1 开始(符合人类习惯),而数组下标从 0 开始,因此第
i
个元素在数组中的位置是i-1
。 - 合法性检查:
i
必须满足1 ≤ i ≤ length
(超出范围则返回ERROR
)。 - 时间复杂度:
O(1)
(直接通过下标访问,无需遍历)。
4. 查找算法(LocateElem)
功能 :根据元素值e
查找其在顺序表中的位序(若存在,返回位序;否则返回 0)。
实现代码:
cpp
int LocateElem(SqList L, ElemType e) {
for (int i = 0; i < L.length; i++) {
if (L.elem[i] == e) return i + 1; // 找到元素,返回位序(下标+1)
}
return 0; // 未找到元素
}
关键细节:
- 采用顺序查找 (遍历数组),逐个比较元素值是否等于
e
。 - 找到时返回位序(
i+1
,因为i
是数组下标),未找到返回 0。 - 时间复杂度:
O(n)
(n
为表长,最坏情况需遍历所有元素)。
5. 插入算法(ListInsert)
功能 :在顺序表的第i
个位置(位序)插入新元素e
。
实现代码:
cpp
Status ListInsert(SqList &L, int i, ElemType e) {
if (i < 1 || i > L.length + 1) return ERROR; // 插入位置不合法
if (L.length == MAXSIZE) return ERROR; // 表已满,无法插入
// 从后往前移动元素,为新元素腾出位置
for (int j = L.length - 1; j >= i - 1; j--) {
L.elem[j + 1] = L.elem[j];
}
L.elem[i - 1] = e; // 插入新元素
L.length++; // 表长加1
return OK;
}
关键细节:
- 插入位置合法性 :
i
必须满足1 ≤ i ≤ length+1
(可以插入到表首、表中或表尾)。 - 表满检查 :若
length == MAXSIZE
,无法插入(顺序表容量固定)。 - 元素后移 :从最后一个元素(下标
length-1
)开始,到第i-1
个元素,依次后移一位(j+1
),防止元素被覆盖。 - 时间复杂度:
O(n)
(最坏情况插入到表首,需移动n
个元素)。
6. 删除算法(ListDelete)
功能 :删除顺序表中第i
个位置(位序)的元素。
实现代码:
cpp
Status ListDelete(SqList &L, int i) {
if (i < 1 || i > L.length) return ERROR; // 删除位置不合法
// 从被删除元素的下一个位置开始,依次前移覆盖
for (int j = i; j <= L.length - 1; j++) {
L.elem[j - 1] = L.elem[j];
}
L.length--; // 表长减1
return OK;
}
关键细节:
- 删除位置合法性 :
i
必须满足1 ≤ i ≤ length
(只能删除已存在的元素)。 - 元素前移 :从被删除元素的下一个位置(下标
i
)开始,到最后一个元素(下标length-1
),依次前移一位(j-1
),覆盖被删除的元素。 - 时间复杂度:
O(n)
(最坏情况删除表首元素,需移动n-1
个元素)。
7. 打印算法(PrintList)
功能:遍历并输出顺序表中所有元素。
实现代码:
cpp
void PrintList(SqList L) {
cout << "当前顺序表元素:";
for (int i = 0; i < L.length; i++) {
cout << L.elem[i] << " ";
}
cout << endl;
}
关键细节:
- 遍历数组从下标
0
到length-1
(仅输出已存储的元素,不包括未使用的空间)。 - 时间复杂度:
O(n)
(需遍历所有元素)。
完整C++代码如下:
cpp
#include<iostream>
using namespace std;
#define MAXSIZE 100 // 顺序表最大长度
typedef int ElemType;
typedef int Status;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
typedef struct {
ElemType *elem; // 存储空间基地址
int length; // 顺序表当前长度
} SqList;
// 函数声明
Status InitList(SqList &L); // 初始化顺序表
Status GetElem(SqList L, int i, ElemType &e); // 取值
int LocateElem(SqList L, ElemType e); // 查找
Status ListInsert(SqList &L, int i, ElemType e); // 插入
Status ListDelete(SqList &L, int i); // 删除
void PrintList(SqList L); // 打印顺序表
int main() {
SqList L;
int i, e, n, result;
// ===================== 1. 测试初始化 =====================
cout << "============ 测试初始化操作 ============" << endl;
if (InitList(L) == OK) {
cout << "顺序表初始化成功!" << endl;
} else {
cout << "顺序表初始化失败!" << endl;
return 1;
}
PrintList(L);
// ===================== 2. 测试插入操作 =====================
cout << "\n============ 测试插入操作 ============" << endl;
cout << "请输入要插入的元素个数:";
cin >> n;
cout << "请依次输入" << n << "个元素(将插入到顺序表的1~" << n << "位置):" << endl;
for (int k = 1; k <= n; k++) {
cin >> e;
if (ListInsert(L, k, e) == OK) {
cout << "插入元素 " << e << " 到位置 " << k << " 成功!" << endl;
} else {
cout << "插入元素 " << e << " 到位置 " << k << " 失败!" << endl;
}
}
PrintList(L);
// ===================== 3. 测试取值操作 =====================
cout << "\n============ 测试取值操作 ============" << endl;
cout << "请输入要取值的位置i(1~" << L.length << "):";
cin >> i;
if (GetElem(L, i, e) == OK) {
cout << "位置 " << i << " 的元素是:" << e << endl;
} else {
cout << "取值位置 " << i << " 不合法!" << endl;
}
// ===================== 4. 测试查找操作 =====================
cout << "\n============ 测试查找操作 ============" << endl;
cout << "请输入要查找的元素e:";
cin >> e;
result = LocateElem(L, e);
if (result != 0) {
cout << "元素 " << e << " 的位序是:" << result << endl;
} else {
cout << "未找到元素 " << e << "!" << endl;
}
// ===================== 5. 测试删除操作 =====================
cout << "\n============ 测试删除操作 ============" << endl;
cout << "请输入要删除的位置i(1~" << L.length << "):";
cin >> i;
if (ListDelete(L, i) == OK) {
cout << "删除位置 " << i << " 的元素成功!" << endl;
PrintList(L);
} else {
cout << "删除位置 " << i << " 不合法!" << endl;
}
// 释放动态分配的内存(防止内存泄漏)
delete[] L.elem;
return 0;
}
// 初始化顺序表
Status InitList(SqList &L) {
L.elem = new ElemType[MAXSIZE]; // 动态分配数组空间
if (!L.elem) exit(OVERFLOW); // 内存分配失败则退出
L.length = 0; // 空表长度初始化为0
return OK;
}
// 取值:获取第i个位置的元素
Status GetElem(SqList L, int i, ElemType &e) {
if (i < 1 || i > L.length) return ERROR; // 位置i不合法
e = L.elem[i - 1]; // 数组下标从0开始,第i个元素对应elem[i-1]
return OK;
}
// 查找:返回元素e的位序(从1开始),未找到返回0
int LocateElem(SqList L, ElemType e) {
for (int i = 0; i < L.length; i++) {
if (L.elem[i] == e) return i + 1; // 找到元素,返回位序
}
return 0; // 查找失败
}
// 插入:在第i个位置插入元素e
Status ListInsert(SqList &L, int i, ElemType e) {
if (i < 1 || i > L.length + 1) return ERROR; // 插入位置不合法
if (L.length == MAXSIZE) return ERROR; // 顺序表已满
// 插入位置及之后的元素后移
for (int j = L.length - 1; j >= i - 1; j--) {
L.elem[j + 1] = L.elem[j];
}
L.elem[i - 1] = e; // 放入新元素
L.length++; // 表长加1
return OK;
}
// 删除:删除第i个位置的元素
Status ListDelete(SqList &L, int i) {
if (i < 1 || i > L.length) return ERROR; // 删除位置不合法
// 被删除元素之后的元素前移
for (int j = i; j <= L.length - 1; j++) {
L.elem[j - 1] = L.elem[j];
}
L.length--; // 表长减1
return OK;
}
// 打印顺序表所有元素
void PrintList(SqList L) {
cout << "当前顺序表元素:";
for (int i = 0; i < L.length; i++) {
cout << L.elem[i] << " ";
}
cout << endl;
}
程序运行结果如下:

完整Python代码如下:
python
# 定义常量(对应原C++的宏定义)
MAXSIZE = 100 # 顺序表最大容量
OK = 1
ERROR = 0
OVERFLOW = -2 # Python中列表初始化极少出现内存溢出,仅保留常量兼容逻辑
class SqList:
"""顺序表类:模拟原C++的结构体+函数集合"""
def __init__(self):
"""初始化顺序表(对应原InitList函数)"""
# 用列表模拟固定容量的数组,初始填充None(模拟空存储空间)
self.elem = [None] * MAXSIZE
self.length = 0 # 初始表长为0(空表)
def GetElem(self, i):
"""取值操作:获取第i个位置(位序,1开始)的元素"""
# 检查位置合法性:i必须在[1, 当前表长]范围内
if i < 1 or i > self.length:
return ERROR, None # 失败:返回错误状态+空值
# 数组下标从0开始,第i个元素对应下标i-1
return OK, self.elem[i - 1]
def LocateElem(self, e):
"""查找操作:返回元素e的位序(1开始),未找到返回0"""
# 遍历当前已存储的元素(仅前length个)
for idx in range(self.length):
if self.elem[idx] == e:
return idx + 1 # 找到:返回位序(下标+1)
return 0 # 未找到
def ListInsert(self, i, e):
"""插入操作:在第i个位置(位序)插入元素e"""
# 1. 检查插入位置合法性:i必须在[1, 当前表长+1](可插在表首/表中/表尾)
if i < 1 or i > self.length + 1:
return ERROR
# 2. 检查顺序表是否已满
if self.length == MAXSIZE:
return ERROR
# 3. 元素后移:从最后一个元素到第i个元素,依次往后挪1位
# (原C++的j从length-1到i-1,Python反向遍历实现相同逻辑)
for j in range(self.length - 1, i - 2, -1):
self.elem[j + 1] = self.elem[j]
# 4. 插入新元素到第i个位置(对应下标i-1)
self.elem[i - 1] = e
# 5. 表长加1
self.length += 1
return OK
def ListDelete(self, i):
"""删除操作:删除第i个位置(位序)的元素"""
# 1. 检查删除位置合法性:i必须在[1, 当前表长](只能删已存在的元素)
if i < 1 or i > self.length:
return ERROR
# 2. 元素前移:从第i+1个元素到最后一个元素,依次往前挪1位
for j in range(i, self.length):
self.elem[j - 1] = self.elem[j]
# 3. 表长减1(无需手动清空最后一个元素,后续插入会覆盖)
self.length -= 1
return OK
def PrintList(self):
"""打印顺序表:输出当前所有元素(对应原PrintList函数)"""
# 仅打印前length个已存储的元素
print("当前顺序表元素:", end="")
for idx in range(self.length):
print(self.elem[idx], end=" ")
print() # 换行
# -------------------------- 主程序:测试所有功能(对应原main函数) --------------------------
if __name__ == "__main__":
# 1. 测试初始化
print("============ 测试初始化操作 ============")
L = SqList() # 初始化顺序表(Python类实例化即完成初始化)
print("顺序表初始化成功!")
L.PrintList() # 打印空表
# 2. 测试插入操作
print("\n============ 测试插入操作 ============")
# 输入插入元素个数
n = int(input("请输入要插入的元素个数:"))
print(f"请依次输入{n}个元素(将插入到顺序表的1~{n}位置):")
# 循环输入并插入元素
for k in range(1, n + 1):
e = int(input(f"请输入第{k}个元素:"))
if L.ListInsert(k, e) == OK:
print(f"插入元素 {e} 到位置 {k} 成功!")
else:
print(f"插入元素 {e} 到位置 {k} 失败!")
L.PrintList() # 打印插入后的表
# 3. 测试取值操作
print("\n============ 测试取值操作 ============")
i = int(input(f"请输入要取值的位置i(1~{L.length}):"))
status, e = L.GetElem(i)
if status == OK:
print(f"位置 {i} 的元素是:{e}")
else:
print(f"取值位置 {i} 不合法!")
# 4. 测试查找操作
print("\n============ 测试查找操作 ============")
e = int(input("请输入要查找的元素e:"))
result = L.LocateElem(e)
if result != 0:
print(f"元素 {e} 的位序是:{result}")
else:
print(f"未找到元素 {e}!")
# 5. 测试删除操作
print("\n============ 测试删除操作 ============")
i = int(input(f"请输入要删除的位置i(1~{L.length}):"))
if L.ListDelete(i) == OK:
print(f"删除位置 {i} 的元素成功!")
L.PrintList() # 打印删除后的表
else:
print(f"删除位置 {i} 不合法!")
# Python无需手动释放内存(垃圾回收机制自动处理)
程序运行结果如下:
python
============ 测试初始化操作 ============
顺序表初始化成功!
当前顺序表元素:
============ 测试插入操作 ============
请输入要插入的元素个数:6
请依次输入6个元素(将插入到顺序表的1~6位置):
请输入第1个元素:23
插入元素 23 到位置 1 成功!
请输入第2个元素:12
插入元素 12 到位置 2 成功!
请输入第3个元素:67
插入元素 67 到位置 3 成功!
请输入第4个元素:10
插入元素 10 到位置 4 成功!
请输入第5个元素:76
插入元素 76 到位置 5 成功!
请输入第6个元素:90
插入元素 90 到位置 6 成功!
当前顺序表元素:23 12 67 10 76 90
============ 测试取值操作 ============
请输入要取值的位置i(1~6):4
位置 4 的元素是:10
============ 测试查找操作 ============
请输入要查找的元素e:67
元素 67 的位序是:3
============ 测试删除操作 ============
请输入要删除的位置i(1~6):5
删除位置 5 的元素成功!
当前顺序表元素:23 12 67 10 90
完整Java代码如下:
java
import java.util.Scanner;
// 顺序表类:封装顺序表的结构和操作
class SqList {
// 常量定义(对应原C++的宏)
public static final int MAXSIZE = 100; // 顺序表最大容量
public static final int OK = 1; // 操作成功状态
public static final int ERROR = 0; // 操作失败状态
public static final int OVERFLOW = -2; // 内存溢出状态(Java中仅作兼容)
private int[] elem; // 存储元素的数组(对应原C++的ElemType* elem)
private int length; // 顺序表当前长度(对应原C++的length)
// 构造函数:初始化顺序表(对应原C++的InitList函数)
public SqList() {
try {
this.elem = new int[MAXSIZE]; // 初始化数组(模拟动态分配)
this.length = 0; // 初始表长为0(空表)
} catch (OutOfMemoryError e) {
// 模拟内存分配失败(对应原C++的exit(OVERFLOW))
throw new IllegalStateException("顺序表初始化失败:内存溢出", e);
}
}
/**
* 取值操作:获取第i个位置(位序,1开始)的元素
* @param i 目标位置(位序)
* @return 结果数组:index0=状态(OK/ERROR),index1=元素值(仅状态为OK时有效)
*/
public int[] getElem(int i) {
int[] result = new int[2]; // 用数组封装状态和返回值(替代C++的引用传参)
// 检查位置合法性:i必须在[1, 当前表长]范围内
if (i < 1 || i > this.length) {
result[0] = ERROR;
return result;
}
// 数组下标从0开始,第i个元素对应下标i-1
result[0] = OK;
result[1] = this.elem[i - 1];
return result;
}
/**
* 查找操作:返回元素e的位序(1开始),未找到返回0
* @param e 目标元素
* @return 位序(找到)或0(未找到)
*/
public int locateElem(int e) {
// 遍历当前已存储的元素(仅前length个)
for (int idx = 0; idx < this.length; idx++) {
if (this.elem[idx] == e) {
return idx + 1; // 位序=下标+1
}
}
return 0; // 未找到
}
/**
* 插入操作:在第i个位置(位序)插入元素e
* @param i 插入位置(位序)
* @param e 待插入元素
* @return 状态(OK/ERROR)
*/
public int listInsert(int i, int e) {
// 1. 检查插入位置合法性:i必须在[1, 表长+1](可插在表首/表中/表尾)
if (i < 1 || i > this.length + 1) {
return ERROR;
}
// 2. 检查顺序表是否已满
if (this.length == MAXSIZE) {
return ERROR;
}
// 3. 元素后移:从最后一个元素到第i个元素,依次后挪1位(反向遍历)
for (int j = this.length - 1; j >= i - 1; j--) {
this.elem[j + 1] = this.elem[j];
}
// 4. 插入新元素到目标位置
this.elem[i - 1] = e;
// 5. 表长加1
this.length++;
return OK;
}
/**
* 删除操作:删除第i个位置(位序)的元素
* @param i 删除位置(位序)
* @return 状态(OK/ERROR)
*/
public int listDelete(int i) {
// 1. 检查删除位置合法性:i必须在[1, 表长](只能删已存在的元素)
if (i < 1 || i > this.length) {
return ERROR;
}
// 2. 元素前移:从第i+1个元素到最后一个元素,依次前挪1位(正向遍历)
for (int j = i; j < this.length; j++) {
this.elem[j - 1] = this.elem[j];
}
// 3. 表长减1(无需清空最后一个元素,后续插入会覆盖)
this.length--;
return OK;
}
/**
* 打印操作:输出当前顺序表的所有元素
*/
public void printList() {
System.out.print("当前顺序表元素:");
for (int idx = 0; idx < this.length; idx++) {
System.out.print(this.elem[idx] + " ");
}
System.out.println();
}
// 获取当前表长(供测试时判断合法位置)
public int getLength() {
return this.length;
}
}
// 测试主类(对应原C++的main函数)
public class SqListTest {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
SqList L = new SqList(); // 初始化顺序表(调用构造函数)
int i, e, n, result;
// 1. 测试初始化(构造函数已完成,仅验证并打印)
System.out.println("============ 测试初始化操作 ============");
System.out.println("顺序表初始化成功!");
L.printList();
// 2. 测试插入操作
System.out.println("\n============ 测试插入操作 ============");
System.out.print("请输入要插入的元素个数:");
n = scanner.nextInt();
System.out.println("请依次输入" + n + "个元素(将插入到顺序表的1~" + n + "位置):");
for (int k = 1; k <= n; k++) {
e = scanner.nextInt();
if (L.listInsert(k, e) == SqList.OK) {
System.out.println("插入元素 " + e + " 到位置 " + k + " 成功!");
} else {
System.out.println("插入元素 " + e + " 到位置 " + k + " 失败!");
}
}
L.printList();
// 3. 测试取值操作
System.out.println("\n============ 测试取值操作 ============");
System.out.print("请输入要取值的位置i(1~" + L.getLength() + "):");
i = scanner.nextInt();
int[] getResult = L.getElem(i);
if (getResult[0] == SqList.OK) {
System.out.println("位置 " + i + " 的元素是:" + getResult[1]);
} else {
System.out.println("取值位置 " + i + " 不合法!");
}
// 4. 测试查找操作
System.out.println("\n============ 测试查找操作 ============");
System.out.print("请输入要查找的元素e:");
e = scanner.nextInt();
result = L.locateElem(e);
if (result != 0) {
System.out.println("元素 " + e + " 的位序是:" + result);
} else {
System.out.println("未找到元素 " + e + "!");
}
// 5. 测试删除操作
System.out.println("\n============ 测试删除操作 ============");
System.out.print("请输入要删除的位置i(1~" + L.getLength() + "):");
i = scanner.nextInt();
if (L.listDelete(i) == SqList.OK) {
System.out.println("删除位置 " + i + " 的元素成功!");
L.printList();
} else {
System.out.println("删除位置 " + i + " 不合法!");
}
scanner.close(); // 关闭输入流
}
}
程序运行结果如下:
java
============ 测试初始化操作 ============
顺序表初始化成功!
当前顺序表元素:
============ 测试插入操作 ============
请输入要插入的元素个数:6
请依次输入6个元素(将插入到顺序表的1~6位置):
23
插入元素 23 到位置 1 成功!
12
插入元素 12 到位置 2 成功!
67
插入元素 67 到位置 3 成功!
10
插入元素 10 到位置 4 成功!
76
插入元素 76 到位置 5 成功!
90
插入元素 90 到位置 6 成功!
当前顺序表元素:23 12 67 10 76 90
============ 测试取值操作 ============
请输入要取值的位置i(1~6):4
位置 4 的元素是:10
============ 测试查找操作 ============
请输入要查找的元素e:67
元素 67 的位序是:3
============ 测试删除操作 ============
请输入要删除的位置i(1~6):5
删除位置 5 的元素成功!
当前顺序表元素:23 12 67 10 90
总结:顺序表的核心特性
-
优点:
- 支持随机访问(通过下标直接访问元素,时间复杂度
O(1)
)。 - 存储密度高(无需额外存储指针,仅需存储元素本身)。
- 支持随机访问(通过下标直接访问元素,时间复杂度
-
缺点:
- 容量固定(受
MAXSIZE
限制,动态扩容成本高)。 - 插入 / 删除操作需移动大量元素(时间复杂度
O(n)
)。
- 容量固定(受
-
适用场景:适用于元素个数固定、频繁查询、较少插入 / 删除的场景。