线性表的定义与实现
线性表的定义
线性表是数据结构中的一种基本结构,它由n个数据元素组成的有限序列。在这个序列中,数据元素之间有序排列,每个元素有唯一的前驱和后继(第一个元素除外,它没有前驱;最后一个元素除外,它没有后继)。线性表可以表示为:
[ (a_1, a_2, a_3, ..., a_n) ]
其中,(a_i) 表示第 (i) 个数据元素。线性表的长度为元素的个数,当长度为零时,称为空表。
线性表的实现
线性表的实现方式主要有两种:顺序存储和链式存储。
-
顺序存储 :
顺序存储使用一块连续的存储单元来依次存储线性表中的数据元素。这种方式在逻辑上和物理上都是连续的,因此支持随机访问。具体实现通常使用数组:
c#define MAX_SIZE 100 typedef struct { int data[MAX_SIZE]; // 存储元素的数组 int length; // 线性表的当前长度 } SeqList; void initList(SeqList *L) { L->length = 0; // 初始化长度为0 } int insertElement(SeqList *L, int pos, int elem) { if (pos < 0 || pos > L->length || L->length >= MAX_SIZE) return -1; // 插入位置不合法或表已满 for (int i = L->length; i > pos; i--) { L->data[i] = L->data[i - 1]; // 将元素后移 } L->data[pos] = elem; // 插入元素 L->length++; return 0; // 插入成功 } int deleteElement(SeqList *L, int pos) { if (pos < 0 || pos >= L->length) return -1; // 删除位置不合法 for (int i = pos; i < L->length - 1; i++) { L->data[i] = L->data[i + 1]; // 将元素前移 } L->length--; return 0; // 删除成功 }
顺序存储的优点是支持快速的随机访问,但在插入和删除操作时可能需要移动大量元素,效率较低。
-
链式存储 :
链式存储使用一组任意的存储单元存放线性表中的数据元素,通过指针链接形成一个链表。链表中的每个节点包含数据元素及其后继节点的指针。常见的链表形式有单链表、双向链表和循环链表。
ctypedef struct Node { int data; // 数据域 struct Node *next; // 指针域 } Node, *LinkList; void initList(LinkList *L) { *L = (LinkList)malloc(sizeof(Node)); // 分配头结点 (*L)->next = NULL; // 初始化为空表 } int insertElement(LinkList L, int pos, int elem) { LinkList p = L; int j = 0; while (p && j < pos) { // 找到插入位置 p = p->next; j++; } if (!p || j > pos) return -1; // 插入位置不合法 LinkList s = (LinkList)malloc(sizeof(Node)); s->data = elem; s->next = p->next; // 插入操作 p->next = s; return 0; // 插入成功 } int deleteElement(LinkList L, int pos) { LinkList p = L; int j = 0; while (p->next && j < pos) { // 找到删除位置 p = p->next; j++; } if (!p->next || j > pos) return -1; // 删除位置不合法 LinkList q = p->next; p->next = q->next; // 删除操作 free(q); return 0; // 删除成功 }
链式存储的优点是插入和删除操作效率较高,不需要移动大量元素,但不支持随机访问,只能顺序查找。
通过理解线性表的定义和两种实现方式,我们可以根据具体需求选择适合的数据结构来优化程序性能,提高运行效率。这不仅在理论上有重要意义,在实际编程中也非常实用。