初阶数据结构【3】--单链表(比顺序表还好的一种数据结构!!!)

本章概述

  • 前情回顾
  • 单链表
  • 实现单链表
  • 彩蛋时刻!!!

前情回顾

咱们在上一章博客点击:《顺序表》的末尾,提出了一个问题,讲出了顺序表的缺点——有点浪费空间。所以,为了解决这个问题,我们今天就要讲解链表,咱们在讲结构体的时候有提到过链表,链表的最大优点——一点空间也不浪费,用多少就开辟多少在这里插入图片描述

单链表

  • 概念一种在逻辑上成线性结构,在物理空间上不一定成线性结构的数据结构因为链表是线性表的一种,所以在逻辑上成线性结构“ 链 ”字上就能猜到,在逻辑上成线性结构)。我们链表的开辟用的内存函数malloc。知识点忘记的同学自行回顾:点击:《动态内存管理》。因为内存开辟是随机的,所以我们也不知道它会在内存的那一块区域开辟空间,这就导致开辟的空间可能是连续的,也可能不是连续的。所以,在物理空间上不一定成线性结构。在这里插入图片描述
  • 节点每一个个独立,而且还能存放数据的空间被称为节点。数据结构是用来存储数据的,链表自然也是来存储数据的。存储数据就需要有空间,自然有malloc来给我们开辟空间。万事俱备,只欠东风!可是有想过一个问题吗?——malloc开辟的空间东一块,西一块的它不像realloc那样开辟的连续空间(我们可以挨着挨着找到空间),它的空间是散乱的,不连续的。那么,我们该怎样进行数据的存储,而且还能找到一个一个的数据呢我们可以在这个节点内部划分两部分,一部分用来存储我们想要存储的数据,另一部分部分用来存储下一个节点的地址(因为我们的节点空间是用nalloc开辟的,所以每个节点自然就有个地址)这就需要用到结构体了,进行链表的结构展示:
typedef int SLDatatype ;
typedef struct  Sqlist
{SLDatatype data;	//存放数据,这里假设存放整型类型struct Sqlist* next;   //存放下一个节点的地址
}SLND;		  //定义节点类型

这样我们就能通过地址找到下一个节点了,以此类推,我们就能顺次找到各个节点,找到数据了。如图所示:在这里插入图片描述
当我们不想再存储数据时,要给最后一个节点的next指针赋值NULL(下一个节点为NULL,就相当于没有下一个节点),就表示到此结束了。

  • 链表的性质
    • 1、链式机构在逻辑上是连续的,在物理结构上不⼀定连续。
    • 2、结点⼀般是从堆上申请的。
    • 3、从堆上申请来的空间,是按照⼀定策略分配出来的,每次申请的空间可能连续,可能不连续。
  • 链表的打印:我们讲过了节点的存储结构了,我们可以通过next指针,找到下一个节点,然后就能打印我们想要的数据了。
  • 直观体验链表:我们先给大家直观感受一下链表,让大家有个感觉,我们就按照上面的结构图进行展示:
#define  _CRT_SECURE_NO_WARNINGS	1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SLDatatype;
typedef struct Sqlist
{SLDatatype data;struct Sqlist* next;
}SLND;void my_printf(SLND* ps)
{assert(ps);while (ps){printf("%d->", ps->data);ps = ps->next;}printf("NULL");
}
void test()
{SLND* plist=NULL;  //创立一个带头指针,用来牵引后面的链表,就像火车头一样SLND* node1 = (SLND*)malloc(sizeof(SLND));   //创立3个节点SLND* node2 = (SLND*)malloc(sizeof(SLND));SLND* node3 = (SLND*)malloc(sizeof(SLND));node1->data = 1;  //分别对3个节点·进行·数据的存储node2->data = 2;node3->data = 3;node1->next = node2;  //每个节点的next的指针指向下一个节点的地址node2->next = node3;node3->next = NULL;plist = node1;my_printf(plist);
}
int main()
{test();return 0;
}

结果运行图:在这里插入图片描述
我们的指针plist就是个牵引的作用,就像高铁一样,没有高铁头车厢照样能跑,就是不美观,没有它也可以正常访问链表。有了它就是逻辑上和美观上要舒服很多。如图所示:在这里插入图片描述

实现单链表

和顺序表一样,我们也是创建3个文件: Sqlist .h , Sqlist.ctest .c文件。具体的原因个顺序表一样的。接下来我直接给大家展示代码,我会在注释中详细讲解的。

  • Sqlist.h:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int SListDatatype;
typedef struct SListNode
{SListDatatype data;struct SListNode* next;
}SLND;SLND* SListFind(SLND* phead, SListDatatype x);//找对应的节点
SLND* SLTButnode(SListDatatype x);//申请新的节点
void my_printf(SLND* phead); //·打印链表信息void SListpushback(SLND** pphead, SListDatatype x); //尾插
void SListpopback(SLND** pphead);//尾删void SListpushFront(SLND** pphead, SListDatatype x); //头插
void SListpopFront(SLND** pphead);//头删void SListrdFrontpush(SLND** pphead, SLND* find, SListDatatype x);//在任意节点之前插入数据
void SListrdBackpush(SLND* find, SListDatatype x);//在任意节点之后插入数据void SListposePop(SLND* phead, SLND* pose); //删除指定节点
void SListDestry(SLND** pphead); //销毁链表
  • Sqlist.c:
#include "SList.h"
//打印链表信息
void my_printf(SLND* phead)   //打印信息,便于我们看信息的输出
{SLND* pcur = phead;while (pcur){printf("%d-> ",pcur->data);pcur = pcur->next;}printf("NULL\n"); //第N+1个为空====没有链表
}
SLND * SLTButnode(SListDatatype x)	//申请新空间,返回新空间地址,便于咱们找到新空间插入数据
{SLND* newnode = (SLND*)malloc(sizeof(SLND));if (newnode == NULL){perror("malloc fail!");exit(1);		//若开辟失败就直接退出程序,也可以写成 return 1;}else{newnode->data = x;  	//走到这里就开辟成功,进行初始化newnode->next = NULL;}return newnode;
}
void SListpushback(SLND** pphead, SListDatatype x) //尾插数据
{assert(pphead);  //检查传递的指针是否为空指针SLND* newnode = SLTButnode(x);if (*pphead==NULL)  {*pphead = newnode;	//如果起始没有节点,先创立个节点}else{SLND* ptail = *pphead;while (ptail->next)      //遍历节点,找到最后一个节点的next为空的情况,跳出循环{ptail = ptail->next;  }ptail->next = newnode;  //走到这里说明找到了最后一个节点,在此之后插入新的节点}
}
void SListpopback(SLND** pphead) //尾删数据
{assert(pphead&&*pphead);  //检查传递的指针是否为空指针   SLND* ptail = *pphead;  //我们把起始节点的地址给ptail,用ptail进行遍历数据,去寻找最后的尾节点SLND* prev = NULL;   //prev是用来记录尾节点前一个节点,不记录的话,就会随着我们删除最后一个节点而丢失信息while (ptail->next){prev = ptail;ptail = ptail->next;}prev->next = NULL;free(ptail);  //找到最后一个节点,进行空间释放ptail = NULL;  //释放后要置空,防止产生野指针
}
void SListpushFront(SLND**pphead,SListDatatype x) //头插数据
{assert(pphead);  //判断传递的地址是否为空指针SLND* newnode = SLTButnode(x);newnode->next = *pphead;*pphead = newnode;
}
void SListpopFront(SLND**pphead)//头删
{assert(pphead&&*pphead);	//判断传递的地址是否为空指针SLND*next = (*pphead)->next;free(*pphead);  //释放头节点*pphead = next;  //释放头节点后,要使得plist指向第二个节点
}
SLND* SListFind(SLND*phead,SListDatatype x) //找对应的节点
{assert(phead); 	//判断传递的地址是否为空指针while (phead){if (phead->data == x)return phead;    //找到目标节点,就返回目标节点的地址phead = phead->next;}return NULL;  //没找到就返回空指针
}
void SListrdFrontpush(SLND**pphead,SLND*find,SListDatatype x)//在任意节点之前插入数据
{assert(pphead&&*pphead);		//判断传递的地址是否为空指针if (*pphead == find)    //任意位置刚好是头节点时,相当于头插数据SListpushFront(pphead, x); //头插数据else {SLND*newnode= SLTButnode(x);//申请新的节点SLND* prev = NULL;SLND* ptail = *pphead;while (ptail!= find){prev = ptail;ptail = ptail->next;}prev->next = newnode;  //指定位置之前的节点的next指针指向要插入的新节点newnode->next = ptail;		//这个新节点的next指针指向下一个节点}
}
void SListrdBackpush( SLND* find, SListDatatype x)//在任意节点之后插入数据
{assert(find);		//判断传递的地址是否为空指针SLND* newnode = SLTButnode(x);newnode->next = find->next;  //新节点的next指针指向下一个节点find->next = newnode;		//新节点之前的节点next指针指向这个新节点
}
void SListposePop(SLND**pphead, SLND* pose) //删除指定节点
{assert(*pphead&&pose);		//判断传递的地址是否为空指针if(pose==*pphead)		//当删除的节点是头节点时,就相当于头删SListpopFront(pphead);//头删else{SLND* prev = NULL;	SLND* ptail = *pphead;while (ptail != pose)		//遍历节点,找到目标节点{prev = ptail;ptail = ptail->next;}SLND* next = ptail->next;	prev->next = next;free(ptail);  //删除指定的节点ptail = NULL;    //置空指针,防止发生野指针}
}//链表的销毁和顺序表不一样
void SListDestry(SLND**pphead) //链表的销毁不像顺序表那样直接释放内存就欧克,因为每个
{							//节点都是独立的,所以我们需要去遍历每个节点去销毁assert(*pphead);		//判断传递的地址是否为空指针SLND* prev = NULL;SLND* ptail = *pphead;while (ptail->next) //一直遍历到最后一个节点才结束{prev = ptail;ptail = ptail->next;free(prev); //每遍历一个节点就释放prev = NULL;  //置空指针防止产生野指针}ptail = NULL;		//置空指针防止产生野指针*pphead = NULL;	//置空指针防止产生野指针
}
  • test.h
#define  _CRT_SECURE_NO_WARNINGS	1
#include "SList.h"
void test()
{		//这里给大家演示一下尾插数据,其它功能大家可以自行尝试一下SLND* plist = NULL;SListpushback(&plist,1);//尾插SListpushback(&plist,2);//尾插SListpushback(&plist,3);//尾插SListpushback(&plist,4);//尾插my_printf(plist);
}int main()
{test();return 0;
}

结果运行图:在这里插入图片描述

彩蛋时刻!!!

歌曲:《All Falls Down》听会儿歌曲放松一下呗!!!
在这里插入图片描述
每章一句道路是曲折的,前途是光明的!感谢你能看到这里,点赞+关注+收藏+转发是对我最大的鼓励,咱们下期见!!!

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

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

相关文章

TypeScript 出现过的问题

不能将类型“unknown”分配给类型“string”。 不能直接将类型“unknown”分配给类型“string” /**** 【1 - 问题】会画红波浪线 ****/ window.document.title to?.meta?.title || /**** 【2 - 解决】解决红波浪线 ****/ const title: unknown to?.meta?.title || if …

QML 基本动画

在介绍完 QML 动画框架之后,现在我们来看看具体的动画及其用法。先从最常用的基本动画入手,这些动画包括:PropertyAnimation、ColorAnimation、Vector3dAnimation 和 PathAnimation 等,它们不仅能够帮助我们轻松地为应用程序添加动态效果,还能显著提升用户体验,使得界面更…

vue3 解决背景图与窗口留有间隙的问题

需要实现一个登录界面&#xff0c;login.vue的代码如下&#xff1a; <script> import { ref } from vue;export default {setup() {return {};}, }; </script><template><div id"login-container" class"login-container"><di…

中国古代数学的杰出研究成果之一 - 杨辉三角 - 怎么用go、C++进行编程解决

杨辉三角&#xff0c;又称帕斯卡三角形&#xff08;Pascals Triangle&#xff09;&#xff0c;是组合数学中的一个重要概念。它是一个三角形数组&#xff0c;其中每个数字是它上方左上方和右上方的数字之和。杨辉三角的每一行都代表了二项式展开式的系数&#xff0c;因此在数学…

利用 OBS 推送 WEBRTC 流到 smart rtmpd

webrtc whip 推流 & whep 拉流简介 RFC 定义 通用的 webrtc 对于 SDP 协议的交换已经有对应的 RFC 草案出炉了。这就是 WHIP( push stream ) & WHEP ( pull stream ) . WHIP RFC Link: https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html WHEP RFC Link:…

ubuntu 开启haproxy UI

一、修改haproxy.cfg nano /etc/haproxy/haproxy.cfg 添加一段 listen statsbind *:8080stats enablestats uri /uistats refresh 10sstats auth admin:123456stats admin if TRUE 重启 sudo systemctl restart haproxy 浏览器访问&#xff1a; http://192.168.31.182:80…

搜维尔科技:SenseGlove触觉反馈数据手套的用途和作用

无论是VR培训、遥控机器人、研究还是营销&#xff0c;我们的VR触觉手套都能让虚拟世界更具沉浸感和吸引力。借助我们的硬件和直观的软件开发工具&#xff0c;研究人员和开发人员可以创建真正的触觉交互。 VR培训 使用 SenseGlove进行虚拟现实训练可产生与现实训练类似的效果&a…

MySQL-CRUD-基础-(详解) ┗( ▔, ▔ )┛

目录 ❄️一、新增&#xff08;Create&#xff09;&#xff1a; ☑ 1、单行数据 全列插入&#xff1a; ☑ 2、指定列插入&#xff1a; ☑ 3、多行插入&#xff1a; ❄️二、查询&#xff08;Retrieve&#xff09;&#xff1a; ☑ 1、全列查询&#xff1a; ☑ 2、指定列查询&a…

【数据结构与算法】走进数据结构的“时间胶囊”——栈

大家好&#xff0c;我是小卡皮巴拉 文章目录 目录 引言 一.栈的基本概念 1.1 定义 1.2 特性 1.3 基本操作 二.栈的实现方式 2.1 顺序栈 2.2 链栈 三.顺序栈的实现 定义顺序栈的结构 初始化 入栈 检查栈是否为空 出栈 销毁 四.链栈的实现 定义链栈的结构 初始…

新版idea菜单栏展开与合并

新版idea把菜单栏合并了看着很是不习惯&#xff0c;找了半天原来在这里展开 ① 点击文件 -> 设置 ② 点击外观与行为 -> 外观 -> 合并主菜单和窗口标题 然后确定&#xff0c;重启即可

戴维南,叠加,稳态笔记

一点点学习笔记,仅做个人复习使用 节点电压分清电流电压源&#xff0c;电流源才能写在右边&#xff0c;容易混淆 叠加定理仅适用于线性电路&#xff0c;且不能用于计算功率&#xff0c;主要是方向&#xff0c;要看源的方向判断等效之后的&#xff0c;受控源不参与除源&#x…

数据库表的创建

运用的环境是pychram python3.11.4 创建一个表需要用到以下语法 注释已经写清楚各种语法的含义&#xff0c;记住缩进是你程序运行的关键&#xff0c;因为程序是看你的缩进来判断你的运行逻辑&#xff0c;像我这个就是缩进不合理导致的报错 那么今天分享就到这里&#xff0c;谢…

android11 usb摄像头添加多分辨率支持

部分借鉴于&#xff1a;https://blog.csdn.net/weixin_45639314/article/details/142210634 目录 一、需求介绍 二、UVC介绍 三、解析 四、补丁修改 1、预览的限制主要存在于hal层和framework层 2、添加所需要的分辨率&#xff1a; 3、hal层修改 4、frameworks 5、备…

第九届清洁能源与发电技术国际学术会议(CEPGT 2024)

第九届清洁能源与发电技术国际学术会议&#xff08;CEPGT 2024&#xff09; 2024 9th International Conference on Clean Energy and Power Generation Technology (CEPGT 2024) 【早投稿早录用&#xff0c;享受早鸟优惠】 CEPGT 2024会议已上线至IEEE官网 第九届清洁能源…

15分钟学Go 第2天:安装Go环境

第2天&#xff1a;安装Go环境 1. 引言 在学习Go语言之前&#xff0c;首先需要配置好本地开发环境。本节将详细介绍如何在Windows 11上安装和配置Go语言环境&#xff0c;包括安装步骤、环境变量设置、VS Code配置与测试、以及常见问题解决方案。完成这些步骤后&#xff0c;你将…

Java项目-基于springboot框架的基于协同过滤算法商品推荐系统项目实战(附源码+文档)

作者&#xff1a;计算机学长阿伟 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、ElementUI等&#xff0c;“文末源码”。 开发运行环境 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBoot、Vue、Mybaits Plus、ELementUI工具&#xff1a;IDEA/…

Kettle9.4支持Clickhouse数据源插件开发以及性能测试

前言 最近业务这边有个指标需要用到大数据这边的列式数据库进行处理&#xff0c;由于kettle不支持clickhouse数据源驱动&#xff0c;这里查了一下网上的相关资料&#xff0c;发现了一些别人开发好的驱动包&#xff0c;下载下来后使用效果不尽人意。总结下来有以下几个问题&…

quic-go源码一---server启动

前言&#xff1a; 走马观花地看了RFC 9000:QUIC: A UDP-Based Multiplexed and Secure Transport&#xff0c; 感受不是那么直观&#xff0c;所以再来看看这个协议的golang语言实现&#xff1a;quic-go,加强学习。 https://quic-go.net/docs/quic/quic-go文档 本篇准备的代…

基于R语言机器学习方法在生态经济学领域中技术应用

近年来&#xff0c;人工智能领域已经取得突破性进展&#xff0c;对经济社会各个领域都产生了重大影响&#xff0c;结合了统计学、数据科学和计算机科学的机器学习是人工智能的主流方向之一&#xff0c;目前也在飞快的融入计量经济学研究。表面上机器学习通常使用大数据&#xf…

证件照小程序源码,前后端稳定运行

演示&#xff1a;证寸照制作 运行环境: Linux Nginx PHP >5.6 MySQL>5.6 安装步骤: 1.下载源码上传至你的服务器宝塔面板 2.直接添加站点选择源码目录&#xff0c;新建数据库 3.设置代码执行目录为/web 4.在浏览器中输入你的域名&#xff0c;会提示安装&#xff0c;填写…