欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 社会 > 数据结构专题 - 线性表

数据结构专题 - 线性表

2025/4/19 17:37:42 来源:https://blog.csdn.net/2302_80961196/article/details/147195906  浏览:    关键词:数据结构专题 - 线性表

   线性表是数据结构中最基础、最常用的数据结构之一,它在实际应用中非常广泛。无论是操作系统中的内存管理,还是数据库中的索引结构,线性表都扮演着重要角色。

一、线性表的概念与抽象数据类型

1.1 线性表的逻辑结构

线性表是由nn ≥ 0)个数据元素组成的有限序列。它的逻辑结构具有以下特点:

  • 每个元素在线性表中都有一个唯一的前驱(除了第一个元素)

  • 每个元素在线性表中都有一个唯一的后继(除了最后一个元素)

  • 元素之间是线性关系(即一对一的关系)

例如,一个学生的成绩列表 [90, 85, 78, 92, 88] 就是一个线性表。

1.2 线性表的抽象数据类型(ADT)

线性表的抽象数据类型定义了它的一组操作接口,而不关心具体的实现细节。以下是线性表的主要操作:

  • 初始化:创建一个空的线性表

  • 插入:在指定位置插入一个新元素

  • 删除:删除指定位置的元素

  • 查找:查找某个元素的位置

  • 遍历:依次访问线性表中的每个元素

  • 清空:清空线性表中的所有元素

1.3 类型定义

线性表中的元素可以是任意类型,例如整数、字符串、对象等。在实际应用中,线性表的元素类型通常根据具体需求定义。

二、线性表的顺序存储

2.1 顺序存储结构

顺序存储是用一段连续的内存空间来存储线性表的元素。通常用数组来实现顺序存储。顺序存储的特点:

  • 优点:支持随机访问,访问速度快

  • 缺点插入和删除操作需要移动大量元素

2.2 顺序存储结构上的基本运算

插入操作

插入操作需要将插入位置之后的所有元素向后移动一位,为新元素腾出空间

初始状态:[a0, a1, a2, a3, a4]
插入位置:2,插入元素:x
操作后:[a0, a1, x, a2, a3, a4]
删除操作

删除操作需要将删除位置之后的所有元素向前移动一位,填补空缺。

初始状态:[a0, a1, a2, a3, a4]
删除位置:2
操作后:[a0, a1, a3, a4]

2.3 顺序存储的代码实现

C语言实现
​
#include <stdio.h>
#include <stdlib.h>#define MAXSIZE 100typedef struct {int data[MAXSIZE];int length;
} SeqList;// 初始化
void InitList(SeqList *L) {L->length = 0;
}// 插入
int Insert(SeqList *L, int pos, int value) {if (pos < 1 || pos > L->length + 1 || L->length >= MAXSIZE) { return 0;} int i; // 声明变量for (i = L->length - 1; i >= pos - 1; i--) { L->data[i + 1] = L->data[i];} L->data[pos - 1] = value;L->length++;return 1;     
}// 删除
int Delete(SeqList *L, int pos, int *value) {if (pos < 1 || pos > L->length) { return 0;} *value = L->data[pos - 1];int i; // 声明变量for (i = pos; i < L->length; i++) { L->data[i - 1] = L->data[i];} L->length--;return 1;
}// 查找
int Locate(SeqList L, int value) {int i; // 声明变量for (i = 0; i < L.length; i++) { if (L.data[i] == value) { return i + 1;}}		 return 0;
}int main() {SeqList L;InitList(&L);Insert(&L, 1, 10);Insert(&L, 2, 20);Insert(&L, 3, 30);int value;Delete(&L, 2, &value);printf("Deleted value: %d\n", value);int pos = Locate(L, 30);printf("Position of 30: %d\n", pos);return 0;
}​
Python实现
​
class SeqList:def __init__(self, size=100):self.data = [None] * sizeself.length = 0self.size = sizedef insert(self, pos, value):if pos < 1 or pos > self.length + 1 or self.length >= self.size:return Falsefor i in range(self.length, pos - 1, -1):self.data[i] = self.data[i - 1]self.data[pos - 1] = valueself.length += 1return Truedef delete(self, pos):if pos < 1 or pos > self.length:return Nonevalue = self.data[pos - 1]for i in range(pos, self.length):self.data[i - 1] = self.data[i]self.length -= 1return valuedef locate(self, value):for i in range(self.length):if self.data[i] == value:return i + 1return 0​

三、线性表的链式存储

3.1 单链表

单链表是通过指针将线性表的元素链接起来的一种存储结构。每个节点包含两个部分:

  • 数据域:存储数据元素

  • 指针域:存储下一个节点的地址

单链表的特点:

  • 优点:插入和删除操作不需要移动元素,只需修改指针

  • 缺点:不支持随机访问,访问速度较慢

3.2 单链表的基本运算

插入操作

在单链表中插入一个新节点,需要修改前驱节点的指针

初始状态:head -> a -> b -> c -> NULL
插入位置:a和b之间,插入x
操作后:head -> a -> x -> b -> c -> NULL

删除操作

在单链表中删除一个节点,需要修改前驱节点的指针,跳过被删除的节点。

初始状态:head -> a -> b -> c -> NULL
删除位置:b
操作后:head -> a -> c -> NULL

3.3 单链表的代码实现

C语言实现
#include <stdio.h>
#include <stdlib.h>typedef struct Node {int data;struct Node *next;
} Node, *LinkedList;// 初始化
void InitList(LinkedList *L) {*L = (LinkedList)malloc(sizeof(Node));(*L)->next = NULL;
}// 插入
void Insert(LinkedList L, int pos, int value) {LinkedList p = L;int i = 0;while (p && i < pos - 1) {p = p->next;i++;}if (!p || i > pos - 1) return;LinkedList newNode = (LinkedList)malloc(sizeof(Node));newNode->data = value;newNode->next = p->next;p->next = newNode;
}// 删除
int Delete(LinkedList L, int pos, int *value) {LinkedList p = L;int i = 0;while (p->next && i < pos - 1) {p = p->next;i++;}if (!p->next || i > pos - 1) return 0;LinkedList q = p->next;*value = q->data;p->next = q->next;free(q);return 1;
}// 查找
LinkedList Locate(LinkedList L, int value) {LinkedList p = L->next;while (p) {if (p->data == value)return p;p = p->next;}return NULL;
}
Python实现
class Node:def __init__(self, data=None):self.data = dataself.next = Noneclass LinkedList:def __init__(self):self.head = Node()def insert(self, pos, value):p = self.headi = 0while p and i < pos - 1:p = p.nexti += 1if not p or i > pos - 1:returnnew_node = Node(value)new_node.next = p.nextp.next = new_nodedef delete(self, pos):p = self.headi = 0while p.next and i < pos - 1:p = p.nexti += 1if not p.next or i > pos - 1:return Noneq = p.nextp.next = q.nextreturn q.datadef locate(self, value):p = self.head.nextwhile p:if p.data == value:return pp = p.nextreturn None

3.4 循环链表

循环链表是单链表的一种变体,其尾节点的指针域指向头节点形成一个环。循环链表的特点:

  • 没有明显的结束标志,需要通过遍历判断是否回到起点

  • 适用于需要频繁从尾部插入或删除的场景

循环链表的代码实现(C语言)
#include <stdio.h>
#include <stdlib.h>typedef struct Node {int data;struct Node *next;
} Node, *CirList;// 初始化
void InitList(CirList *L) {*L = (CirList)malloc(sizeof(Node));(*L)->next = *L; // 指向自身形成循环
}// 插入
void Insert(CirList L, int pos, int value) {CirList p = L;int i = 0;while (p->next != L && i < pos - 1) {p = p->next;i++;}if (p->next == L && i < pos - 1) return;CirList newNode = (CirList)malloc(sizeof(Node));newNode->data = value;newNode->next = p->next;p->next = newNode;
}// 删除
int Delete(CirList L, int pos, int *value) {CirList p = L;int i = 0;while (p->next != L && i < pos - 1) {p = p->next;i++;}if (p->next == L || i > pos - 1) return 0;CirList q = p->next;*value = q->data;p->next = q->next;free(q);return 1;
}

四、线性表的性能分析与应用场景

4.1 性能对比

操作顺序存储单链表循环链表
插入O(n)O(n)O(n)
删除O(n)O(n)O(n)
查找O(1)(随机访问)O(n)O(n)
空间性能需预先分配固定大小空间动态分配,无浪费动态分配,无浪费
适用场景频繁查找的场景频繁插入/删除的场景需要从尾部频繁操作的场景

4.2 应用场景

  • 顺序存储:适用于数据量较小且查找频繁的场景,例如数组实现的栈和队列。

  • 单链表:适用于数据量较大且插入/删除频繁的场景,例如实现动态内存分配。

  • 循环链表:适用于需要从尾部频繁操作的场景,例如循环队列。

五、总结

    线性表是数据结构的基础,理解它的逻辑结构和存储结构是学习其他复杂数据结构的前提。顺序存储和链式存储各有优缺点,选择合适的存储结构需要根据具体的应用场景权衡。通过本文的讲解和代码示例,相信读者已经对线性表有了全面的理解,可以灵活运用到实际开发中。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词