【Hello算法】 > 第 2 关 >数据结构 之 数组与链表

数据结构 之 数组与链表

    • 1:Understanding data structures !
    • ——了解数据结构——
      • 1.1:Classification-分类-
      • 1.2:Type-类型-
    • 2:Arrays are the bricks that make up the wall of data structures *
    • ——数组是组成数据结构这堵墙的一块块砖——
      • 2.1:Common operations-常用操作-
      • 2.2:A&D-优缺点-
      • 2.3:Applicationg-应用-
    • 3:A linked list is a vine that shuttles between these bricks *
    • ——链表是穿梭在这些砖块间的藤蔓——
      • 3.1:Common operations-常用操作-
      • 3.2:Arrays VS Linked list-数组 VS 链表-
      • 3.3:Applicationg-应用-
    • 4:小结Tips:

———————————————————————————————————————————————————————————-
————————————————————Hello算法—速通笔记—第二集—start———————–———————————————-

1:Understanding data structures !

——了解数据结构——

1.1:Classification-分类-

常见的数据结构包括数组、链表、栈、队列、哈希表、树、堆、图,它们从 逻辑结构 和 物理结构 两个维度进行分类。

逻辑结构揭示了数据元素之间的逻辑关系:

  • 线性数据结构:数组、链表、栈、队列、哈希表,元素之间是一对一的顺序关系。
  • 非线性数据结构:树、堆、图、哈希表。(进一步划分为树形结构和网状结构)
    • 树形结构:树、堆、哈希表,元素之间是一对多的关系。
    • 网状结构:图,元素之间是多对多的关系。

物理结构反映了数据在计算机内存中的存储方式:

  • 当算法程序运行时,正在处理的数据主要存储在内存中。
  • 系统通过内存地址来访问目标位置的数据。
  • 内存是所有程序的共享资源。因此在数据结构与算法的设计中,内存资源是一个重要的考虑因素。
  • 所有数据结构都是基于数组、链表或二者的组合实现的。
    例如,栈和队列既可以使用数组实现,也可以使用链表实现;而哈希表的实现可能同时包含数组和链表。
    • 基于数组可实现:栈、队列、哈希表、树、堆、图、矩阵、张量(维度 >=3 的数组)等。
    • 基于链表可实现:栈、队列、哈希表、树、堆、图等。

1.2:Type-类型-

基本数据类型:
是 CPU 可以直接进行运算的类型,在算法中直接被使用,主要包括以下几种。

  • 整数类型 byte、short、int、long 。
  • 浮点数类型 float、double ,用于表示小数。
  • 字符类型 char ,用于表示各种语言的字母、标点符号甚至表情符号等。
  • 布尔类型 bool ,用于表示“是”与“否”判断。

基本数据类型以二进制的形式存储在计算机中。
基本数据类型提供了数据的 内容类型,而数据结构提供了数据的 组织方式

2:Arrays are the bricks that make up the wall of data structures *

——数组是组成数据结构这堵墙的一块块砖——

数组(array)是一种线性数据结构,其将相同类型的元素存储在连续的内存空间中。元素在数组中的位置称为该元素的索引(index)

2.1:Common operations-常用操作-

1:初始化数组 2:访问元素 3:插入元素 4:删除元素 5:遍历数组 6:查找元素 7:扩容数组

代码示例:

/*1------ 初始化数组 */
int arr[5];
int nums[5] = { 1, 3, 2, 5, 4 };// 存储在栈上
int* arr1 = new int[5];// 存储在堆上(需要手动释放空间)
int* nums1 = new int[5] { 1, 3, 2, 5, 4 };/*2------ 随机访问元素 */
int randomAccess(int *nums, int size) {int randomIndex = rand() % size;// 在区间 [0, size) 中随机抽取一个数字int randomNum = nums[randomIndex];// 获取并返回随机元素return randomNum;
}/*3------ 在数组的索引 index 处插入元素 num */
void insert(int *nums, int size, int num, int index) {for (int i = size - 1; i > index; i--) {// 把索引 index 以及之后的所有元素向后移动一位nums[i] = nums[i - 1];}nums[index] = num;// 将 num 赋给 index 处的元素
}/*4------ 删除索引 index 处的元素 */
void remove(int *nums, int size, int index) {for (int i = index; i < size - 1; i++) {// 把索引 index 之后的所有元素向前移动一位nums[i] = nums[i + 1];}
}/*5------ 遍历数组 */
void traverse(int *nums, int size) {int count = 0;for (int i = 0; i < size; i++) {// 通过索引遍历数组count += nums[i];}
}/*6------ 在数组中查找指定元素 */
int find(int *nums, int size, int target) {for (int i = 0; i < size; i++) {if (nums[i] == target)return i;}return -1;
}/*7------ 扩展数组长度 */
int *extend(int *nums, int size, int enlarge) {int *res = new int[size + enlarge]; // 初始化一个扩展长度后的数组for (int i = 0; i < size; i++) {// 将原数组中的所有元素复制到新数组res[i] = nums[i];}delete[] nums;// 释放内存return res;// 返回扩展后的新数组
}

2.2:A&D-优缺点-

A—Advantages:

  • 空间效率高:数组为数据分配了连续的内存块,无须额外的结构开销。
  • 支持随机访问:数组允许在 O(1) 时间内访问任何元素。
  • 缓存局部性:当访问数组元素时,计算机不仅会加载它,还会缓存其周围的其他数据,从而借助高速缓存来提升后续操作的执行速度。

连续空间存储是一把双刃剑。

D—Disadvantages:

  • 插入与删除效率低:当数组中元素较多时,插入与删除操作需要移动大量的元素。
  • 长度不可变:数组在初始化后长度就固定了,扩容数组开销很大。
  • 空间浪费:如果数组分配的大小超过实际所需,多余的空间就被浪费。

2.3:Applicationg-应用-

随机访问:随机抽取一些样本,可以用数组存储,并生成一个随机序列,根据索引实现随机抽样。
排序和搜索:快速排序、归并排序、二分查找等都主要在数组上进行。
查找表:当需要快速查找一个元素或其对应关系时,可以使用数组作为查找表。
假如我们想实现字符到 ASCII 码的映射,则可以将字符的 ASCII 码值作为索引,对应的元素存放在数组中的对应位置。
机器学习:神经网络中大量使用了向量、矩阵、张量之间的线性代数运算,这些数据都是以数组的形式构建的。
数组是神经网络编程中最常使用的数据结构。
数据结构实现:数组可以用于实现栈、队列、哈希表、堆、图等数据结构。例如,图的邻接矩阵表示实际上是一个二维数组。

3:A linked list is a vine that shuttles between these bricks *

——链表是穿梭在这些砖块间的藤蔓——

链表(linked list)是一种线性数据结构,其中的每个元素都是一个节点对象,各个节点通过“引用”相连接。
链表的组成单位是节点(node)对象。每个节点都包含两项数据:节点的“值”和指向下一节点的“引用”。节点有 头节点 和 尾节点 。
尾节点指向的是“空”,在 Java、C++ 和 Python 中分别被记为 null、nullptr 和 None 。
链表节点 ListNode 除了包含值,还需额外保存一个引用(指针)。因此在相同数据量下链表比数组占用更多的内存空间

3.1:Common operations-常用操作-

1:初始化链表 2:插入节点 3:删除节点 4:访问节点 5:查找节点

代码示例:

/*1------ 初始化链表 1 -> 3 -> 2 -> 5 -> 4 */
ListNode* n0 = new ListNode(1);// 初始化各个节点
ListNode* n1 = new ListNode(3);
ListNode* n2 = new ListNode(2);
ListNode* n3 = new ListNode(5);
ListNode* n4 = new ListNode(4);
n0->next = n1;// 构建节点之间的引用
n1->next = n2;
n2->next = n3;
n3->next = n4;/*2------ 在链表的节点 n0 之后插入节点 P ------只需改变两个节点引用(指针)即可*/
void insert(ListNode *n0, ListNode *P) {ListNode *n1 = n0->next;P->next = n1;n0->next = P;
}/*3------ 删除链表的节点 n0 之后的首个节点 ------只需改变一个节点的引用(指针)即可*/
void remove(ListNode *n0) {if (n0->next == nullptr)return;ListNode *P = n0->next; // n0 -> P -> n1ListNode *n1 = P->next;n0->next = n1;delete P;// 释放内存
}/*4------ 访问链表中索引为 index 的节点 ------在链表中访问节点的效率较低*/
ListNode *access(ListNode *head, int index) {for (int i = 0; i < index; i++) {if (head == nullptr)return nullptr;head = head->next;}return head;
}/*5------ 在链表中查找值为 target 的首个节点 ------属于线性查找*/
int find(ListNode *head, int target) {int index = 0;while (head != nullptr) {if (head->val == target)return index;head = head->next;index++;}return -1;
}

3.2:Arrays VS Linked list-数组 VS 链表-

在这里插入图片描述

3.3:Applicationg-应用-

常见的链表类型包括三种:
单向链表:即普通链表。
环形链表:令单向链表的尾节点指向头节点(首尾相接),得到一个环形链表。其任意节点都可以视作头节点。
双向链表:与单向链表相比,双向链表记录了两个方向的引用。双向链表更灵活,可以朝两个方向遍历链表,但也占用更多的内存空间。

  • 单向链表通常用于实现 栈、队列、哈希表和图等数据结构

  • 双向链表常用于需要快速查找前一个和后一个元素的场景。

    • 高级数据结构:比如在红黑树、B 树中,我们需要访问节点的父节点,这可以通过在节点中保存一个指向父节点的引用来实现。
    • 浏览器历史:在网页浏览器中,当用户点击前进或后退按钮时,浏览器需要知道用户访问过的前一个和后一个网页。
    • LRU 算法:在缓存淘汰(LRU)算法中,我们需要快速找到最近最少使用的数据,以及支持快速添加和删除节点。
  • 环形链表常用于需要周期性操作的场景,比如操作系统的资源调度。

    • 时间片轮转调度算法在操作系统中,时间片轮转调度算法是一种常见的 CPU 调度算法,需要对一组进程进行循环。
    • 数据缓冲区:在某些数据缓冲区的实现中,也可能会使用环形链表。

4:小结Tips:

  • 哈希表可能同时包含线性数据结构(数组、链表)和非线性数据结构(树)。
  • char类型的长度由编程语言采用的编码方法决定,可能为1字节或2字节。
  • 栈(队列)可以实现动态的数据操作,但数据结构仍然是“静态”(长度不可变)的。
  • 原码和补码的相互转换实际上是计算“补数”的过程。
  • res = [0] * self.size() 操作,列表不会导致 res 的每个元素引用相同的地址,但二维列表会。
  • C++ STL 里面的 std::list 已经实现了双向链表,但不常被使用,因为空间开销与缓存不友好。
  • 数组中存储的是节点的引用,而非节点本身。
  • 数组要求相同类型的元素,在链表中没有强调相同类型。

————————————————————————————————————————————————————————————
—————————————————————Hello算法—速通笔记—第二集—end—————————————————————–—-

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

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

相关文章

ActiveMQ介绍及linux下安装ActiveMQ

ActiveMQ介绍 概述 ActiveMQ是Apache软件基金下的一个开源软件&#xff0c;它遵循JMS1.1规范&#xff08;Java Message Service&#xff09;&#xff0c;是消息队列服务&#xff0c;是面向消息中间件&#xff08;MOM&#xff09;的最终实现&#xff0c;它为企业消息传递提供高…

Linux_iptables防火墙学习笔记

文章目录 iptables 概述四表五链iptables 安装启动iptables 配置详解iptables配置文件iptables配置语法iptables常用实例查看规则修改默认规则保存和备份规则恢复备份的规则清空规则放行SSH服务在ubuntu14.04中iptables规则持久化 iptables 概述 主机型 对主机进行保护 网络型…

Linux第89步_了解异步通知及其结构和函数

1、了解“异步通知” “异步通知”的核心就是信号。信号是采用软件模拟的“中断”&#xff0c;它由“驱动程序”主动向“应用程序”发送信号&#xff0c;并报告自己可以访问了&#xff0c;“应用程序”收到信号以后&#xff0c;就从“驱动设备”中读取或者写入数据。整个过程就…

JSON数据格式讲解与cJSON库的使用

文章目录 写在前面一、安装cJSON二、使用cJSON1、使用的文件2、如何传输数据&#xff1a;**** 三、JSON语法四、cJSON函数讲解1、cJSON结构体 **2、cJSON结构体与字符串之间的转换&#xff08;重要&#xff09;2.1、标题将cJSON结构体转换为字符串(常用)2.2、将字符串转为cJSON…

浅尝 express + ORM框架 prisma 的结合

一、prisma起步 安装&#xff1a; npm i prisma -g查看初始化帮助信息&#xff1a; prisma init -h查看初始化帮助信息结果&#xff1a; Set up a new Prisma projectUsage$ prisma init [options] Options-h, --help Display this help message --datasource-provider …

MQ概览及Kafka详解

文章目录 概览MQ优点MQ缺点常见MQ对比JMS消息模型点对点模式发布订阅模式 kafka基础架构发布订阅工作流程生产者生产者文件存储生产者分区策略生产者数据可靠性保证生产者数据一致性保证生产者ack机制ExactlyOnce生产者发送消息流程 消费者消费者分区分配策略消费者消费数据问题…

平价健身运动耳机哪个好?真实分享五款高性能产品

在挑选这些耳机时&#xff0c;我们应该综合考虑了音质、舒适度、耐用性、稳定性以及价格等多个因素&#xff0c;无论你是跑步爱好者、健身达人还是户外运动者&#xff0c;接下来就让我们一起探索高性能平价健身运动耳机有哪些吧&#xff0c;都是我真实使用分享的哦。 第一款&am…

Web3与社会契约:去中心化治理的新模式

在数字化时代&#xff0c;技术不断为我们提供新的可能性&#xff0c;而Web3技术作为一种基于区块链的创新&#xff0c;正在引领着互联网的下一波变革。它不仅改变了我们的经济模式和商业逻辑&#xff0c;还对社会契约和权力结构提出了全新的挑战和思考。本文将深入探讨Web3的基…

如何在CentOS安装Firefox并结合内网穿透工具实现公网访问本地火狐浏览器

文章目录 1. 部署Firefox2. 本地访问Firefox3. Linux安装Cpolar4. 配置Firefox公网地址5. 远程访问Firefox6. 固定Firefox公网地址7. 固定地址访问Firefox Firefox是一款免费开源的网页浏览器&#xff0c;由Mozilla基金会开发和维护。它是第一个成功挑战微软Internet Explorer浏…

折叠面板组件(vue)

代码 <template><div class"collapse-info"><div class"collapse-title"><div class"title-left">{{ title }}</div><div click"changeHide"> <Button size"small" v-if"sho…

node后端上传文件到本地指定文件夹

实现 第一步&#xff0c;引入依赖 const fs require(fs) const multer require(multer) 第二步&#xff0c;先设置一个上传守卫&#xff0c;用于初步拦截异常请求 /*** 上传守卫* param req* param res* param next*/ function uploadFile (req, res, next) {// dest 值…

如何在SFTP工具中使用固定公网地址远程访问内网Termux系统

文章目录 1. 安装openSSH2. 安装cpolar3. 远程SFTP连接配置4. 远程SFTP访问4. 配置固定远程连接地址 SFTP&#xff08;SSH File Transfer Protocol&#xff09;是一种基于SSH&#xff08;Secure Shell&#xff09;安全协议的文件传输协议。与FTP协议相比&#xff0c;SFTP使用了…

MVVM、MVC、MVP的区别

MVC、MVP 和 MVVM 是三种常见的软件架构设计模式&#xff0c;主要通过分离关注点的方式来组织代码结构&#xff0c;优化开发效率。 在开发单页面应用时&#xff0c;往往一个路由页面对应了一个脚本文件&#xff0c;所有的页面逻辑都在一个脚本文件里。页面的渲染、数据的获取&a…

Day01-环境准备与镜像案例

Day01-环境准备与镜像案例 1. 容器架构1.1 Iaas Paas Saas (了解)1.2 什么是容器1.3 容器vs虚拟机1.4 Docker极速上手指南1&#xff09;配置docker源(用于安装docker)2&#xff09;docker下载镜像加速的配置3&#xff09;自动补全 1.5 Docker C/S架构1.6 Docker的镜像管理1&…

每日练习——leetcode402. 移掉 K 位数字和17. 电话号码的字母组合

目录 402. 移掉 K 位数字 题目描述 解题思路 代码实现 17. 电话号码的字母组合 题目描述 解题思路 代码实现 402. 移掉 K 位数字 题目描述 给你一个以字符串表示的非负整数 num 和一个整数 k &#xff0c;移除这个数中的 k 位数字&#xff0c;使得剩下的数字最小。请…

为了保护版权,有大量图片需要加logo水印怎么办?快速批量加水印 一键可批量加水印几十张 几百张

一&#xff0c;加水印必要性 在数字化时代&#xff0c;图片作为信息传递的重要媒介&#xff0c;其保护和管理显得尤为重要。而给图片添加水印则是一种有效的方式&#xff0c;它不仅能够防止图片被未经授权地复制和盗用&#xff0c;还能够标明图片的来源和版权信息&#xff0c;…

【Spring】依赖注入(DI)时常用的注解@Autowired和@Value

目录 1、Autowired 自动装配 1.1、要实现自动装配不是一定要使用Autowired 1.2、Autowired的特性 &#xff08;1&#xff09;首先会根据类型去spring容器中找(bytype),如果有多个类型&#xff0c;会根据名字再去spring容器中找(byname) &#xff08;2&#xff09;如果根据名…

springcloud-fegin 组件调用

一、Feign 概述 Feign是Netflix开发的声明式、模板化的HTTP客户端&#xff0c; Feign可以帮助我们更快捷、优雅地调用HTTP API。 在Spring Cloud中&#xff0c;使用Feign非常简单——创建一个接口&#xff0c;并在接口上添加一些注解&#xff0c;代码就完成了。Feign支持多种…

llama-factory SFT系列教程 (二),大模型在自定义数据集 lora 训练与部署

文章目录 简介支持的模型列表2. 添加自定义数据集3. lora 微调4. 大模型 lora 权重&#xff0c;部署问题 参考资料 简介 文章列表&#xff1a; llama-factory SFT系列教程 (一)&#xff0c;大模型 API 部署与使用llama-factory SFT系列教程 (二)&#xff0c;大模型在自定义数…

Day01——NestJS学习之了解、安装、运行

什么是 Nest.js&#xff1f; NestJs 官方简介: Nest (NestJS) 是一个用于构建高效、可扩展的 Node.js 服务器端应用程序的开发框架。它利用 JavaScript 的渐进增强的能力&#xff0c;使用并完全支持 TypeScript &#xff08;仍然允许开发者使用纯 JavaScript 进行开发&#x…