《算法笔记》总结No.10——链表

        从第10期破例插叙一期单链表的实现,这个东东相当重要!考研的同学也可以看:相较于王道考研的伪码不太相同,专注于可以运行。如果是笔试中的伪码,意思正确即可~

 注:博主之前写过一个版本的顺序表和单链表的C++实现,和这篇的写法有所不同,不过内容也较全,大家可以先行阅读~C++数据结构笔记(2)线性表的顺序存储和链式存储_c++线性表的顺序存储和链式存储-CSDN博客文章浏览阅读348次。1.线性表是0个或者多个数据元素的有限序列,其中数据元素类型相同2.线性表可以逐项访问和顺序存储3.有顺序存储和链式存储两种存储方式。接下来,_c++线性表的顺序存储和链式存储https://jslhyh32.blog.csdn.net/article/details/131440870

一.理论精炼

        线性表没什么可说的,比较简单,大家姑且把他理解为数组即可。相较于顺序表的物理结构上也连续存取,链表在内存中的存储位置是离散的。在实现的过程中,多数参考资料愿意以带头节点的链表为例,如下图:

二.分配内存空间

先来看一下链表节点的定义方式: 

struct LNode{int data;LNode* next;
}; 

        初学者接触的时候有人会蒙圈——因为这相当于是嵌套定义,即类型里面又直接定义了一个指向自己类型的指针。但这恰恰是链表的“几何意义”:顺序表的定义就很符合人类的思维惯式,对吧,一个表,或者说是一个有顺序的集合一样,物理上就应该是连续的一堆东西连在一起——计算机的内存中实际上也是这么存放的,因此在定义的时候直接定义成和数组“长得一样”的类型。

        不过链表就不一样了,和他本身的逻辑意义一致——即各节点之间通过指针串起来,彼此之间是不连续的。因此在声明一个链表的时候,其实是声明了一个头结点——这样后面的元素根据指针就可以存在了!即声明的时候先声明一个,然后再根据指针域的值继续赋值。

1.malloc函数

malloc是用于申请分配动态内存的函数,这篇博客已经介绍过,这里不再赘述:

C语言malloc函数及数组初始长度的辨析-CSDN博客文章浏览阅读389次,点赞7次,收藏7次。知名的教材在编写中总是给出了很多伪代码,虽然说从意图上来说只要将代码的逻辑表达清楚就没什么问题,不过很多书中的伪码有些过于逆天,会误导许多基础不扎实的人;另一方面,毕竟每个人的编码习惯不同,可能有些高手喜欢写生僻的代码来让人云里雾里语法的规则。。。。https://jslhyh32.blog.csdn.net/article/details/140559079?spm=1001.2014.3001.5502如下,声明一个LNode类型的指针,再赋予空间:

	LNode* head;head=(LNode*)malloc(5*sizeof(LNode));

逻辑非常清晰明了,malloc返回的是地址,因此需要将这部分地址赋予一个指针~ 

2.new运算符

C++中,可以这样写:

LNode* p=new LNode;

没什么难度,这里主要想讲C,就不展开细说了。 

3.内存泄漏

C语言的设计者认为,程序员完全右能力自己控制内存的分配与释放,因此把对内存的控制、操作都分配给了程序员。使用完malloc等之后,一定要使用free将其释放:

free(head);

三.创建链表

先来直观的感受一下如何创建链表:

	LNode* node1=(LNode*)malloc(sizeof(LNode));LNode* node2=(LNode*)malloc(sizeof(LNode));LNode* node3=(LNode*)malloc(sizeof(LNode));node1->data=1;node1->next=node2;node2->data=2;node2->next=node3;node3->data=3;node3->next=NULL;

显然这样太死板了,没有人机交互,那么不妨我们改善一下,main函数中可以输入链表的长度,如下:

int main(int argc, char *argv[]) {printf("请输入链表的长度:");int num=0;scanf("%d",&num);LNode* List=createLinkList(num); //根据长度创建链表List=List->next; //第一个是头结点,因此从第二个开始才能遍历到数据while(List!=NULL){printf("%d ",List->data);List=List->next;	} return 0;
}

然后我们来编写createLinkList函数:

LNode* createLinkList(int x)
{LNode* head;// 声明头结点LNode* tNode;//当前结点LNode* pre;//当前结点的前驱节点head=(LNode*)malloc(sizeof(LNode));head->next=NULL;//初始化指针域为0 pre=head; int i=1;for(;i<=x;i++){tNode=(LNode*)malloc(sizeof(LNode));//创建一个新节点int temp=0;temp=i;tNode->data=temp;tNode->next=NULL;pre->next=tNode;pre=tNode; } return head;}

(加前驱是为了方便链表的创建,也可以不这样做~)

 

如上图,没什么bug~


为了让大家直观感受一下所谓的【离散】,我们把链表中的节点地址也打印一下,修改main函数如下:

int main(int argc, char *argv[]) {printf("请输入链表的长度:");int num=0;scanf("%d",&num);LNode* List=createLinkList(num); //根据长度创建链表LNode* other=List; //另外单独存放一个头结点 printf("地址依次如下:\n");while(other!=NULL){printf("%d ",&other);other=other->next;	} printf("\n");printf("数值依次如下:\n");List=List->next; //第一个是头结点,因此从第二个开始才能遍历到数据while(List!=NULL){printf("%d ",List->data);List=List->next;	} return 0;
}

如下图:头结点和其他5个节点之间均不是连续的!

 

 另外,每次执行的地址也不尽相同。相信这样直观感受一下,各位就能理解到链表的物理意义了~

四.查找元素

查找就非常简单了,这里我们直接写一个统计某元素个数的函数,如下:

int SearchByValue(LNode* target,int x)
{int count=0;LNode* temp=target->next;while(temp!=NULL){if(temp->data==x)count++;temp=temp->next;	} return count;
}

main函数调用:

 

继续写别的~ 

五.插入元素

这个有点意思,因为需要交换两个指针,具体的逻辑这里不多说了,太基础了,这里放个图让大家看看,千万别被逻辑绕晕~

代码如下:

void InsertByPos(LNode* L,int pos,int x)
{LNode* temp=L;//将头结点的值赋给临时的节点int i=1;for(;i<=pos-1;i++) //找到待插入位置的前一个指针 temp=temp->next; LNode* tNode;	tNode=(LNode*)malloc(sizeof(LNode)); //创建一个新节点tNode->next=temp->next;temp->next=tNode;tNode->data=x; 
}

main函数测试:

//3.测试 InsertByPosInsertByPos(List,4,32); List=List->next; while(List!=NULL){printf("%d %d\n",List->data,&List->next);List=List->next;	} 

结果如下:

堪称完美~ 

六.删除元素

1.按值删除

简单,直接按照上面按值查询的代码写就好,只需要改变if条件的逻辑即可:

void DeleteByValue(LNode* L,int x)
{LNode* temp=L->next;//忽略头结点的第一个LNode* pre=L;//pre始终用来保存 while(temp!=NULL){if(temp->data==x)pre->next=temp->next;pre=temp;temp=temp->next;} 
}

main函数:

	
//4.测试DeleteByValueDeleteByValue(List,4);List=List->next; //第一个是头结点,因此从第二个开始才能遍历到数据while(List!=NULL){printf("%d %d\n",List->data,&List->next);List=List->next;	} 

测试结果: 

4成功被删掉~

2.按位删除

根据插入元素的代码即可修改成功。题外话,其实这里还可以写一个按位查找,大家自己试试~

void DeleteByPos(LNode* L,int pos)
{LNode* temp=L->next;LNode* pre=L;int i=1;for(;i<=pos-1;i++) //找到待插入位置的前一个指针 {pre=temp;temp=temp->next; 	}pre->next=temp->next;	} 

老套路:

	DeleteByPos(List,4);List=List->next; //第一个是头结点,因此从第二个开始才能遍历到数据while(List!=NULL){printf("%d %d\n",List->data,&List->next);List=List->next;	} free(List);return 0;

还是删除掉了第4位的元素~

主打一个过五关斩六将~ 

七.静态链表 

静态链表感觉没什么意思,感觉还不如直接用顺序表,大家自己看看就行,比较简单:

 


写在最后:无论408还是众多985名校的自命题,线性表都是算法题、大题考察的热门,大家一定要熟练掌握代码规范。至于二叉树乃至图论的具体编程实现,怎么说,要是你不是奔着140+去考,其实是可以允许自己不会的,参照二八定律——应该尽可能地从简易的20%里面获取占大头的80%分数。因此这期结束后也不优先更新各种数据结构的实现了,优先更新一些数学的问题,接着就是DFS、BFS、DP这些蓝桥杯等竞赛偏爱的内容。(说句题外话,蓝桥杯之所以被戏称圈钱杯、DP杯,就是因为近年来的考试题目逐渐以暴力和DP为主,在一个不是很发达的省份比如我们这里,即便是A组,如果你的DP异常熟练,拿个省一进国赛是没什么难度的。除了蓝桥杯还有CSP,如果代码基础非常扎实,会处理复杂的字符串,还能熟练掌握DP,考个300+似乎也不是很有难度。。由此可见DP的重要性!


完整的.c文件源码,有需要的自提:

链接:https://pan.baidu.com/s/1uN0elyL2N25vNhF2bSewoA 
提取码:hma8 

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

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

相关文章

Jolt路线图

1. 引言 a16z crypto团队2024年7月更新了其Jolt路线图&#xff1a; 主要分为3大维度&#xff1a; 1&#xff09;链上验证维度&#xff1a; 1.1&#xff09;Zeromorph&#xff1a;见Aztec Labs团队2023年论文 Zeromorph: Zero-Knowledge Multilinear-Evaluation Proofs from…

视觉巡线小车——STM32+OpenMV

系列文章目录 第一章&#xff1a;视觉巡线小车——STM32OpenMV&#xff08;一&#xff09; 第二章&#xff1a;视觉巡线小车——STM32OpenMV&#xff08;二&#xff09; 第三章&#xff1a;视觉巡线小车——STM32OpenMV&#xff08;三&#xff09; 第四章&#xff1a;视觉巡…

【过题记录】 7.21

Mad MAD Sum 算法&#xff1a;思维&#xff0c;前缀最大值 模拟一下他的运行过程就会发现&#xff0c;两次之后整个数组就固定了&#xff0c;之后每次都是每个数往后移动一位&#xff0c;可以模拟两次之后计算每个数的存活轮数&#xff0c;计算贡献。 #include<bits/stdc.h…

JavaSE 知识梳理(下)

1.继承 继承是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特 性 的基础上进行扩展&#xff0c;增加新功能&#xff0c;这样产生新的类&#xff0c;称派生类。 继承主要解决的问题是&#xff1a;共性的抽取&#xff0c;实现代码复用&a…

【D3.js in Action 3 精译_018】2.4 向选择集添加元素

当前内容所在位置 第一部分 D3.js 基础知识 第一章 D3.js 简介&#xff08;已完结&#xff09; 1.1 何为 D3.js&#xff1f;1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践&#xff08;上&#xff09;1.3 数据可视化最佳实践&#xff08;下&#xff09;1.4 本章小结 第二章…

【PyTorch】图像二分类项目-部署

【PyTorch】图像二分类项目 【PyTorch】图像二分类项目-部署 在独立于训练脚本的新脚本中部署用于推理的模型&#xff0c;需要构造一个模型类的对象&#xff0c;并将权重加载到模型中。操作流程为&#xff1a;定义模型--加载权重--在验证和测试数据集上部署模型。 import torch…

基于PSO算法优化PID参数的一些问题

目录 前言 Q1&#xff1a;惯性权重ω如何设置比较好&#xff1f;学习因子C1和C2如何设置&#xff1f; Q2&#xff1a;迭代速度边界设定一定能够遍历&#xff08;/覆盖&#xff09;整个PID参数二维空间范围吗&#xff1f;还是说需要与迭代次数相关&#xff1f;迭代次数越高&a…

MATLAB图像处理分析基础(一)

一、引言 MATLAB软件得到许多数字图像处理学生、老师和科研工作者的喜爱&#xff0c;成为数字图像处理领域不可或缺的工具之一&#xff0c;其与其他软件相比有以下诸多显著优点。首先&#xff0c;MATLAB 拥有强大的内置函数库&#xff0c;涵盖了图像读取、显示、处理及分析的全…

【学习笔记】无人机系统(UAS)的连接、识别和跟踪(九)-无人机区域地面探测与避让(DAA)

引言 3GPP TS 23.256 技术规范&#xff0c;主要定义了3GPP系统对无人机&#xff08;UAV&#xff09;的连接性、身份识别、跟踪及A2X&#xff08;Aircraft-to-Everything&#xff09;服务的支持。 3GPP TS 23.256 技术规范&#xff1a; 【免费】3GPPTS23.256技术报告-无人机系…

ESP8266模块(2)

实例1 查看附近的WiFi 步骤1&#xff1a;进入AT指令模式 使用USB转串口适配器将ESP8266模块连接到电脑。打开串口终端软件&#xff0c;并设置正确的串口和波特率&#xff08;通常为115200&#xff09;。输入以下命令并按回车确认&#xff1a; AT如果模块响应OK&#xff0c;…

【计算机网络】0 课程主要内容(自顶向下方法,中科大郑烇、杨坚)(待)

1 教学目标 掌握计算机网络 基本概念 工作原理 常用技术 为将来学习、应用和研究计算机网络打下坚实基础 2 课程主要内容 1 计算机网络和互联网2 应用层3 传输层4 网络层&#xff1a;数据平面5 网络层&#xff1a;控制平面6 数据链路层和局域网7 网络安全8 无线和移动网络9 多…

构建gitlab远端服务器(check->build->test->deploy)

系列文章目录 提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加 TODO:写完再整理 文章目录 系列文章目录前言构建gitlab远端服务器一、步骤一:搭建gitlab的运行服务器【运维】1. 第一步:硬件服务器准备工作(1)选择合适的硬件和操作系统linux(2)安装必…

Learning vtkjs之WarpScalar

过滤器 WarpScalar 介绍 先看一个官方的一句话介绍&#xff1a; vtkWarpScalar - deform geometry with scalar data vtkWarpScalar - 使用标量数据变形几何体 详细介绍 vtkWarpScalar is a filter that modifies point coordinates by moving points along point normals by…

spss数据分析是什么 怎么下载spss

什么是SPSS SPSS是社会统计科学软件包的简称&#xff0c; 其官方全称为IBM SPSS Statistics。SPSS软件包最初由SPSS Inc.于1968年推出&#xff0c;于2009年被IBM收购&#xff0c;主要运用于各领域数据的管理和统计分析。作为世界社会科学数据分析的标准&#xff0c;SPSS操作操作…

C++合作开发项目:美术馆1.0

快乐星空MakerZINCFFO 合作入口&#xff1a;CM工作室 效果图&#xff1a; 代码&#xff1a; &#xff08;还有几个音乐&#xff01;&#xff09; main.cpp #include <bits/stdc.h> #include <windows.h> #include <conio.h> #include <time.h> #in…

《数据结构》--顺序表

C语言语法基础到数据结构与算法&#xff0c;前面已经掌握并具备了扎实的C语言基础&#xff0c;为什么要学习数据结构课程&#xff1f;--我们学完本章就可以实践一个&#xff1a;通讯录项目 简单了解过后&#xff0c;通讯录具备增加、删除、修改、查找联系人等操作。要想实现通…

Python学习笔记—100页Opencv详细讲解教程

目录 1 创建和显示窗口... - 4 - 2 加载显示图片... - 6 - 3 保存图片... - 7 - 4 视频采集... - 8 - 5视频录制... - 11 - 6 控制鼠标... - 12 - 7 TrackBar 控件... - 14 - 8.RGB和BGR颜色空间... - 16 - 9.HSV和HSL和YUV.. - 17 - 10 颜色空间的转化... - 18 - …

数据结构——栈的实现(java实现)与相应的oj题

文章目录 一 栈栈的概念:栈的实现&#xff1a;栈的数组实现默认构造方法压栈获取栈元素的个数出栈获取栈顶元素判断当前栈是否为空 java提供的Stack类Stack实现的接口&#xff1a; LinkedList也可以当Stack使用虚拟机栈&#xff0c;栈帧&#xff0c;栈的三个概念 二 栈的一些算…

JetBrains IDE 使用git进行多人合作开发教程

以下DEMO可以用于多人共同开发维护一个项目时&#xff0c;使用Git远程仓库的实践方案 分支管理 dev&#xff1a;开发分支test&#xff1a;测试分支prod&#xff1a;生成分支 个人开发也最起码有一个masterdev&#xff0c;作为主分支和当前开发分支。master永远是稳定版本&am…

花几千上万学习Java,真没必要!(十九)

1、StringBuilder&#xff1a; 测试代码1&#xff1a; package stringbuilder.com; import java.util.ArrayList; import java.util.List; public class StringBuilderExample { public static void main(String[] args) { // 初始化StringBuilder StringBuilder sb n…