考研数据结构单链表的增删改查看这一篇就够了

目录

一. 单链表的特点

1.1 解引用拓展 🤖

二. 单链表的操作

2.1不带头节点的操作

2.1.1 打印 

2.1.1.1 创建结点

2.1.2 尾插(需要二级指针)

注意形参的值不改变实参:(精髓部分)

2.1.3 头插

2.1.4 尾删

2.1.5 头删

2.1.6 在pos前插入

2.1.7 删除pos位置 


一. 单链表的特点

单链表的结点是随机的不是逻辑上相邻即物理上相邻的。用指针指向下一个节点的地址。

1.1 解引用拓展 🤖

解引用有两种,* ->

*p的意思是:是取p所指向内存的值,取多少大小的值,取决于结构体前的数据类型,如int                         取四个字节,char取一个字节。

p->的意思是: 结构体用->,取决于->后面是什么值,如果是->val则取data域的值,->next则                       取下个结点的地址。相当于(*p).next

 

二. 单链表的操作

单链表分为带头结点和不带头结点 ☆*: .。. o(≧▽≦)o .。.:*☆

2.1不带头节点的操作

2.1.1 打印 

打印不用二级指针的原因是:打印不用改变外部结构体指针,只用遍历打印就好了,当要改变结构体指针就要用二级指针。

void SLTPrint(SLNode* phead)
{
	SLNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->val);
		cur = cur->next;
	}
	printf("NULL\n");
}
2.1.1.1 创建结点
SLNode* CreateNode(SLNDataType x)
{
	SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

	newnode->val = x;
	newnode->next = NULL;
	return newnode;
}

2.1.2 尾插(需要二级指针)

void SLTPushBack(SLNode** pphead, SLNDataType x)
{
	SLNode* newnode = CreateNode(x);

	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		// 找尾
		SLNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}

		tail->next = newnode;
	}
}

 

注意形参的值不改变实参:(精髓部分)

接下来是很多人都迷迷糊糊搞不懂的地方。

当前函数定义的可以直接修改,不是当前当前函数定义的,无论是外部函数,还是malloc出来的空间,访问时都要用指针去通过地址修改。全局变量可以直接修改。

形参不不能改变实参的,要传实参的地址才能改变形参。

想用形参pphead改变外部指针phead(实参) ,先将实参的地址&plist,传给实参pphead,这时pphead代表的是plist地址(&plist),*pphead解引用所以*pphead代表是plist,这里是要改变SNode*,所以要node**。这里是要修改结构体的指针plist,所以是需要结构体指针的地址&plist传给*pphead。

如果要改变外部定义的结构指针SLNode*,要用二级指针SLNode**。

如果要改变外部定义的结构体Node,就要一级指针Node*。

2.1.3 头插

void SLTPushFront(SLNode** pphead, SLNDataType x)
{
	SLNode* newnode = CreateNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

2.1.4 尾删

删后n-1个不需要二级指针,直接free();

但是只有一个空间的时候,删掉,plist就成了没有指向空间的野指针,所以需要将plist置空,需要改变结构体指针。 

 

void SLTPopBack(SLNode** pphead)
{
	// 温柔的检查
	//if (*pphead == NULL)
	//	return;

	// 空
	assert(*pphead);

	// 1、一个节点
	// 2、一个以上节点
	if ((*pphead)->next == NULL)
	{
		free(*pphead);
		*pphead = NULL;
	}
	else
	{
		// 找尾
		/*SLNode* prev = NULL;
		SLNode* tail = *pphead;
		while (tail->next != NULL)
		{
			prev = tail;
			tail = tail->next;
		}

		free(tail);
		tail = NULL;

		prev->next = NULL;*/

		SLNode* tail = *pphead;
		while (tail->next->next != NULL)
		{
			tail = tail->next;
		}

		free(tail->next);
		tail->next = NULL;
	}
}

 

2.1.5 头删

void SLPopFront(SLNode** pphead) {

	assert(pphead);
	if ((*pphead)== NULL) {
		free(*pphead);
		*pphead= NULL;
	}
	else {
		/**pphead = (*pphead)->next;
		free(*pphead);*/
		SLNode* tmp = *pphead;
		*pphead = (*pphead)->next;
		free(tmp);


	}

}

 

2.1.6 在pos前插入

2.1.7 删除pos位置 

不带头结点的完整代码 

//头文件SList.h
#pragma once
#include<stdio.h>
#include<stdlib.h>

typedef int SLDataType;
typedef struct SListNode {

	SLDataType val;
	struct SListNode* next;

}SLNode;
void SLPrint(SLNode* phead);
void SLPushBack(SLNode** pphead, SLDataType x);
void SLPopBack(SLNode** pphead);
void SLPushFront(SLNode** pphead, SLDataType x);
void SLPopFront(SLNode** pphead);

//SList.c
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include"SList.h"
#include<assert.h>
//打印
void SLPrint(SLNode* phead) {

	assert(phead);
	while (phead!= NULL) {
		printf("%d->", phead->val);
		phead = phead->next;
	}
	printf("NULL\n");
}
//创建新节点

SLNode* CreateNode(SLDataType x) {

	SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
	while (newnode == NULL) {
		perror("malloc fail");
		exit(-1);
	}
	newnode->val = x;
	newnode->next = NULL;
	return newnode;

}

//尾插
void SLPushBack(SLNode** pphead, SLDataType x) {
	SLNode* newnode = CreateNode(x);		//调用函数,实参没有数据类型
	if (*pphead == NULL) {
		*pphead = newnode;
	}
	else {
	
		SLNode* tail = *pphead;
		while (tail->next != NULL) {
			tail = tail->next;
		}
		newnode->next = NULL;
		tail->next = newnode;
	}

}
//尾删
void SLPopBack(SLNode** pphead) {

	assert(*pphead);
	if ((*pphead)->next == NULL) {
		free(*pphead);
		*pphead = NULL;
	}
	else {
		SLNode* pre = NULL;
		SLNode* tail = *pphead;
		while (tail->next != NULL) {
			pre = tail;
			tail = tail->next;
		}
		free(tail);
		tail = NULL;
		pre->next = NULL;

	}

}
//头插
void SLPushFront(SLNode** pphead, SLDataType x) {
	SLNode* newnode = CreateNode(x);
	/*if (*pphead == NULL) {
		*pphead = newnode;
	}*/    //可以不要
	newnode->next = *pphead;
	*pphead= newnode;
}
//头删
void SLPopFront(SLNode** pphead) {

	assert(pphead);
	if ((*pphead)== NULL) {
		free(*pphead);
		*pphead= NULL;
	}
	else {
		/**pphead = (*pphead)->next;
		free(*pphead);*/
		SLNode* tmp = *pphead;
		*pphead = (*pphead)->next;
		free(tmp);


	}

}


//Test.c 文件
#define _CRT_SECURE_NO_WARNINGS
#include"SList.h"

void Test1() {
	SLNode* splist=NULL;
	SLPushBack(&splist, 1);
	SLPushBack(&splist, 2);
	SLPushBack(&splist, 3);
	SLPushBack(&splist, 4);
	SLPrint(splist);
	SLPopBack(&splist);
	SLPopBack(&splist);
	SLPrint(splist);
	SLPushFront(&splist, 1);
	SLPushFront(&splist, 2);
	SLPushFront(&splist, 3);
	SLPushFront(&splist, 4);
	SLPrint(splist);
	SLPopFront(&splist);
	SLPopFront(&splist);
	SLPrint(splist);
}
int main() {
	Test1();
	return 0;

}

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

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

相关文章

java项目之服装定制系统(ssm框架)

项目简介 服装定制系统实现了以下功能&#xff1a; 管理员&#xff1a;管理员使用本系统涉到的功能主要有首页、个人中心、用户管理、服装类型管理、服装信息管理、服装定制管理、留言反馈、系统管理等功能。用户&#xff1a;用户进入系统可以对首页、个人中心、服装定制管理…

测试开源加解密库NETCore.Encrypt中的RSA加解密函数

微信公众号“dotNET跨平台”的文章《开箱即用&#xff0c;.NET最全的加解密开源库》介绍了开源通用工具库NETCore.Encrypt&#xff0c;其支持对称加密算法、非对称加密算法、摘要算法等多种常用算法&#xff0c;使用方便&#xff0c;不过目前仅支持.net core。本文主要测试调用…

Python每日练习:20个常用代码,初学者也可以自己实现!

文章目录 前言20个代码1.重复元素判定2.字符元素组成判定3.内存占用4.字节占用5.打印 N 次字符串6.大写第一个字母7.分块8.压缩9.解包10.链式对比11.逗号连接12.元音统计13.首字母小写14.展开列表15.列表的差16.通过函数取差17.链式函数调用18.检查重复项19.合并两个字典20.将两…

jmeter接口自动化测试工具在企业开展实际的操作

在企业使用jmeter开展实际的接口自动化测试工具&#xff0c;建议按如下操作流程&#xff0c; 可以使整个接口测试过程更规范&#xff0c;更有效。 接口自动化的流程&#xff1a; 1、获取到接口文档&#xff1a;swagger、word、excel ... 2、熟悉接口文档然后设计测试用例&am…

推荐这款机器学习的特征筛选神器!

大家好&#xff0c;特征选择是机器学习建模流程中最重要的步骤之一&#xff0c;特征选择的好坏直接决定着模型效果的上限&#xff0c;好的特征组合甚至比模型算法更重要。除了模型效果外&#xff0c;特征选择还有以下几点好处&#xff1a; 提高模型性能并降低复杂性&#xff08…

不可否认程序员的护城河已经越来越浅了

文章目录 那些在冲击程序员护城河低代码/无代码开发平台自动化测试和部署工具AI辅助开发工具在线学习和教育平台 面临冲击&#xff0c;程序员应该怎么做深入专业知识&#xff1a;不断学习全栈技能开发解决问题的能力建立人际网络管理和领导技能 推荐阅读 技术和应用的不断发展对…

Springboot通过ObjectMapper(节点树)解析JSON

1、ObjectMapper通过节点树的方式解析JSON字符串 1.1、通过节点直接获取属性值 1.1.1、测试代码 node.get("order_id")&#xff1a;直接获取JSON中属性对应的值 Test public void parseJson() throws Exception{//创建json字符串&#xff0c;模拟从外界接收的订…

第二章 03Java基础-IDEA相关叙述

文章目录 前言一、IDEA概述二、IDEA下载和安装三、IDEA项目结构介绍四、IDEA的项目和模块操作总结前言 今天我们学习Java基础,IDEA下载以及相关配置和基础使用方法 一、IDEA概述 1.IDEA全称IntelliJ IDEA,是用于Java语言开发的集成工具,是业界公认的目前用于Java程序开发最…

Leetcode Hot100之六:42.接雨水

题目 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 提示&#xff1a; n height.length 1 < n < 2 * 10^4 0 < height[i] < 10^5 思路 暴力循环&#xff1a; 原本的思路是左边界i从左到…

阿里云从公网IP转为弹性公网IP,同时绑定多个IP教程

先将云服务器ECS 转为弹性IP 购买新的弹性辅助网卡 购买弹性公网iP 购买之后选择绑定资源选择第二步购买的网卡 进入ECS 终端 ,输入 ip address可以查看到eth1 的对应mac 地址 终端输入 vi /etc/sysconfig/network-scripts/ifcfg-eth1保存一下信息 DEVICEeth1 #表示新配置…

RK3568平台 查看内存的基本命令

一.free命令 free命令显示系统使用和空闲的内存情况&#xff0c;包括物理内存、交互区内存(swap)和内核缓冲区内存。共享内存将被忽略。 Mem 行(第二行)是内存的使用情况。 Swap 行(第三行)是交换空间的使用情况。 total 列显示系统总的可用物理内存和交换空间大小。 used 列显…

《Redis实战》笔记

文章目录 1.字符串命令2.列表命令3.集合命令4.散列命令5.有序集合命令6.发布订阅命令7.其他命令8.redis事务9.键的过期时间10.redis的持久化 1.字符串命令 2.列表命令 3.集合命令 4.散列命令 5.有序集合命令 6.发布订阅命令 7.其他命令 8.redis事务 5个命令&#xff1a;WATCH …

Spring IoC注解式开发

2023.11.11 注解的存在主要是为了简化XML的配置。Spring6倡导全注解开发。 负责声明Bean的注解&#xff0c;常见的包括四个&#xff1a; ComponentControllerServiceRepository 通过源码可以发现&#xff0c;Controller、Service、Repository这三个注解都是Component注解的别名…

开发模型(瀑布、螺旋、scrum) 和 测试模型(V、W)、增量和迭代、敏捷(思想)及敏捷开发 scrum

&#x1f9f8;欢迎来到dream_ready的博客&#xff0c;&#x1f4dc;相信您对这篇博客也感兴趣o (ˉ▽ˉ&#xff1b;) 震惊&#xff01;测试人员对BUG的全方位解析&#xff0c;测试的执行和BUG管理&#xff01; 原来测试人员遇到BUG是这样返回给开发的&#xff01;什么是BUG&am…

文件管理技巧:按文件容量大小分类,自动移动至目标文件夹的方法

按文件容量大小分类可以帮助快速识别和筛选出不同大小的文件。这样做有很多好处。首先&#xff0c;可以轻松地查找和访问特定大小的文件&#xff0c;提高工作效率。其次&#xff0c;通过将不同大小的文件分类&#xff0c;可以更好地了解和掌控文件的使用情况&#xff0c;避免存…

从windows iso文件中提取install.wim

1、首先从微软官方下载需要的windows镜像 https://www.microsoft.com/zh-cn/software-download/windows10/ 2、在下载的iso文件右键&#xff0c;打开压缩包&#xff0c;在sources文件夹下&#xff0c;应该就可以看到install.wim了。但似乎在最新的win10版本&#xff0c;微软采…

redis: 记录一次线上redis内存占用过大问题解决过程

引言 记录一次线上redis占用过大的排查过程&#xff0c;供后续参考 问题背景 测试同事突然反馈测试环境的web系统无法登陆&#xff0c;同时发现其他子系统也存在各类使用问题 排查过程 1、因为首先反馈的是测试环境系统无法登陆&#xff0c;于是首先去查看了登陆功能的报错…

jupyter notebook添加markdown目录

jupyternotebook添加markdown目录 1. 安装python包2. 安装JavaScript和CSS文件3. 启用扩展4. 设置markdown选项 1. 安装python包 官方安装 使用pip pip install jupyter_contrib_nbextensions # 或者 pip install https://github.com/ipython-contrib/jupyter_contrib_nbext…

【Spring】SpringBoot日志

SpringBoot日志 日志概述日志使用打印日志获取日志对象使用日志对象打印日志日志框架介绍门面模式SLF4J框架介绍(simple logging facade for java) 日志格式说明日志级别日志级别的分类日志级别的使用 日志配置配置日志级别日志持久化配置日志文件的路径和文件名配置日志文件的…

若依如何进行页面路由跳转,路由跳转时如何携带参数(超详细图文教程)

我们经常会有这样需求&#xff0c;当我们在一个页面时&#xff0c;想要跳转到另一个页面&#xff0c;但是跳转的同时还需要携带参数。那么这种情况在若依系统中该如何做呢&#xff0c;下面我们来说一下。 文章目录 问题提出&#xff1a;一、创建目标页面的路由(也就是图2的路由…