数据结构_1.0

news2024/12/23 18:39:51

一、数据结构概述

1.1 概念

在计算机科学中,数据结构是一种数据组织、管理和存储的格式 。它是相互之间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术相关。

1.1.1 数据逻辑结构

数据的逻辑结构是指数据元素之间存在的逻辑关系,由数据元素的集合和定义在此集合上的关系组成。数据的逻辑结构与数据的存储无关,独立于计算机,是从具体问题抽象出来的数学模型。

数据的逻辑结构由两个要素构成,分别是:数据元素的集合和关系的集合 。

1.1.2 数据存储结构

数据的逻辑结构在计算机中的存储表示或实现叫做数据的存储结构,也叫物理结构。数据的存储结构依赖于计算机。

一般来说,一种数据结构的逻辑结构根据需要可以表示成多种存储结构,常用的存储结构有顺序存储、链式存储、索引存储哈希存储等。

数据的顺序存储结构的特点是:借助元素在存储器中的相对位置来表示数据元素之间的逻辑关系;非顺序存储的特点是:借助指示元素存储地址的指针表示数据元素之间的逻辑关系。

1.1.3 数据的运算

数据操作是指对数据结构中的数据元素进行运算或处理。数据操作定义在数据的逻辑结构上,每种逻辑结构都需要一组对其数据元素进行处理以实现特定功能的操作,如插入、删除、更新等。数据操作的实现依赖于数据的存储结构。

数据的运算包括:检索、排序、插入、删除、修改等。

二、常见的数据结构

常见的数据结构有:数组(Array)、栈(Stack)、队列(Queue)、链表(Linked List)、树(Tree)、图(Graph)、堆(Heap)、散列表(Hash)。

2.1 数组(Array)

数组是一种线性结构,是可以在内存中连续存储多个元素的结构,在内存中的分配也是连续的,数组中的元素通过数组下标进行访问,数组下标从0开始。

  • 优点:访问数据简单。
  • 缺点:添加和删除数据比较耗时间,因为要移动其他的元素;数组只能存储一种类型的数据;数组的大小固定后就无法扩容了
  • 使用场景:频繁查询,对存储空间要求不大,很少增加和删除的情况。
int[] a = {1,3,4,5,6,8,9,26,30,89};//直接创建并声明容量元素的数组

int[] data = new int[100];// 创建一个整型int数组,大小是100个
 
data[0]  = 1;  // 向数组第一个元素赋值1;
data[1]  = 2;  // 向数组第二个元素赋值2;

JDK提供的顺序表有:java.util.ArrayList 其底层实现就是数组

数组(顺序表)时间复杂度分析:

  1. 查询get(i) ,不难看出不论数据元素量N有多大,只需要一次eles[i] 就可以获取到对应的元素,所以时间复杂度为O(1)
  2. 插入insert(int i, T t),每一次插入,都需要把i位置后面的元素移动一次,随着元素数量N的增大,移动的元素也越多,时间复杂度为O(n)
  3. 删除元素remove(int i),每一次删除,都需要把i位置后面的元素移动一次,随着数据量N的增大,移动的元素也越多,时间复杂度为O(n)
  4. 数组长度是固定的,所以在操作的过程中涉及到了容器扩容操作。这样会导致顺序表在使用过程中的时间复杂度不是线性的,在某些扩容的结点处,耗时会突增,尤其是元素越多,这个问题越明显

2.2 链表(Linked List)

链表是一种数据元素按照链式存储结构进行存储的数据结构,这种存储结构具有在物理上非连续、非顺序的特点。链表由一系列数据结点构成,每个数据结点包括数据域和指针域两部分。其中,指针域保存了数据结构中下一个元素存放的地址。

链表结构中数据元素的逻辑顺序通过链表中的指针链接次序实现 。

根据指针的指向,链表能形成不同的结构,例如单链表,双向链表,循环链表等。

链表时间复杂度分析:

  1. get(int i):每一次查询,都需要从链表的头部开始,依次向后查找,随着数据元素N的增多,比较的元素越多,时间复杂度为O(n)
  2. insert(int i, T t):每一次插入,需要先找到i位置的前一个元素,然后完成插入操作,随着数据元素N的增多,查找的元素越多,时间复杂度为O(n)
  3. remove(int i):每一次移除,需要先找到i位置的前一个元素,然后完成插入操作,随着数据元素N的增多,查找的元素越多,时间复杂度为O(n)

ArrayList vs LinkedList

ArrayList

  1. 基于数组,需要连续内存
  2. 随机访问快(指根据下标访问)
  3. 尾部插入、删除性能可以,其它部分插入、删除都会移动数据,因此性能会低
  4. 可以利用 cpu 缓存,局部性原理

LinkedList

  1. 基于双向链表,无需连续内存
  2. 随机访问慢(要沿着链表遍历)
  3. 头尾插入删除性能高
  4. 占用内存多

链表的优点: 

  • 链表是很常用的一种数据结构,不需要初始化容量,可以任意加减元素; 
  • 添加或者删除元素时只需要改变前后两个元素结点的指针域指向地址即可,所以添加,删除很快;

缺点: 

  • 因为含有大量的指针域,占用空间较大; 
  • 查找元素需要遍历链表来查找,非常耗时。

JDK提供的链表有:java.util.LinkedList

适用场景: 

  • 数据量较小,需要频繁增加,删除操作的场景;
  • 快慢指针:求中间值问题、单向链表是否有环问题、有环链表入口问题;
  • 循环链表:约瑟夫问题

2.3 栈(Stack) 

栈是一种特殊的线性表,又称为栈。是一种基于先进后出(FILO)的数据结构,它只能在表的固定端进行数据结点的插入和删除操作。栈按照先进后出、后进先出的原则来存储数据,也就是说,先插入的数据将被压入栈底,最后插入的数据在栈顶,读出数据时,从栈顶开始逐个读出。

栈在汇编语言程序中,经常用于重要数据的现场保护。栈中没有数据时,称为空栈 。

我们称数据进入到栈的动作为压栈,数据从栈中出去的动作为弹栈。

JDK提供的栈有:java.util.Stack 

应用场景:括号匹配问题;逆波兰表达式求值问题;实现递归功能方面的场景,例如斐波那契数列。

2.4 队列(Queue)

队列是一种基于先进先出(FIFO)的数据结构,是一种只能在一端进行插入,在另一端进行删除操作的特殊线性表,它按照先进先出的原则存储数据,先进入的数据,在读取数据时先被读取出来。

入队列:进行插入操作的一端称为队尾 出队列:进行删除操作的一端称为队头

JDK提供的队列接口有:java.util.Queue

使用场景:因为队列先进先出的特点,在多线程阻塞队列管理中非常适用。

2.5 树(Tree)

树是典型的非线性结构,它是由n(n>0)个有限结点组成的一个具有层次关系的集合。在树结构中,有且仅有一个根结点,该结点没有前驱结点。在树结构中的其他结点都有且仅有一个前驱结点。

树具有以下特点:

  1. 每个结点有零个或多个子结点;
  2. 没有父结点的结点为根结点;
  3. 每一个非根结点只有一个父结点;
  4. 除了根节点外,每个子节点可以分为多个不相交的子树;

在日常的应用中,我们讨论和用的更多的是树的其中一种结构,就是二叉树、平衡树、红黑树、B树、B+树。

应用场景:

  1. JDK1.8中 HashMap的底层源码中用到了数组+链表+红黑树;
  2. 磁盘文件中使用B树做为数据组织,B树大大提高了IO的操作效率;
  3. mysql数据库索引结构采用B+树;
2.5.1 二叉树:满二叉树和完全二叉树

二叉树是一种比较有用的折中方案,它添加,删除元素都很快,并且在查找方面也有很多的算法优化,所以,二叉树既有链表的好处,也有数组的好处,是两者的优化方案,在处理大批量的动态数据方面非常有用。

二叉树有很多扩展的数据结构,包括平衡二叉树、红黑树、B+树等,这些数据结构在二叉树的基础上衍生了很多的功能,在实际应用中广泛用到,例如mysql的数据库索引结构用的就是B+树,还有HashMap的底层源码中用到了红黑树。

二叉树是树的特殊一种,具有如下特点:

  • 每个结点最多有两颗子树,结点的度最大为2。
  • 左子树和右子树是有顺序的,次序不能颠倒。
  • 即使某结点只有一个子树,也要区分左右子树。

顺序结构(数组来存储,heap里面讲)
顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。

链式结构
二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。 通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址 。链式结构又分为二叉链和三叉链,当前我们学习中一般都是二叉链,后面课程学到高阶数据 结构如红黑树等会用到三叉链。

链式结构接口如下:(包括三种遍历方式:前序遍历、中序遍历、后序遍历,以及层序遍历)

2.6 散列表(Hash)

散列表,也叫哈希表,是根据关键码和值 (key和value) 直接进行访问的数据结构,通过key和value来映射到集合中的一个位置,这样就可以很快找到集合中的对应元素。

记录的存储位置=f(key)

这里的对应关系 f 成为散列函数,又称为哈希 (hash函数),而散列表就是把Key通过一个固定的算法函数既所谓的哈希函数转换成一个整型数字,然后就将该数字对数组长度进行取余,取余结果就当作数组的下标,将value存储在以该数字为下标的数组空间里,这种存储空间可以充分利用数组的查找优势来查找元素,所以查找的速度很快。

在存储数据的过程中,如果发生冲突,可以利用链表在已有数据的后面插入新数据来解决冲突。这种方法被称为“链地址法”。除了链地址法以外,还有几种解决冲突的方法。其中,应用较为广泛的是“开放地址法”。

DK提供的哈希表有:java.util.HashMap

散列表应用场景:

  • 哈希表的应用场景很多,当然也有很多问题要考虑,比如哈希冲突的问题,如果处理的不好会浪费大量的时间,导致应用崩溃。
  • 解决哈希冲突问题:1 可以对数组扩容; 2 优化hash计算方式;

2.7 堆(Heap)

堆是一种特殊的树形数据结构,一般讨论的堆都是二叉堆。堆的特点是根结点的值是所有结点中最小的或者最大的,并且根结点的两个子树也是一个堆结构 。

被用于实现“优先队列”(priority queues)。优先队列是一种数据结构,可以自由添加数据,但取出数据时要从最小值开始按顺序取出。在堆的树形结构中,各个顶点被称为“结点”(node),数据就存储在这些结点中。堆有下列特点

  • 每个节点最多有两个子节点
  • 排列顺序必须从上到下,同一行从左到右
  • 堆中某个节点的值总是不大于或不小于其父节点的值;
  • 存放数据时,一般会把新数据放在最下面一行靠左的位置。如果最下面一行没有多余空间时,就再往下另起一行,并把数据添加到这一行的最左端。

堆的性质:

  • 堆是一个完全二叉树
  • 堆中某个结点的值总是不大于或不小于其父结点的值;
  • 除了树的最后一层结点不需要是满的,其它的每一层从左到右都是满的,如果最后一层结点不是满的,那么要求左满右不满;
  • 它通常用数组来实现;
将根结点最大的堆叫做最大堆或大根堆,根结点最小的堆叫做最小堆或小根堆。常见的堆有二叉堆、
斐波那契堆等。
一棵深度为k的有n个结点的二叉树,对树中的结点按从上至下、从左到右的顺序进行编号,
如果编号为i(1≤i≤n)的结点与满二叉树中编号为i的结点在二叉树中的位置相同,则这棵二叉树
称为完全二叉树。
一棵深度为k且有2^k−1个结点的二叉树称为满二叉树。也就是说除了叶子节点都有2个子节点,且
所有的叶子节点都在同一层。

堆应用场景:因为堆有序的特点,一般用来做数组中的排序,称为堆排序。

2.8 图(Graph)

图是另一种非线性数据结构。图的数据结构包含一个有限的集合作为结点集合,以及一个无序对(对应无向图)或有序对(对应有向图)的集合作为边的集合。如果两个结点之间存在一条边,那么就表示这两个结点具有相邻关系 。

无向图:

有向图:

图的搜索:

  • 深度优先搜索:指的是在搜索时,如果遇到一个结点既有子结点,又有兄弟结点,那么先找子结点,然后找兄弟结点。
  • 广度优先搜索:指的是在搜索时,如果遇到一个结点既有子结点,又有兄弟结点,那么先找兄弟结点,然后找子结点。

图的应用场景:

  • 道路畅通工程
  • 最短路径

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

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

相关文章

【】AI八股-神经网络相关

Epoch Epoch 是指完成一次完整的数据集训练的过程。比如,有一个数据集有1000个样本,当网络用这些样本训练一次后,这就是一个epoch。 Iteration Iteration 是指在一个epoch中,使用一个batch进行训练的次数。如果你的数据集有100…

2024年【四川省安全员A证】试题及解析及四川省安全员A证模拟考试

题库来源:安全生产模拟考试一点通公众号小程序 四川省安全员A证试题及解析根据新四川省安全员A证考试大纲要求,安全生产模拟考试一点通将四川省安全员A证模拟考试试题进行汇编,组成一套四川省安全员A证全真模拟考试试题,学员可通…

深度解密Spark性能优化之道

课程介绍 课程通过实战案例解析和性能调优技巧的讲解,帮助学员提升大数据处理系统的性能和效率。课程内容涵盖了Spark性能调优的各个方面,包括内存管理、并行度设置、数据倾斜处理、Shuffle调优、资源配置等关键技术和策略。学员将通过实际案例的演示和…

文件操作详解(C语言)

1.为什么要用到文件?怎样数据才能持久化? 保存在内存中的数不安全(一次断电,忘记保存,不用了还给系统) 持久化:保存在硬盘上(放在文件中) 什么是文件?文件…

鱼塘专用激光冲击波声压网驱鸟器

随着生态环境的日益改善,越来越多的鸟类频繁光临鱼塘,捕食鱼苗或成鱼,给养殖户造成巨大的经济损失。 如何有效地让鸟远离你的鱼塘呢? 鱼塘专用激光冲击波声压网驱鸟器,结合了多种驱鸟功能,包括激光驱鸟技术…

分页导航DOM更新实践:JavaScript与jQuery的结合使用

分页导航DOM更新实践:JavaScript与jQuery的结合使用 在Web开发中,分页导航是展示大量数据时不可或缺的UI组件。合理的分页不仅可以提高应用性能,还能优化用户体验。本博客将通过一个实际的DOM结构和模拟数据,讲解如何使用JavaScr…

CentOS修复OpenSSH漏洞升级到openssh 9.7 RPM更新包

在做政府和学校单位网站时,经常需要服务器扫描检测,经常被OpenSSH Server远程代码执行漏洞(CVE-2024-6387)安全风险通告,出了报告需要升级OpenSSH。 使用yum update openssh是无法更新到最新的,因为系统里的…

基于蜉蝣优化的聚类算法(MATLAB)

优化问题广泛存在于人们的日常生活和工程领域,其解决如何寻找使目标值达到最优的可行解的问题。伴随着科技发展,优化问题在生产调度、神经网络训练、图像处理、能源系统等领域起到举足轻重的作用,有助于提高系统效率。优化问题依据不同标准可…

Vision Transformer论文阅读笔记

目录 An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale -- Vision Transformer摘要Introduction—简介RELATED WORK—相关工作METHOD—方法VISION TRANSFORMER (VIT)—视觉Transformer(ViT) 分析与评估PRE-TRAINING DATA REQUIREMENTS—预训练数据…

基于小波分析的纹理和颜色反射对称性检测(MATLAB R2018A)

对称物体在自然图像和合成图像中普遍存在。作为对称物体最重要的全局特征之一,对称性检测长期以来都是计算机视觉领域的研究热点,并在图片的语义提取、图像语义理解以及情感识别等任务上具有广泛的应用。对称物体的检测技术,就是将图片中所蕴…

大淘客api实现多多进宝的商品查询PHP版

大家好,我是网创有方,今天教大家如何使用大淘客的api实现拼多多商品详情信息查询。这里用到的多多进宝,如果没有多多进宝的,先去多多进宝注册个账号吧! 第一步:进入大淘客官方创建应用,并且下载…

易编橙·终身成长社群:帮助编程小伙伴少走弯路

🍊 目录 🍊 自我介绍 🍊 如何加入? 🍊 【擅长的技术】 🍊 星主介绍 🍊 星球天团 🍊 易编橙终身成长社群介绍及权益~ 🍊 受众群体 🍊 如何…

ERP系统中有哪些模块?有哪些具体实现方案呢?

对于许多初次接触ERP系统的企业来说,可能会对系统中包含的模块和功能感到困惑。本文将详细介绍ERP系统中的主要模块,需要明确的是,ERP系统是一个庞大的系统,包含了多个模块,每个模块都有其独特的功能和作用。这些模块涵…

CCAA:认证通用基础 10(审核的概念、审核有关的术语、审核的特征、审核原则)

10.审核的概念、审核有关的术语、审核的特征、审核原则 10.1审核的基本概念 第一章 审核基础知识 第一节 概述 1.什么是审核 审核是认证过程中最基本的活动,是审核方案的重要组成部分,其实施效果直接影响到审核方案的意图和审核目标的达成。 在认证…

新手教学系列——【Python开发】不同系统更换pip源的方法

在使用Python进行开发时,你可能会发现使用pip安装包的速度较慢,尤其是在国内进行操作时。为了提高安装速度,我们可以将pip的默认源更换为国内的一些镜像源。本文将详细介绍如何在不同操作系统上进行这一操作,并给出常用的国内镜像源。 为什么要换源 pip默认使用的是官方的…

Python入门 2024/7/1

目录 第一个程序hello world 数据类型 注释 变量 用type类型查看数据类型 ​编辑 数据类型转换 ​编辑 标识符 运算符 字符串的三种定义方式 字符串拼接 ​编辑​编辑 字符串格式化 第一个程序hello world 区分c和python c是printf python是print print("h…

QT Creator生成uml类图

先说方法,使用Doxygen工具,笔者用的虚拟机linux系统下的qt5.7,没找到自带的uml生成类的工具。 1、Doxygen 安装 在 Ubuntu 系统中,执行下面命令安装 doxygen 和 graphviz 软件包。 sudo apt install graphviz # 用于生成代码…

汇凯金业:投资交易如何才能不亏损

投资交易中永不亏损是一个理想化的目标,现实中无法完全避免亏损。然而,通过科学的方法、合理的策略和严格的风险管理,投资者可以大幅减少亏损,并提高长期盈利的概率。以下是一些关键策略和方法,帮助投资者在交易中尽量…

国内品牌成功入驻美国线下商超的五大要诀

海外市场拥有巨大资源,许多国内品牌寻求海外市场拓展,美国市场尤为吸引。但入驻美国线下商超非易事,需明确目标定位、周密策略及强大执行力。下面探讨入驻技巧。 一、明确目标与定位 进入美国市场前,品牌方需明确目标&#xff1a…

【C语言】常见的字符串函数

©作者:末央& ©系列:C语言初阶(适合小白入门) ©说明:以凡人之笔墨,书写未来之大梦 目录 strlen函数模拟实现 strstr子串查找函数模拟实现 strtok字符串分割 strlen函数 strlen函数是一个用于求字符串长度的库函数。它的参数是被求长度的字…