学习思维导图:
# 线性表
## 线性表的基本概念
## 线性表的实现
- 顺序存储
- 链式存储
## 线性表的应用
学习思维导图:
# 线性表
## 线性表的基本概念
## 线性表的实现
- 顺序存储
- 链式存储
## 线性表的应用
线性表是L数据结构中的一种基本结构。它是零个或多个数据元素的有限序列。通常,线性表中的数据元素之间是有序的,它们之间存在着前驱和后继的关系。
$$L = (a_1, a_2, \cdots, a_i, a_{i+1}, \cdots, a_n)$$
特点:
InitList
): 创建一个空的线性表。Insert
): 在线性表的指定位置插入一个新的元素。Delete
): 删除线性表中的指定位置的元素。LocateElem
): 根据给定的条件查找线性表中的元素。GetElem
): 获取线性表中指定位置的元素。SetElem
): 修改线性表中指定位置的元素的值。Length
): 返回线性表中的元素数量。IsEmpty
): 判断线性表是否为空。ClearList
): 清除线性表中的所有元素。Traverse
): 对线性表中的每个元素执行某种操作。顺序表(Sequential List) 是一种常见的数据结构,用于存储一组元素,并按照它们在内存中的物理顺序来排列和访问这些元素。顺序表通常由一个数组或列表构成,其中每个元素都占据一个连续的内存位置,并且可以通过索引值来访问。
假设线性表 A 存储的其实位置为LOC(A)
,每个元素占用的存储空间的大小为sizeof(Elem)
,则 A 所对应的顺序存储结构为:
#define MAXSIZE 100
typedef struct {
ElementType data[MAXSIZE];
int length;
} SeqList;
void InitList(SeqList *L) {
L->length = 0;
}
bool Insert(SeqList *L, int pos, ElementType e) {
if (L->length == MAXSIZE || pos < 1 || pos > L->length + 1) {
return false;
}
for (int i = L->length; i >= pos; i--) {
L->data[i] = L->data[i - 1];
}
L->data[pos - 1] = e;
L->length++;
return true;
}
bool Delete(SeqList *L, int pos, ElementType *e) {
if (pos < 1 || pos > L->length) {
return false;
}
*e = L->data[pos - 1];
for (int i = pos; i < L->length; i++) {
L->data[i - 1] = L->data[i];
}
L->length--;
return true;
}
int LocateElem(SeqList L, ElementType e) {
for (int i = 0; i < L.length; i++) {
if (L.data[i] == e) {
return i + 1; // 返回元素位置,而不是下标
}
}
return 0; // 未找到返回0
}
bool GetElem(SeqList L, int pos, ElementType *e) {
if (pos < 1 || pos > L.length) {
return false;
}
*e = L.data[pos - 1];
return true;
}
bool IsEmpty(SeqList L) {
return L.length == 0;
}
void ClearList(SeqList *L) {
L->length = 0;
}
int Length(SeqList L) {
return L.length;
}
线性表的链式表示通常指的是使用链表来实现线性表。链表是由一系列节点组成的,每个节点都包含一个数据元素和一个指向下一个节点的指针。这种结构允许我们动态地插入和删除元素,而不需要移动其他元素。
为了方便链表的操作,常常在单链表中常常引入头结点,头结点中的指针为头指针,指向链表中的第一个结点,如果头指针指向NULL的话,则表示链表为空。
// 链表定义
typedef struct Node {
ElementType data;
struct Node *next;
} Node;
typedef Node *LinkList;
// 初始化
LinkList InitList() {
LinkList L = (Node *)malloc(sizeof(Node)); // 创建头结点
if (L == NULL) exit(1); // 内存分配失败
L->next = NULL; // 初始为空链表
return L;
}
bool Insert(LinkList L, int pos, ElementType e) {
Node *p = L;
int i = 0;
while (p && i < pos - 1) { // 找到第pos-1个节点
p = p->next;
i++;
}
if (!p || i > pos - 1) return false;
Node *s = (Node *)malloc(sizeof(Node));
s->data = e;
s->next = p->next;
p->next = s;
return true;
}
bool Delete(LinkList L, int pos, ElementType *e) {
Node *p = L;
int i = 0;
while (p->next && i < pos - 1) { // 找到第pos-1个节点
p = p->next;
i++;
}
if (!(p->next) || i > pos - 1) return false;
Node *q = p->next;
p->next = q->next;
*e = q->data;
free(q);
return true;
}
int LocateElem(LinkList L, ElementType e) {
Node *p = L->next;
int i = 1;
while (p) {
if (p->data == e) return i;
p = p->next;
i++;
}
return 0; // 未找到返回0
}
bool GetElem(LinkList L, int pos, ElementType *e) {
Node *p = L->next;
int i = 1;
while (p && i < pos) {
p = p->next;
i++;
}
if (!p || i > pos) return false;
*e = p->data;
return true;
}
bool IsEmpty(LinkList L) {
return L->next == NULL;
}
void ClearList(LinkList L) {
Node *p = L->next, *q;
L->next = NULL;
while (p) {
q = p->next;
free(p);
p = q;
}
}