【数据结构】初识链表

顺序表的优缺点

缺点:

  • 中间/头部的插入删除,时间复杂度效率较低,为O(N)

  • 空间不够的时候需要扩容。

    • 如果是异地扩容,增容需要申请新空间,拷贝数据,释放旧空间,会有不小的消耗。
  • 扩容可能会存在空间浪费。

    • 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

优点:

  • 尾差尾删足够快。
  • 下标的随机访问和修改足够快。

链表的初步认知

针对顺序表的缺点,链表就被设计出来了。
链表的特点即,按需申请释放。
当我们需要一块空间时,我们就申请一块空间。当我们需要添加数据时,就继续增加一个一个小块。
主要是就是一个一个小块之间的连接。为了方便连接和管理,每一个结点中都存有一个指针,用于指向下一个结点。正式一个一个“链接”起来,所以叫做链表。

下面图中主要标识了顺序表和链表的逻辑结构的不同。
对于顺序表,我们只需要知道指向这块内存空间的指针即可。
但是对于链表,我们仅仅知道指向第一块内存空间的指针是不够的,因为一块与一块之间没有连接。所以对于每一块,都必须存有指向下一块空间的指针。

定义单链表的结构

链表的逻辑图:

链表的物理图:

//Single List Table
typedef int SLTDataType;
typedef struct SListNode
{SLTDataType data;struct SListNode* next;//SLTNode* next 是不可以的
}SLTNode;

下面,我们再来写一个打印单链表的的函数。

void PrintSList(SLTNode* phead)
{SLTNode* p = phead;while (p != NULL){printf("%d ", p->data);p=p->next;}printf("NULL\n");
}

然后,接下来,我们再来在主函数中自己建一个单链表,其实也就是开辟几个结点的空间,然后使得结点之间可以“链接”起来即可。

int main()
{SLTNode* n1 = (SLTNode*)malloc(sizeof(SLTNode));n1->data = 1;SLTNode* n2 = (SLTNode*)malloc(sizeof(SLTNode));n2->data = 2;SLTNode* n3 = (SLTNode*)malloc(sizeof(SLTNode));n3->data = 3;n1->next = n2;n2->next = n3;n3->next = NULL;PrintSList(n1);
}

由上图,我们可以知道代码的逻辑。

  • 动态分配内存,创建3个 SLTNode 类型的节点,并将其地址赋值给指针 n1、n2、n3。
  • 然后将3个结点的next字段都赋值。
  • 然后将链表链接起来。
    • n1->next = n2;将节点 n1 的 next 指针指向节点 n2,表示 n1 的下一个节点是 n2。
    • n2->next = n3;将节点 n2 的 next 指针指向节点 n3,表示 n2 的下一个节点是 n3。
    • n3->next = NULL;将节点 n3 的 next 指针设置为 NULL,表示链表到此结束。
  • 最后打印链表。


我们进行逐语句调试,在监视窗口中观察n1,n2,n3的变化。

我们可以看出来,n1、n2 和 n3 的物理地址并不连续。
根据结构体的定义,我们可以计算出结构体的大小。

如果内存连续,地址应该是:

而根据我们的监视信息,并非连续,这正是因为在代码中使用了 malloc 动态分配内存。
malloc 从堆中分配内存,而堆内存的分配通常是非连续的,具体取决于系统内存分配器的实现和当前堆内存的使用情况。因此,动态分配的内存块通常在物理地址上是分散的。



这一篇小博客,我们认识链表,下面我们将接着实现链表。
加油!

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

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

相关文章

I.MX6ULL 中断介绍上

i.MX6ULL是NXP(原Freescale)推出的一款基于ARM Cortex-A7内核的微处理器,广泛应用于嵌入式系统。在i.MX6ULL中,中断(Interrupt)是一种重要的机制,用于处理外部或内部事件,允许微处理…

4-图像梯度计算

文章目录 4.图像梯度计算(1)Sobel算子(2)梯度计算方法(3)Scharr与Laplacian算子4.图像梯度计算 (1)Sobel算子 图像梯度-Sobel算子 Sobel算子是一种经典的图像边缘检测算子,广泛应用于图像处理和计算机视觉领域。以下是关于Sobel算子的详细介绍: 基本原理 Sobel算子…

苍穹外卖——数据统计

在商家管理端的左侧,有一个名为"数据统计"的菜单,该页面负责展示各个维度的数据统计,分别是营业额统计、用户统计、订单统计、销量排名top10。统计的数据是借助一些图形化的报表技术来生成并展示的。在左上角还可选择时间段&#x…

优盘恢复原始容量工具

买到一个优盘,显示32mb,我见过扩容盘,但是这次见到的是缩容盘,把2g的容量缩成32MB了,首次见到。。用芯片查询工具显示如下 ChipsBank(芯邦) CBM2199E 使用以下工具,恢复原始容量。。 其他CMB工具可能不行…

Flutter Candies 一桶天下

| | | | | | | | 入魔的冬瓜 最近刚入桶的兄弟,有责任心的开发者,对自己的项目会不断进行优化,达到最完美的状态 自定义日历组件 主要功能 支持公历,农历,节气,传统节日,常用节假日 …

[Collection与数据结构] B树与B+树

🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏: 🧊 Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 🍕 Collection与…

ROS应用之SwarmSim在ROS 中的协同路径规划

SwarmSim 在 ROS 中的协同路径规划 前言 在多机器人系统(Multi-Robot Systems, MRS)中,SwarmSim 是一个常用的模拟工具,可以对多机器人进行仿真以实现复杂任务的协同。除了任务分配逻辑以外,SwarmSim 在协同路径规划方…

新鲜速递:DeepSeek-R1开源大模型本地部署实战—Ollama + MaxKB 搭建RAG检索增强生成应用

在AI技术快速发展的今天,开源大模型的本地化部署正在成为开发者们的热门实践方向。最火的莫过于吊打OpenAI过亿成本的纯国产DeepSeek开源大模型,就在刚刚,凭一己之力让英伟达大跌18%,纳斯达克大跌3.7%,足足是给中国AI产…

【Rust自学】15.5. Rc<T>:引用计数智能指针与共享所有权

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 15.5.1. 什么是Rc<T> 所有权在大部分情况下都是清晰的。对于一个给定的值&#xff0c;程序员可以准确地推断出哪个变量拥有它。 …

UE5制作视差图

双目深度估计开源数据集很多都是用UE制作的&#xff0c;那么我们自己能否通过UE制作自己想要的场景的数据集呢。最近花了点时间研究了一下&#xff0c;分享给需要的小伙伴。 主要使用的是UnrealCV插件&#xff0c;UnrealCV是一个开源项目&#xff0c;旨在帮助计算机视觉研究人…

基于遗传优化GRNN和Hog特征提取的交通标志识别算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 HOG 4.2 GRNN&#xff08;General Regression Neural Network&#xff09;模型原理 4.3 遗传算法&#xff08;GA&#xff09;优化GRNN平滑因子 5.算法完整程序工程 1.算法运行效果图预…

C语言【基础篇】之流程控制——掌握三大结构的奥秘

流程控制 &#x1f680;前言&#x1f99c;顺序结构&#x1f4af; 定义&#x1f4af;执行规则 &#x1f31f;选择结构&#x1f4af;if语句&#x1f4af;switch语句&#x1f4af;case穿透规则 &#x1f914;循环结构&#x1f4af;for循环&#x1f4af;while循环&#x1f4af;do -…

C++实现状态模式

首先上代码&#xff1a; #include <iostream> #include <memory>class Context;class State { public:virtual void Handle(Context * context) 0; //纯虚函数virtual ~State() default; //虚析构函数 };//创建状态A class ConcreateStateA : public State{…

【React】PureComponent 和 Component 的区别

前言 在 React 中&#xff0c;PureComponent 和 Component 都是用于创建组件的基类&#xff0c;但它们有一个主要的区别&#xff1a;PureComponent 会给类组件默认加一个shouldComponentUpdate周期函数。在此周期函数中&#xff0c;它对props 和 state (新老的属性/状态)会做一…

二级C语言:二维数组每行最大值与首元素交换、删除结构体的重复项、取出单词首字母

目录 一、程序填空 --- 二维数组每行最大值与首元素交换 题目 分析 知识点 --- 交换语句 二、程序修改 --- 删除结构体的重复项 题目 分析 三、程序设计 --- 取出单词首字母 题目 分析 前言 本章讲解&#xff1a;二维数组每行最大值与首元素交换、删除结构体的重复项…

CUDA学习-内存访问

一 访存合并 1.1 说明 本部分内容主要参考: 搞懂 CUDA Shared Memory 上的 bank conflicts 和向量化指令(LDS.128 / float4)的访存特点 - 知乎 1.2 share memory结构 图1.1 share memory结构 放在 shared memory 中的数据是以 4 bytes(即 32 bits)作为 1 个 word,依…

【python】python基于机器学习与数据分析的手机特性关联与分类预测(源码+数据集)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;专__注&#x1f448;&#xff1a;专注主流机器人、人工智能等相关领域的开发、测试技术。 python基于机器学习与数据分析的手机特性关联与分类…

【leetcode详解】T3175(一点反思)

解题心得 要写出一个好的程序&#xff0c;有效解决问题&#xff0c;思路上就不能“太乖” —— 不能被题目的叙述过程所束缚&#xff0c;而是力求细思问题&#xff0c;抽象化问题&#xff0c;并找到背后的逻辑&#xff1b;最后抓住核心对象&#xff0c;去除多余项&#xff0c;…

图论——最小生成树

最小生成树 给定一个无向图&#xff0c;在图中选择若干条边把图的所有节点连起来。要求边长之和最小。在图论中&#xff0c;叫做求最小生成树。 prim算法 prim 算法采用的是一种贪心的策略。 每次将离连通部分的最近的点和点对应的边加入的连通部分&#xff0c;连通部分逐渐扩大…

jvisualvm工具使用

jvisualvm 是JDK自带的具有图形界面操作功能的JVM性能监控和诊断工具&#xff0c;它不仅能分析和诊断堆转储文件&#xff0c;在线实时监控本地JVM进程&#xff0c;还能监控远程服务器上的JVM进程。 1 分析服务器下载dump文件 1&#xff09;在我们在安装JDK的bin目录双击jvisa…