迷人的数据结构:揭秘数组和链表的不同

数据结构中的数组和链表的区别

  • 一、简介
  • 二、数组的特点和特性
  • 三、链表的特点和特性
  • 四、数组和链表的对比
  • 五、数组和链表的代码实现
  • 六、总结

一、简介

数据结构是组织和存储数据的方式,直接影响着程序性能、内存利用和资源管理等关键方面。

  1. 数据结构提供了各种方法来组织和存储数据,包括数组、链表、栈、队列、树和图等。

  2. 许多算法的设计和优化都与数据结构密不可分。

  3. 合适的数据结构能够更有效地利用内存资源,减少资源浪费并提高程序性能。

  4. 在软件工程和系统设计中,数据结构是构建复杂系统和解决实际问题的基础。

数组和链表是两种常见的数据结构,本文旨在深入探讨数组和链表的区别,揭秘它们的异同点。

二、数组的特点和特性

数组是一种数据结构,用于存储相同类型的元素,这些元素通常被存储在连续的内存位置上。

定义:数组是具有相同数据类型的元素集合,这些元素按照一定的顺序在内存中连续存储。数组可以包含任意数量的元素,但一旦创建后其大小通常是固定的。

相关概念:

  • 元素:数组中的每个数据项称为一个元素,数组可以存储整数、浮点数、字符、对象等各种数据类型的元素。元素可以通过索引(或下标)来访问,索引通常从0开始,依次递增。
  • 索引:数组元素的位置通过索引来表示,索引用于唯一标识数组中的每个元素。通过索引,可以快速定位数组中的元素。
  • 大小:数组的大小是指数组中元素的数量。一旦数组在创建时分配了一定的大小,无法动态地增加或减少。
  • 初始化:在创建数组时,需要指定数组的大小,并为每个元素分配内存空间。

在这里插入图片描述

数组的存储结构通常是连续的内存空间,也就是说数组中的元素是依次存储在内存中的连续位置上。这种连续存储结构可以使得数组支持高效的随机访问,因为可以通过元素的索引来直接计算出该元素在内存中的位置。

特点:

  1. 支持高效的随机访问。

  2. 固定大小。

  3. 插入和删除操作的效率较低。

三、链表的特点和特性

链表是一种常见的线性数据结构,由一系列的节点组成,每个节点由两部分组成:数据域和指针域。数据域用于存储节点的数据,而指针域用于指向下一个节点,从而形成一系列的连接。
在这里插入图片描述

基本概念:

  1. 节点:链表中的基本单元,包含数据和指向下一个节点的指针。

  2. 头节点:链表的第一个节点,通常用来标识链表的起始位置。

  3. 尾节点:链表的最后一个节点,其指针通常指向空值(null),表示链表的结束。

  4. 单向链表:每个节点只包含一个指向下一个节点的指针。

  5. 双向链表:每个节点包含两个指针,分别指向前一个节点和后一个节点,使得可以双向遍历链表。

链表相对于数组的优点在于,可以更高效地支持插入和删除操作,因为在链表中插入或删除节点只需要修改相邻节点的指针,而不需要移动大量的元素。链表的缺点是访问时需要从头节点开始顺序查找,无法像数组那样通过索引直接访问元素。

链表的每个节点至少由两部分组成:数据域和指针域。指针域指向下一个节点(对于单向链表)或者同时指向前一个和后一个节点(对于双向链表)。

单向链表的存储结构特点:

  • 每个节点包含数据和指向下一个节点的指针。
  • 节点在内存中不必须是连续存储的,每个节点可以存储在任意内存地址上。
  • 插入和删除节点的操作比较灵活,只需要修改节点指针即可,不需要移动大量元素。
  • 无法直接访问链表中的任一元素,需要从头节点开始按顺序查找,访问效率较低。

在这里插入图片描述

双向链表的存储结构特点:

  • 每个节点包含数据和分别指向前一个节点和后一个节点的指针。
  • 可以双向遍历链表,即可以从头节点到尾节点或者从尾节点到头节点进行遍历。
  • 插入和删除节点的操作相对于单向链表更方便,可以在节点前后两个方向进行操作。
  • 每个节点需要额外存储一个指向前一个节点的指针,因此占用的空间较大。

在这里插入图片描述

在链表中插入一个新节点,可以分为以下几种情况:

  1. 在链表头部插入节点:新节点成为链表的新头节点,将新节点的指针指向原来的头节点,更新链表的头指针。
  2. 在链表尾部插入节点:遍历链表,直到找到尾节点,将新节点的指针指向尾节点,并将新节点设置为新尾节点。
  3. 在链表中间插入节点:找到要插入位置的前一个节点,将前一个节点的指针指向新节点,新节点的指针指向原来位置的下一个节点。

从链表中删除一个节点,可以分为以下几种情况:

  1. 删除头节点:将头指针指向头节点的下一个节点,并释放原来的头节点内存。
  2. 删除尾节点:遍历链表,找到倒数第二个节点,将倒数第二个节点的指针设置为null,并释放原尾节点的内存。
  3. 删除中间节点:找到要删除位置的前一个节点,将前一个节点的指针指向要删除节点的下一个节点,并释放要删除节点的内存。

通过遍历链表来查找特定节点:

  1. 遍历查找:从头节点开始,依次遍历链表的每个节点,直到找到要查找的节点或者遍历到链表尾部。
  2. 特定查找:根据实际需求,可以采用不同的方式进行特定的查找,例如查找第一个符合条件的节点。

除此之外,链表的其他操作还包括获取链表长度、反转链表、合并链表等,这些操作都是基于节点的插入、删除和查找等基本操作进行实现的。

四、数组和链表的对比

数组是连续存储 ,链表是离散存储;数组插入和删除操作需移动元素,而链表插入和删除操作只需要简单修改指针;数组支持随机访问,而链表只能遍历查找。

在这里插入图片描述

数组的连续存储:

  • 数组中的元素在内存中是连续存储的,即相邻的元素在内存中的地址是相邻的。
  • 由于元素的连续存储特性,可以通过元素的下标直接访问和操作元素。
  • 在插入和删除元素时需要移动元素的位置,如果在中间插入或删除元素,需要移动后续元素的位置。

链表的离散存储:

  • 链表中的节点在内存中是离散存储的,即每个节点可以存储在任意的内存地址上。
  • 由于节点的离散存储特性,不能通过下标直接访问元素,只能通过指针进行遍历访问。
  • 在插入和删除节点时,只需要调整节点的指针指向,不需要移动大量的元素,因此插入和删除的时间复杂度通常较低。

插入操作:

  • 在数组中插入元素需要移动插入位置后面的所有元素,以腾出空间来插入新元素。最好情况下,插入到末尾的时间复杂度为 O(1),最坏情况下需要移动整个数组,时间复杂度为 O(n)。
  • 在链表中插入元素只需要修改节点的指针,将新节点插入到合适的位置。无需移动其他节点,时间复杂度为 O(1)。

删除操作:

  • 在数组中删除元素同样需要移动删除位置后面的所有元素,填补删除位置,最好情况下为 O(1),最坏情况下需要移动整个数组,时间复杂度为 O(n)。
  • 在链表中删除元素只需要修改节点的指针,将要删除节点的前一个节点指向要删除节点的下一个节点。同样,时间复杂度为 O(1)。

在查找操作的效率方面,数组的随机访问时间复杂度为 O(1),链表的遍历查找时间复杂度为 O(n)。

五、数组和链表的代码实现

数组的实现:

#include <iostream>
using namespace std;

int main() {
    int arr[5] = {1, 2, 3, 4, 5};

    // 访问数组中的元素
    cout << arr[0] << endl;  // 输出:1

    // 修改数组中的元素
    arr[2] = 10;

    // 打印整个数组
    for (int i = 0; i < 5; ++i) {
        cout << arr[i] << " ";
    }
    cout << endl;  // 输出:1 2 10 4 5

    return 0;
}

链表的实现:

#include <iostream>
using namespace std;

class Node {
public:
    int data;
    Node* next;

    Node(int data) {
        this->data = data;
        this->next = nullptr;
    }
};

class LinkedList {
public:
    Node* head;

    LinkedList() {
        head = nullptr;
    }

    // 在链表末尾添加一个节点
    void append(int data) {
        Node* new_node = new Node(data);
        if (!head) {
            head = new_node;
            return;
        }
        Node* last_node = head;
        while (last_node->next) {
            last_node = last_node->next;
        }
        last_node->next = new_node;
    }

    // 打印链表中的所有节点数据
    void print_list() {
        Node* current_node = head;
        while (current_node) {
            cout << current_node->data << " ";
            current_node = current_node->next;
        }
    }
};

int main() {
    LinkedList linked_list;

    // 在链表末尾添加节点
    linked_list.append(3);
    linked_list.append(5);
    linked_list.append(7);

    // 打印链表数据
    linked_list.print_list();  // 输出:3 5 7

    return 0;
}

六、总结

数组的场景和应用:

  • 需要随机访问元素的场景,因为数组支持常量时间的随机访问,适合需要频繁定位元素位置的情况。
  • 内存空间的利用率相对高,因为数组元素在内存中是连续存储的,没有额外的指针开销,因此相对节省内存。
  • 需要按照元素的索引进行各种操作,并且元素的数量是固定的或者很少改变的情况。

链表的场景和应用:

  • 需要频繁地插入或删除元素的场景,因为链表的插入和删除操作时间复杂度为 O(1)。
  • 需要动态分配内存,并且对内存空间利用率要求较高的情况,因为链表可以动态增长且不要求连续的内存空间。
  • 需要快速查找元素的场景,尤其是对未知位置的元素进行查找、删除和插入。
Doubly Linked List
prev
next,prev
next,prev
结点1
头结点
结点2
结点3
Singly Linked List
结点1
头结点
结点2
结点3

数组适合于需要快速定位元素位置、元素数量固定不变、对内存空间要求较少的场景。而链表适合于需要频繁插入和删除操作、对内存空间的动态分配和利用率要求较高的场景。

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

写点东西《JavaScript 中的递归》

写点东西《JavaScript 中的递归》 您是否曾经发现自己需要在 JavaScript 中循环遍历一个复杂的多维对象&#xff0c;却不知道如何操作&#xff1f; 那么&#xff0c;递归函数到底是什么&#xff1f; 让我们回到我们的树对象。 为什么使用递归&#x1f31f;更多精彩 您是否曾经发…

【前端web入门第二天】01 html语法实现列表与表格

html语法实现列表与表格 文章目录: 1.列表 1.1 无序列表1.2 有序列表1.3 定义列表 2.表格 2.1 表格基本结构2.2 表格结构标签 写在最前,第二天学习目标: 列表 表格 表单 元素为嵌套关系 1.列表 作用:布局内容排列整齐的区域。 列表分类:无序列表、有序列表、定义列表。 1…

动态规划算法题刷题笔记

首先看动态规划的三要素&#xff1a;重叠子问题、最优子结构和状态转移方程。 重叠子问题&#xff1a;存在大量的重复计算 最优子结构&#xff1a; 状态转移方程&#xff1a;当前状态转移成以前的状态 动态规划的解题步骤主要有&#xff1a; 确定 dp 数组以及下标的含义状…

HTML新手教程

HTML入门 教程&#xff1a;【狂神说Java】HTML5完整教学通俗易懂_哔哩哔哩_bilibili 一.初识HTML HyperTextMarkupLanguage&#xff08;超文本标记语言&#xff09; 超文本包括&#xff1a;文字、图片、音频、视频、动画。 HTML5的优势 世界知名浏览器厂商对HTML5的支持市场的…

Spring: alibaba代码规范校验工具checkstyle

文章目录 一、idea配置checkstyle插件二、激活CheckStyle三、配置自动格式化功能四、使用代码格式化 一、idea配置checkstyle插件 下载 Intellij IDEA Checkstyle 插件&#xff1a;File -> setting -> plugin通过关键字CheckStyle-IDEA搜索并安装。 安裝完成后重启idea…

【复现】万户ezoffice协同管理平台 任意文件读取漏洞_30

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 万户ezOFFICE协同管理平台分为企业版和政务版。 解决方案由五大应用、两个支撑平台组成&#xff0c;分别为知识管理、工作流程、沟…

Linux cat,tac,more,head,tail命令 查看文本

目录 一. cat 和 tac命令二. head 和 tail 命令三. more命令 一. cat 和 tac命令 cat&#xff1a;用来打开文本文件&#xff0c;从上到下的顺序显示文件内容。tac&#xff1a;用法和cat相同&#xff0c;只不过是从下到上逆序的方式显示文件内容。当文件的内容有很多的时候&…

LiveGBS流媒体平台GB/T28181常见问题-如何快速查看推流上来的摄像头并停止摄像头推流?

LiveGBS流媒体平台GB/T28181常见问题-如何快速查看推流上来的摄像头并停止摄像头推流&#xff1f; 1、负载信息2、负载信息说明3、会话列表查看3.1、会话列表 4、停止会话5、搭建GB28181视频直播平台 1、负载信息 实时展示直播、回放、播放、录像、H265、级联等使用数目 2、负…

Linux下的进程操作

进程概念 ps -elf&#xff1a;查看操作系统的所有进程&#xff08;Linux命令&#xff09; ctrl z&#xff1a;把进程切换到后台 crtl c&#xff1a;结束进程 fg&#xff1a;把进程切换到前台 获取进程进程号和父进程号 函数原型&#xff1a; pid_t getpid(void); //pid_t…

【阻塞队列】阻塞队列的模拟实现及在生产者和消费者模型上的应用

文章目录 &#x1f4c4;前言一. 阻塞队列初了解&#x1f346;1. 什么是阻塞队列&#xff1f;&#x1f345;2. 为什么使用阻塞队列&#xff1f;&#x1f966;3. Java标准库中阻塞队列的实现 二. 阻塞队列的模拟实现&#x1f35a;1. 实现普通队列&#x1f365;2. 实现队列的阻塞功…

美赛注意事项

2024年1月27日 &#xff1a; 赖维杰 同学分享 1、最后的展现必须要漂亮&#xff08;绘图、呈现&#xff09; 李维情 西北建模王 论文位&#xff08;核心&#xff09;必须清楚建模位、编程位知道做了些什么 常见模型&#xff1a; 1、看真题&#xff0c;读往年论文&#xff0c;选…

计算机找不到ucrtbased.dll无法运行程序,分享5种有效的解决方法

当计算机系统在运行过程中无法找到ucrtbased.dll这个特定的动态链接库文件时&#xff0c;可能会引发一系列的问题和故障现象。ucrtbased.dll是Windows操作系统中一个至关重要的组件&#xff0c;它包含了C运行时库的核心函数&#xff0c;对于许多应用程序特别是基于Microsoft Vi…

vue中的computed

目录 一&#xff1a;介绍 二&#xff1a;例子演示 一&#xff1a;介绍 在 Vue.js 中&#xff0c;computed 属性是一种特殊类型的属性&#xff0c;它允许你声明依赖于其他数据属性的值。computed 属性的值是通过一个函数计算得出的&#xff0c;这个函数可以在其依赖的数据发生…

【misc | CTF】攻防世界 适合作为桌面

天命&#xff1a;这题还挺繁琐的&#xff0c;知识点还不少 目录 步骤1&#xff1a;图片隐写 步骤2&#xff1a;Winhex查看ascii码 步骤1&#xff1a;图片隐写 拿到这张图片&#xff0c;不可能扔进ps会有多图层&#xff0c;普通图片也就一个图层而已 但居然可以有隐写图片这…

I/O多路复用

简介&#xff1a; I/O 多路复用(I/O 多路转接)使得程序能同时监听多个文件描述符&#xff0c;能够提高程序的性能&#xff0c;Linux 下实现 I/O 多路复用的系统调用主要有 select 、 poll 和 epoll 。 select &#xff1a; 主旨思想&#xff1a; 1. 首先要构造一个关于文…

查询排序(2)

Oracle从入门到总裁:https://blog.csdn.net/weixin_67859959/article/details/135209645 1.选择部门 30 中的所有员工 SQL> select *2 from emp3 where deptno 30;EMPNO ENAME JOB MGR HIREDATE SAL COMM …

《动手学深度学习(PyTorch版)》笔记2

Chapter2 Preliminaries 2.1 Automatic Differentiation 让计算机实现微分功能&#xff0c; 有以下四种方式&#xff1a; - 手工计算出微分&#xff0c; 然后编码进代码 - 数值微分 (numerical differentiation) - 符号微分 (symbolic differentiation) - 自动微分&#xff0…

搜维尔科技:【简报】元宇宙数字人赛道,《莉思菱娜》

个性有些古灵精怪时儿安静时而吵闹&#xff0c;虽然以人类寿命来算已经200多岁但在 吸血鬼中还只是个小毛头&#xff0c;从中学开始喜欢打扮偏爱黑白灰色系的服装喜欢时 尚圈&#xff0c;立志想成为美妆或时尚网红不过目前还是学生&#xff0c;脸上的浅色血迹是纹身 贴纸&#…

Javat集合之Lis---(ArrayList和LinkedList)

文章目录 一、 List概述1.1概念1.2list体系结构图1.3 通用方法测试代码 二、List的特点三、遍历方式foreachfor循环迭代器 四、ArrayListArrayList概述概念数据结构 ArrayList的特点 ArrayList去重字符串去重对象去重 五、LinkedListLinkedList概述概念数据结构LinkedList的特点…

一键轻松,免费创造:QuickQR带你体验AI二维码的轻松生成!

当今时代&#xff0c;将信息快速转变为可扫描图案&#xff0c;以简化人们的生活和工作方式&#xff0c;二维码技术展现了它强大的功能。特别是在分享链接、联系信息或进行支付时&#xff0c;二维码已成为现代社会一个不可或缺的部分。本文将探讨生成AI二维码的一种工具&#xf…