目录
[1 简介](#1 简介)
[2 线性表的基本概念](#2 线性表的基本概念)
[3 顺序存储的线性表](#3 顺序存储的线性表)
[3.1 定义线性表结构](#3.1 定义线性表结构)
[3.2 初始化线性表](#3.2 初始化线性表)
[3.3 插入元素](#3.3 插入元素)
[3.4 删除元素](#3.4 删除元素)
[3.5 查找元素](#3.5 查找元素)
[3.6 扩容操作](#3.6 扩容操作)
[3.7 打印线性表](#3.7 打印线性表)
[4 线性表的应用](#4 线性表的应用)
[5 总结](#5 总结)
1 简介
线性表是数据结构中最基础且常用的一种结构,它是由一组具有相同类型的元素组成的有序序列。线性表可以通过顺序存储或链式存储来实现。本文将重点介绍顺序存储的线性表,并通过C语言代码来展示其基本操作。
2 线性表的基本概念
线性表是一种线性结构,元素之间存在一对一的关系。线性表的基本操作包括:

3 顺序存储的线性表
顺序存储的线性表是通过数组来实现的。数组中的元素在内存中是连续存储的,因此可以通过下标直接访问元素,具有较高的访问效率。然而,顺序存储的线性表在插入和删除操作时,需要移动大量元素,时间复杂度较高。

3.1 定义线性表结构
我们首先定义一个线性表的结构体,包含以下成员:
-
data
:指向存储元素的数组。 -
size
:当前线性表的大小(即元素个数)。 -
capacity
:线性表的最大容量。
cpp
typedef struct
{
int *data; // 存储元素的数组
int size; // 当前大小
int capacity; // 最大容量
} List;
3.2 初始化线性表
在初始化线性表时,我们需要为其分配一块连续的内存空间,并设置初始容量和大小。
cpp
void init(List *l)
{
l->capacity = MAX; // 初始容量
l->size = 0; // 初始大小为0
l->data = malloc(sizeof(int) * l->capacity); // 分配内存
}
3.3 插入元素
插入元素时,需要考虑线性表是否已满。如果已满,则需要先进行扩容操作。插入元素的时间复杂度为O(n),因为可能需要移动大量元素。
cpp
void insert(List *l, int index, int e)
{
// 扩容
if (l->size == l->capacity)
{
incr(l);
}
if (index == l->size)
add(l, e);
if (index < l->size)
{
for (int i = l->size - 1; i >= index; i--)
{
l->data[i + 1] = l->data[i];
}
l->data[index] = e;
l->size++;
}
}
3.4 删除元素
删除元素时,同样需要移动元素以填补删除后的空缺。删除操作的时间复杂度也是O(n)。
cpp
int del(List *l, int index)
{
for (int i = index; i < l->size; i++)
{
l->data[i] = l->data[i + 1];
}
l->size--;
}
3.5 查找元素
查找操作可以通过遍历数组来实现。如果找到目标元素,则返回其索引;否则返回-1。查找操作的时间复杂度为O(n)。
cpp
int find(List *l, int val)
{
int index = -1;
for (int i = 0; i < l->size; i++)
{
if (l->data[i] == val)
{
index = i;
break;
}
}
return index;
}
3.6 扩容操作
当线性表的容量不足时,我们需要对其进行扩容。常见的扩容策略有:
-
倍增:每次扩容时将容量翻倍。
-
固定增量:每次扩容时增加固定的容量。
在本文中,我们采用倍增策略进行扩容。
cpp
void incr(List *l)
{
if (l->size < l->capacity) return;
int incr = l->capacity << 1; // 容量翻倍
l->capacity += incr;
l->data = realloc(l->data, sizeof(int) * l->capacity); // 重新分配内存
}
3.7 打印线性表
为了方便调试和查看线性表的状态,我们可以实现一个打印函数,输出线性表中的所有元素及其容量和大小。
cpp
int show(List *l)
{
printf("--------------------\n");
printf("数据:");
for (int i = 0; i < l->size; i++)
{
printf("%d,", l->data[i]);
}
printf("\n容量:%d,大小:%d\n", l->capacity, l->size);
}
4 线性表的应用
顺序存储的线性表在实际应用中有广泛的用途,例如:
-
数组:数组本身就是一种顺序存储的线性表。
-
栈和队列:栈和队列可以通过顺序存储的线性表来实现。
-
动态数组:通过动态扩容,顺序存储的线性表可以实现动态数组的功能。
5 总结
顺序存储的线性表是一种简单且高效的数据结构,适用于元素数量相对固定且需要频繁访问的场景。然而,由于其插入和删除操作的时间复杂度较高,因此在需要频繁插入和删除的场景下,链式存储的线性表可能更为合适。
通过本文的代码示例,我们可以清晰地看到顺序存储线性表的基本操作及其实现细节。希望本文能帮助你更好地理解线性表的概念及其应用。