线性表的定义
线性表是一种逻辑结构,由相同数据类型的有限序列组成。元素之间存在顺序关系,除首尾元素外,每个元素有且仅有一个直接前驱和一个直接后继。
线性表的基本操作
- 初始化:创建空表。
- 插入:在指定位置添加元素。
- 删除:移除指定位置的元素。
- 查找:按值或位置检索元素。
- 修改:更新指定位置的元素值。
- 遍历:顺序访问所有元素。
- 判空/判满:检查表的状态。
线性表的存储结构
顺序存储(顺序表)
使用连续的存储单元依次存放元素,逻辑顺序与物理顺序一致。
特点:
- 随机访问高效(时间复杂度 O(1))。
- 插入/删除需移动元素(平均时间复杂度 O(n))。
- 需预先分配固定空间,可能浪费或溢出。
代码示例(C语言):
#define MAX_SIZE 100
typedef struct {
int data[MAX_SIZE];
int length;
} SeqList;
// 初始化
void InitList(SeqList *L) {
L->length = 0;
}
// 插入
int InsertList(SeqList *L, int pos, int value) {
if (pos < 1 || pos > L->length + 1 || L->length >= MAX_SIZE)
return 0; // 失败
for (int i = L->length; i >= pos; i--)
L->data[i] = L->data[i - 1];
L->data[pos - 1] = value;
L->length++;
return 1; // 成功
}
链式存储(链表)
通过指针链接节点,节点包含数据域和指针域。
类型:
- 单链表:每个节点指向下一个节点。
- 双向链表:节点包含前驱和后继指针。
- 循环链表:尾节点指向头节点。
特点:
- 动态分配空间,无需预定义大小。
- 插入/删除效率高(时间复杂度 O(1),若需查找前驱则为 O(n))。
- 随机访问效率低(时间复杂度 O(n))。
代码示例(单链表):
typedef struct Node {
int data;
struct Node *next;
} ListNode;
// 创建节点
ListNode *CreateNode(int value) {
ListNode *node = (ListNode *)malloc(sizeof(ListNode));
node->data = value;
node->next = NULL;
return node;
}
// 头插法
void InsertAtHead(ListNode **head, int value) {
ListNode *newNode = CreateNode(value);
newNode->next = *head;
*head = newNode;
}
应用场景
- 顺序表:元素数量固定、频繁查询的场景(如数组存储静态数据)。
- 链表:动态增删、内存灵活分配的场景(如实现队列、栈或图邻接表)。
性能对比
| 操作 | 顺序表 | 链表 |
|---|---|---|
| 访问元素 | O(1) | O(n) |
| 插入/删除 | O(n) | O(1) |
| 空间灵活性 | 低 | 高 |
通过理解逻辑结构与存储实现的差异,可结合实际需求选择合适结构。