数据结构专题 - 线性表

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

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

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 应用场景

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

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

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

五、总结

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/79395.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用wpa_cli和wpa_supplicant配置Liunx开发板的wlan0无线网

目录 1 简单介绍下wpa_cli和wpa_supplicant 1.1 wpa_supplicant 简介 1.2 wpa_cli 简介 1.3 它们之间的关系 2 启动wpa_supplicant 3 使用rz工具把wpa_cli命令上传到开发板 4 用wpa_cli配置网络 参考文献&#xff1a; 1 简单介绍下wpa_cli和wpa_supplicant 1.1 wpa_su…

筛选条件在on和where中的区别(基于hivesql)

理解筛选条件在on和where中的区别&#xff0c;最好先理解sql的执行顺序&#xff0c;尽管实际执行时不同的物理执行引擎可能会有特定的优化&#xff0c;但是逻辑执行顺序必须遵循&#xff1a; 1&#xff09;from&#xff1a;确定数据源是什么&#xff0c;from后可以是单表&#…

springboot 项目 jmeter简单测试流程

测试内容为 主机地址随机数 package com.hainiu.example;import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotat…

爱普生FA2016AS晶振在智能家居中的应用

在智能家居设备高速发展的今天&#xff0c;稳定可靠的时钟信号是确保设备互联互通、精准执行指令的核心。爱普生&#xff08;EPSON&#xff09;推出的FA2016AS内置热敏电阻晶振&#xff0c;凭借其高精度、小体积和卓越的温度稳定性&#xff0c;成为智能家居领域的关键元件&…

分享一个python启动文件脚本(django示例)

今天给大家分享一个python启动文件脚本 在日常开发中&#xff0c;我们常常需要运行多条命令来完成“静态收集”“数据库迁移”“启动服务”……如果把这些命令整合到一个脚本里就好了 一、整体流程概览 #mermaid-svg-wA6UnfATaUOfJoPn {font-family:"trebuchet ms"…

Kubernetes》》K8S》》Pod的健康检查

K8s概念总结 》》》Pod的生命周期阶段 Pod的生命周期可以简单描述&#xff1a;首先Pod被创建&#xff0c;紧接着Pod被调度到Node节点进行部署。 Pod是非常忠诚的&#xff0c;一旦被分配到Node节点后&#xff0c;就不会离开这个Node节点&#xff0c;直到它被删除&#xff0c;删除…

bininote: 使用AI将视频转换了Markdown笔记

GitHub&#xff1a;https://github.com/JefferyHcool/BiliNote 更多AI开源软件&#xff1a;发现分享好用的AI工具、AI开源软件、AI模型、AI变现 - 小众AI BiliNote 是一个开源的 AI 视频笔记助手&#xff0c;支持通过哔哩哔哩、YouTube 等视频链接&#xff0c;自动提取内容并生…

鸿蒙NEXT开发文件预览工具类(ArkTs)

import { uniformTypeDescriptor } from kit.ArkData; import { filePreview } from kit.PreviewKit; import { FileUtil } from ./FileUtil; import { AppUtil } from ./AppUtil; import { WantUtil } from ./WantUtil;/*** 文件预览工具类* 提供文件预览、加载、判断等功能。…

MySQL常用SQL语句的示例

概述 MySQL 常用 SQL 语句的示例&#xff0c;涵盖数据定义、操作、查询等常见场景 一、数据库操作 创建数据库 CREATE DATABASE mydb;选择数据库 USE mydb;删除数据库 DROP DATABASE mydb;二、表操作 创建表 CREATE TABLE users (id INT PRIMARY KEY AUTO_INCREMENT,name VAR…

智算启新篇 安全筑新基 ——中国移动举办智算基础设施及安全分论坛

4月10日&#xff0c;2025中国移动云智算大会智算基础设施及安全分论坛在苏州金鸡湖国际会议中心揭幕。 在数字经济浪潮奔涌向前的时代坐标下&#xff0c;中国移动锚定“创世界一流信息服务科技创新公司”定位&#xff0c;持续推进智算基础设施建设&#xff0c;持续提升网信安全…

MySQL——游标(cursor)

一、什么是游标&#xff1f; 游标&#xff08;Cursor&#xff09; 是MySQL中用于逐行处理查询结果集的数据库对象。它类似于指针&#xff0c;允许开发者在结果集中逐行移动&#xff0c;并对每一行数据进行特定操作。游标将传统的集合操作转换为面向过程的记录处理方式&#xf…

异步编程——微信小程序

1. 前言 引用来自&#xff1a;微信小程序开发中的多线程处理与异步编程_微信小程序 多线程-CSDN博客 微信小程序是基于JavaScript开发的&#xff0c;与浏览器JavaScript不同&#xff0c;小程序运行在WebView内部&#xff0c;没有多线程的概念。小程序的 JavaScript 是单线程的…

HarmonyOS-ArkUI V2状态-PersistenceV2:持久化存储UI状态

PersistenceV2类是一个与AppStorageV2类用法非常相似的类。因为它俩是子类和父类的关系。如果不了解AppStorageV2,可以先跳转至了解一下这个类。 HarmonyOS-ArkUI V2工具类:AppStorageV2:应用全局UI状态存储-CSDN博客 PersistenceV2相比于其父类AppStorageV2而言,它存储的…

《Mycat核心技术》第22章:搭建Mycat+Zookeeper+HAProxy+Keepalived+MySQL高可用架构

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 星球项目地址&#xff1a;https://binghe.gitcode.host/md/zsxq/introduce.html 沉淀&#xff0c…

Aosp13 文件应用点击apk无反应的处理

最近遇到一个问题&#xff0c;在A13上&#xff0c;打开文件管理应用时&#xff0c;点击apk 无反应或者启动安装进程后安装完成或取消安装进程&#xff0c;再次点击apk 无反应。在此记录该问题。 做一下修改&#xff1a;root/package/ providers/DownloadProvider/下 jenkinsdel…

SQL刷题记录贴

1.题目&#xff1a;现在运营想要对用户的年龄分布开展分析&#xff0c;在分析时想要剔除没有获取到年龄的用户&#xff0c;请你取出所有年龄值不为空的用户的设备ID&#xff0c;性别&#xff0c;年龄&#xff0c;学校的信息。 错误&#xff1a;select device_id,gender,age,un…

【Windows本地部署n8n工作流自动平台结合内网穿透远程在线访问】

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

python爬虫降低IP封禁,python爬虫除了使用代理IP和降低请求频率,还有哪些方法可以应对IP封禁?

文章目录 前言1. 利用 CDN 节点2. 模拟真实用户行为3. 使用 IP 池轮换策略4. 处理 Cookie 和会话信息5. 分布式爬虫 前言 除了使用代理 IP 和降低请求频率&#xff0c;以下这些方法也能应对 IP 封禁&#xff1a; Python 3.13.2安装教程&#xff08;附安装包&#xff09;Python…

光谱相机的成像方式

光谱相机的成像方式决定了其如何获取物体的空间与光谱信息&#xff0c;核心在于分光技术与扫描模式的结合。以下是主要成像方式的分类解析&#xff1a; ‌一、滤光片切换型‌ ‌1. 滤光片轮&#xff08;Filter Wheel&#xff09;‌ ‌原理‌&#xff1a;通过旋转装有多个窄带…

AI在市场营销分析中的核心应用及价值,分场景详细说明

以下是 AI在市场营销分析中的核心应用及价值&#xff0c;分场景详细说明&#xff1a; 1. 客户行为分析与细分 AI技术应用&#xff1a; 机器学习&#xff1a;分析用户点击、购买、浏览等行为数据&#xff0c;识别消费模式&#xff08;如高频购买时段、偏好品类&#xff09;。聚…