当前位置: 首页 > article >正文

数据结构专题 - 线性表

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

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

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

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

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

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

五、总结

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

相关文章:

数据结构专题 - 线性表

线性表是数据结构中最基础、最常用的数据结构之一&#xff0c;它在实际应用中非常广泛。无论是操作系统中的内存管理&#xff0c;还是数据库中的索引结构&#xff0c;线性表都扮演着重要角色。 一、线性表的概念与抽象数据类型 1.1 线性表的逻辑结构 线性表是由n&#xff08…...

上门送水小程序区域代理模块框架设计

一、逻辑分析 代理申请流程&#xff1a; 潜在代理商通过小程序提交代理申请&#xff0c;需要填写个人或企业基本信息、联系方式、期望代理区域等。系统收到申请后&#xff0c;进行初步审核&#xff0c;检查信息的完整性和合规性。运营人员进行人工审核&#xff0c;根据公司政策…...

asp-for等常用的HTML辅助标记?

在ASP.NET Core Razor Pages 和 MVC 中&#xff0c;除了asp-for之外&#xff0c;还有许多常用的 HTML 辅助标记&#xff0c;下面为你详细介绍&#xff1a; 表单与路由相关 asp-action 和 asp-controller 用途&#xff1a;这两个标记用于生成表单或链接的 URL&#xff0c;指定…...

qt pyqt5的开发, 修改psd图像

这是引子, 需要将这个 photoshop-python-api 进行使用 https://juejin.cn/post/7445112318693621797#heading-4 这个是ps-python-api的官网, 在里面找api文档 https://pypi.org/project/photoshop-python-api/ 源码.gitee.url https://gitee.com/lbnb/psd_work.git 一. 安装必要…...

Spring 中的循环依赖问题:解决方案与三级缓存机制

目录 Spring 中的循环依赖问题&#xff1a;解决方案与三级缓存机制什么是循环依赖&#xff1f;循环依赖的定义循环依赖的举例 Spring 中的循环依赖类型1. 构造器注入引发的循环依赖2. Setter 注入引发的循环依赖3. 字段注入&#xff08;Autowired&#xff09;引发的循环依赖 Sp…...

ios接入穿山甲【Swift】

1.可接入的广告&#xff0c;点击右下角查看接入文档 https://www.csjplatform.com/union/media/union/download/groMore 2.进入接入文档&#xff0c;选择最新版本进行接入 pod Ads-CN-Beta,6.8.0.2pod GMGdtAdapter-Beta, 4.15.22.0pod GDTMobSDK,4.15.30pod KSAdSDK,3.3.74.0p…...

蓝桥杯大模板

init.c void System_Init() {P0 0x00; //关闭蜂鸣器和继电器P2 P2 & 0x1f | 0xa0;P2 & 0x1f;P0 0x00; //关闭LEDP2 P2 & 0x1f | 0x80;P2 & 0x1f; } led.c #include <LED.H>idata unsigned char temp_1 0x00; idata unsigned char temp_old…...

电脑一直不关机会怎么样?电脑长时间不关机的影响

现代生活中&#xff0c;许多人会让自己的电脑24小时不间断运行&#xff0c;无论是为了持续的工作、娱乐&#xff0c;还是出于忘记关机的习惯。然而&#xff0c;电脑长时间不关机&#xff0c;除了提供便利之外&#xff0c;也可能对设备的健康产生一系列影响。本文将为大家介绍电…...

vue3 当页面显示了 p/span/div 标签 想要转换成正常文字

返回值有标签出现时&#xff0c;使用v-html 解决 <p>{{ item.content }}</p> //页面直接显示接口返回的带标签的数据 <p v-html"item.content "></p> //转换成html文件 显示正常文字各种样式 问题&#xff1a; 解决&#xff1a;v-html 显…...

Elasticsearch 8.18 中提供了原生连接 (Native Joins)

作者&#xff1a;来自 Elastic Costin Leau 探索 LOOKUP JOIN&#xff0c;这是一条在 Elasticsearch 8.18 的技术预览中提供的新 ES|QL 命令。 很高兴宣布 LOOKUP JOIN —— 这是一条在 Elasticsearch 8.18 的技术预览中提供的新 ES|QL 命令&#xff0c;旨在执行左 joins 以进行…...

java CountDownLatch用法简介

CountDownLatch倒计数锁存器 CountDownLatch&#xff1a;用于协同控制一个或多个线程等待在其他线程中执行的一组操作完成&#xff0c;然后再继续执行 CountDownLatch用法 构造方法&#xff1a;CountDownLatch(int count)&#xff0c;count指定等待的条件数&#xff08;任务…...

k8s蓝绿发布

k8s蓝绿发布 什么是蓝绿部署K8S中如何实现蓝绿部署k8s蓝绿部署流程图 什么是蓝绿部署 参考: https://youtu.be/CLq_hA0lAd0 https://help.coding.net/docs/cd/best-practice/blue-green.html 蓝绿部署最早是由马丁福勒 2010年在他的博客中提出. 蓝绿部署是一种软件部署策略,用…...

链接世界:计算机网络的核心与前沿

计算机网络引言 在数字化时代&#xff0c;计算机网络已经成为我们日常生活和工作中不可或缺的基础设施。从简单的局域网&#xff08;LAN&#xff09;到全球互联网&#xff0c;计算机网络将数以亿计的设备连接在一起&#xff0c;推动了信息交换、资源共享以及全球化的进程。 什…...

记录Docker部署CosyVoice V2.0声音克隆

#记录工作 CosyVoice 是由 FunAudioLLM 团队开发的一个开源多语言大规模语音生成模型&#xff0c;提供了从推理、训练到部署的全栈解决方案。 项目地址&#xff1a; https://github.com/FunAudioLLM/CosyVoice.git 该项目目前从v1.0版本迭代到v2.0版本&#xff0c;但是在Wind…...

MCU刷写——HEX与S19文件互转详解及Python实现

工作之余来写写关于MCU的Bootloader刷写的相关知识,以免忘记。今天就来聊聊Hex与S19这这两种文件互相转化,我是分享人M哥,目前从事车载控制器的软件开发及测试工作。 学习过程中如有任何疑问,可底下评论! 如果觉得文章内容在工作学习中有帮助到你,麻烦点赞收藏评论+关注走…...

全链路开源数据平台技术选型指南:六大实战工具链解析

在数字化转型加速的背景下&#xff0c;开源技术正重塑数据平台的技术格局。本文深度解析数据平台的全链路架构&#xff0c;精选六款兼具创新性与实用性的开源工具&#xff0c;涵盖数据编排、治理、实时计算、联邦查询等核心场景&#xff0c;为企业构建云原生数据架构提供可落地…...

C++学习:六个月从基础到就业——面向对象编程:封装、继承与多态

C学习&#xff1a;六个月从基础到就业——面向对象编程&#xff1a;封装、继承与多态 本文是我C学习之旅系列的第九篇技术文章&#xff0c;主要讨论C中面向对象编程的三大核心特性&#xff1a;封装、继承与多态。这些概念是理解和应用面向对象设计的关键。查看完整系列目录了解…...

Golang Event Bus 最佳实践:使用 NSQite 实现松耦合架构

Go Event Bus 最佳实践&#xff1a;使用 NSQite 实现松耦合架构 什么是 Event Bus&#xff1f; Event Bus&#xff08;事件总线&#xff09;是一种消息传递模式&#xff0c;它允许应用程序的不同组件通过发布/订阅机制进行通信&#xff0c;而不需要直接相互依赖。这种模式特别…...

独家!美团2025校招大数据题库

推荐阅读文章列表 2025最新大数据开发面试笔记V6.0——试读 我的大数据学习之路 面试聊数仓第一季 题库目录 Java 1.写一个多线程代码 2.写一个单例代码 3.LinkedBlockingQueue原理 4.模板设计模式 5.如何设计一个 生产者-消费者队列 6.堆内存和栈内存 7.ThreadLo…...

用 C++ 模拟客户端渲染中的分步数据加载

用 C++ 模拟客户端渲染中的分步数据加载 引言 在前端开发中,客户端渲染是一种常见的技术,它允许页面在加载后动态地更新内容。通常,页面会先展示一个基本的骨架,然后再逐步加载和渲染具体的数据。本文将介绍如何使用 C++ 编写一个简单的程序来模拟客户端渲染中的这种分步…...

Dify智能体平台源码二次开发笔记(5) - 多租户的SAAS版实现(2)

目录 前言 用户的查询 controller层 添加路由 service层 用户的添加 controller层 添加路由 service层-添加用户 service层-添加用户和租户关系 验证结果 结果 前言 完成租户添加功能后&#xff0c;下一步需要实现租户下的用户管理。基础功能包括&#xff1a;查询租…...

Linux的目录结构(介绍,具体目录结构)

目录 介绍 具体目录结构 简洁的目录解释 详细的目录解释 介绍 Linux的文件系统是采用级层式的树状目录结构&#xff0c;在此结构的最上层是根目录“/”。Linux的世界中&#xff0c;一切皆文件&#xff08;比如&#xff1a;Linux会把硬件映射成文件来管理&#xff09; 具体目…...

如何用 esProc 补充数据库 SQL 的缺失能力

某些数据库 SQL 缺失必要的能力&#xff0c;通常要编写大段的代码&#xff0c;才能间接实现类似的功能&#xff0c;有些情况甚至要改用存储过程&#xff0c;连结构都变了。常见的比如&#xff1a;生成时间序列、保持分组子集、动态行列转换、自然序号、相对位置、按序列和集合生…...

晶晨线刷工具下载及易错点说明:Key文件配置错误/mac剩余数为0解决方法

晶晨线刷工具下载及易错点说明&#xff1a;Key文件配置错误&#xff0f;mac剩余数为0解决方法 各种版本晶晨线刷工具下载&#xff1a; 晶晨线刷工具易出错点故障解决方法&#xff1a; 1、晶晨线刷工具加载固件的时候提示mac红字且剩余数为0的解决办法 很多同学可能会与遇到加…...

论文阅读:Invertible Grayscale

这是一篇 ACM Transactions on Graphic 上的文章&#xff0c;这篇文章中介绍的应用还挺有意思的&#xff0c;关于可逆的图像灰度化。 Abstract 一旦彩色图像被转换为灰度图像&#xff0c;人们普遍认为&#xff0c;即使采用最先进的彩色化方法&#xff0c;原始颜色也无法完全恢…...

linux下使用php修改php.ini的session.save_path无效的解决办法

linux下安装php的组合还是php-fpm和nginx&#xff0c;其实已经安装好了&#xff0c;网站已经能够跑起来了&#xff0c;但是遇到后台登录的时候验证码一直不对&#xff0c;看了下报错&#xff0c;session无法存储&#xff0c;于是新增了一个phpinfo文件&#xff0c;使用web查看下…...

关于ResNet和FPN的一份介绍

在这篇文章中我将介绍ResNet和FPN这两个深度学习中重要的技术。 一、ResNet-50/101 首先我们先来看ResNet技术&#xff1a; 1.1 概述 ResNet技术是基于残差学习&#xff0c;引入Bottleneck技术以及Shortcut Connection技术&#xff0c;而去解决神经网络中的退化问题。 1.2…...

以技术的形式实现发票真伪的快速查验-Android发票查验接口

对于企业而言&#xff0c;假票入账不仅可能导致企业财务损失&#xff0c;更会引发一系列法律风险&#xff0c;因此精准、高效的发票查验服务成为了企业运营不可或缺的支持。发票验真服务接口&#xff0c;正是一款能满足这些需求&#xff0c;助力企业摆脱繁琐流程、提升工作效率…...

Python实现贪吃蛇三

上篇文章Python实现贪吃蛇一&#xff0c;实现了一个贪吃蛇的基础版本。后面第二篇文章Python实现贪吃蛇二修改了一些不足&#xff0c;但最近发现还有两点需要优化&#xff1a; 1、生成食物的时候有概率和记分牌重合 2、游戏缺少暂停功能 先看生成食物的时候有概率和记分牌重合的…...

Docker 中多个容器之间的通信

在 Docker 中&#xff0c;多个容器之间的通信可以通过以下几种主要方式实现&#xff0c;具体选择取决于网络需求、隔离性及管理复杂度&#xff1a; 一、自定义 Bridge 网络&#xff08;推荐&#xff09; 通过创建自定义的 Docker 网络&#xff0c;容器可以加入同一网络并通过容…...