2.C语言--链表-头插、头删、尾插、尾删、查找、插入和删除

文章目录

  • 简介
    • 动态顺序表结构体
    • 1.头插功能
    • 2.头删功能
    • 3.尾插功能
    • 4.尾删功能
    • 5.查找功能
    • 6.插入功能
      • 6.1 指定位置之(前)去插入一个节点
      • 6.2 指定位置之(后)去插入一个节点
    • 7.删除功能
      • 7.1 删除指定位置的数据-时间复杂度O(N)
      • 7.2 删除指定位置后一个位置的数据-时间复杂度O(1)
    • 8. 释放链表缓存
    • 9. 打印链表的值
    • 10.此程序共包含3个文件,2个.c文件和1个.h文件
      • 10.1 SList.h文件
      • 10.2 SList.c文件
      • 10.3 test.c文件

简介

	本文主要介绍链表的头插、头删、尾插、尾删、查找、插入和删除,提供全部的.c和.h文件,确保使用者直接复制粘贴到编译器上即可直接运行程序。

动态顺序表结构体

typedef int SLTDateType;typedef struct SListNode
{SLTDateType data;struct SListNode* next;
}SLTNode;

1.头插功能

	思路是将节点的首地址赋值到新申请节点的next中。
/*插入数据-头插*/
void SListPushFront(SLTNode** ppHead, SLTDateType x)
{assert(ppHead != NULL);SLTNode* newNode = CreatListNode(x);newNode->next = *ppHead;*ppHead = newNode;return;
}
	开辟一个新的节点,并将要插入的值放心节点对应的data中。
/*创建节点*/
SLTNode* CreatListNode(SLTDateType x)
{SLTNode* newNode = (SLTNode*)malloc(sizeof(SLTNode));if (NULL == newNode){printf("CreatListNode malloc fail\n");exit(-1);}newNode->data = x;newNode->next = NULL;return newNode;
}

2.头删功能

	思路是将下一个节点的地址赋值到头节点地址上,将当前节点free掉。
/*头删*/
void SListPopFront(SLTNode** ppHead)
{assert(ppHead != NULL);SLTNode* next = (*ppHead)->next;free(*ppHead);*ppHead = next;return;
}

3.尾插功能

	思路是先检查输入*ppHead是否为空,不为空就找到链表的尾节点进行新节点的插入。
/*插入数据-尾插*/
void SListPushBack(SLTNode** ppHead, SLTDateType x)
{assert(ppHead != NULL);/*新结点申请空间*/SLTNode* newNode = CreatListNode(x);if (*ppHead == NULL){*ppHead = newNode;}else{/*找到尾结点*/SLTNode* tail = *ppHead;while (tail->next != NULL){tail = tail->next;}tail->next = newNode;}return;
}

4.尾删功能

	思路是释放节点时,要将下一个节点的地址保存好再释放当前节点。
/*尾删*/
void SListPopBack(SLTNode** ppHead)
{assert(ppHead != NULL);/*如果只有一个节点时,直接释放此节点*/if ((*ppHead)->next == NULL){free(*ppHead);*ppHead = NULL;}else/*存在2个及2个以上节点的处理方式*/{SLTNode* tail = *ppHead;SLTNode* pre = NULL;while (tail->next != NULL){pre = tail;tail = tail->next;}pre->next = NULL;free(tail);tail = NULL;}return;
}

5.查找功能

	思路是遍历,找到节点后返回当前节点的地址,找不到就返回NULL。
/*查找*/
SLTNode* SListFind(SLTNode* pHead, SLTDateType x)
{assert(pHead != NULL);SLTNode* cur = pHead;while (cur){if (cur->data == x){return cur;}else{cur = cur->next;}}return NULL;
}

6.插入功能

6.1 指定位置之(前)去插入一个节点

	此方法是比较笨的方法,为了节约资源应该将数据往指定位置的后边插入。
/*指定位置插入数据-在pos位置之前去插入一个节点--时间复杂度O(N)*/
SLTNode* SListInsert(SLTNode** ppHead, SLTNode* pos, SLTDateType x)
{assert(ppHead != NULL);assert(pos != NULL);SLTNode* newNode = CreatListNode(x);if (*ppHead == pos)/*pos的位置在第一个位置时*/{newNode->next = *ppHead;*ppHead = newNode;}else{/*找到pos位置的前一个位置*/SLTNode* posPrev = *ppHead;while (posPrev->next != pos){posPrev = posPrev->next;}posPrev->next = newNode;newNode->next = pos;}return NULL;
}

6.2 指定位置之(后)去插入一个节点

	此方法是常用的插入方式,时间复杂度是O(1)。
/*指定位置插入数据-在pos位置之后去插入一个节点--时间复杂度O(1)*/
SLTNode* SListInsertAfter(SLTNode* pos, SLTDateType x)
{assert(pos != NULL);SLTNode* newNode = CreatListNode(x);newNode->next = pos->next;pos->next = newNode;return NULL;
}

7.删除功能

7.1 删除指定位置的数据-时间复杂度O(N)

	此方法需要记住当前节点前一个的节点地址,会多耗费时间资源,时间复杂度O(N)。
SLTNode* SListErase(SLTNode** ppHead, SLTNode* pos)
{assert(ppHead != NULL);assert(pos != NULL);/*如果删除的数据是头*/if (*ppHead == pos){SListPopFront(ppHead);}else{SLTNode* prev = *ppHead;while (prev->next != pos)/*找到pos前一个节点*/{prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}return NULL;
}

7.2 删除指定位置后一个位置的数据-时间复杂度O(1)

	此方法需要记住当前节点前一个的节点地址,会多耗费时间资源,时间复杂度O(1)。
/*删除指定位置后一个位置的数据*/
SLTNode* SListEraseAfter(SLTNode* pos)
{assert(pos->next != NULL);SLTNode* next = pos->next;pos->next = next->next;free(next);next = NULL;return NULL;
}

8. 释放链表缓存

	思路将下一个节点的地址先记住,然后释放当前节点。再将保存的地址赋值到当前节点循环释放缓存。
/*释放链表缓存*/
SLTNode* SListDestory(SLTNode** ppHead)
{assert(ppHead != NULL);SLTNode* cur = *ppHead;while (cur){SLTNode* next = cur->next;free(cur);cur = next;}*ppHead = NULL;return NULL;
}

9. 打印链表的值

/*打印链表的值*/
void SListTPrint(SLTNode* pHead)
{SLTNode* cur = pHead;while (cur != NULL){printf("%d->", cur->data);cur = cur->next;}return;
}

10.此程序共包含3个文件,2个.c文件和1个.h文件

10.1 SList.h文件

	文件中包含了函数功能的头文件以及对应的结构体。
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>typedef int SLTDateType;typedef struct SListNode
{SLTDateType data;struct SListNode* next;
}SLTNode;void SListTPrint(SLTNode *pHead);							/*打印链表的值*/
void SListPushBack(SLTNode** ppHead, SLTDateType x);		/*插入数据-尾插*/
void SListPushFront(SLTNode** ppHead, SLTDateType x);		/*插入数据-头插*/void SListPopBack(SLTNode** ppHead);						/*尾删*/
void SListPopFront(SLTNode** ppHead);						/*头删*/SLTNode* SListFind(SLTNode* pHead, SLTDateType x);				    /*查找*/
SLTNode* SListInsert(SLTNode** ppHead, SLTNode* pos, SLTDateType x);/*指定位置插入数据-在pos位置之前去插入一个节点*/
SLTNode* SListInsertAfter(SLTNode* pos, SLTDateType x);				/*指定位置插入数据-在pos位置之后去插入一个节点*/
SLTNode* SListErase(SLTNode** ppHead, SLTNode* pos);				/*删除指定位置的数据*/
SLTNode* SListEraseAfter(SLTNode* pos);								/*删除指定位置后一个位置的数据*/
SLTNode* SListDestory(SLTNode** ppHead);							/*释放链表缓存*/SLTNode* CreatListNode(SLTDateType x);								/*创建一个新的节点*/

10.2 SList.c文件

	文件中包含了功能函数的具体实现方式。
#define _CRT_SECURE_NO_WARNINGS
#include "SList.h"/*插入数据-尾插*/
void SListPushBack(SLTNode** ppHead, SLTDateType x)
{assert(ppHead != NULL);/*新结点申请空间*/SLTNode* newNode = CreatListNode(x);if (*ppHead == NULL){*ppHead = newNode;}else{/*找到尾结点*/SLTNode* tail = *ppHead;while (tail->next != NULL){tail = tail->next;}tail->next = newNode;}return;
}/*插入数据-头插*/
void SListPushFront(SLTNode** ppHead, SLTDateType x)
{assert(ppHead != NULL);SLTNode* newNode = CreatListNode(x);newNode->next = *ppHead;*ppHead = newNode;return;
}/*创建节点*/
SLTNode* CreatListNode(SLTDateType x)
{SLTNode* newNode = (SLTNode*)malloc(sizeof(SLTNode));if (NULL == newNode){printf("CreatListNode malloc fail\n");exit(-1);}newNode->data = x;newNode->next = NULL;return newNode;
}/*尾删*/
void SListPopBack(SLTNode** ppHead)
{assert(ppHead != NULL);/*如果只有一个节点时,直接释放此节点*/if ((*ppHead)->next == NULL){free(*ppHead);*ppHead = NULL;}else/*存在2个及2个以上节点的处理方式*/{SLTNode* tail = *ppHead;SLTNode* pre = NULL;while (tail->next != NULL){pre = tail;tail = tail->next;}pre->next = NULL;free(tail);tail = NULL;}return;
}/*头删*/
void SListPopFront(SLTNode** ppHead)
{assert(ppHead != NULL);SLTNode* next = (*ppHead)->next;free(*ppHead);*ppHead = next;return;
}/*查找*/
SLTNode* SListFind(SLTNode* pHead, SLTDateType x)
{assert(pHead != NULL);SLTNode* cur = pHead;while (cur){if (cur->data == x){return cur;}else{cur = cur->next;}}return NULL;
}/*指定位置插入数据-在pos位置之前去插入一个节点--时间复杂度O(N)*/
SLTNode* SListInsert(SLTNode** ppHead, SLTNode* pos, SLTDateType x)
{assert(ppHead != NULL);assert(pos != NULL);SLTNode* newNode = CreatListNode(x);if (*ppHead == pos)/*pos的位置在第一个位置时*/{newNode->next = *ppHead;*ppHead = newNode;}else{/*找到pos位置的前一个位置*/SLTNode* posPrev = *ppHead;while (posPrev->next != pos){posPrev = posPrev->next;}posPrev->next = newNode;newNode->next = pos;}return NULL;
}/*指定位置插入数据-在pos位置之后去插入一个节点--时间复杂度O(1)*/
SLTNode* SListInsertAfter(SLTNode* pos, SLTDateType x)
{assert(pos != NULL);SLTNode* newNode = CreatListNode(x);newNode->next = pos->next;pos->next = newNode;return NULL;
}/*删除指定位置的数据--时间复杂度O(N)*/
SLTNode* SListErase(SLTNode** ppHead, SLTNode* pos)
{assert(ppHead != NULL);assert(pos != NULL);/*如果删除的数据是头*/if (*ppHead == pos){SListPopFront(ppHead);}else{SLTNode* prev = *ppHead;while (prev->next != pos)/*找到pos前一个节点*/{prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}return NULL;
}/*删除指定位置后一个位置的数据*/
SLTNode* SListEraseAfter(SLTNode* pos)
{assert(pos->next != NULL);SLTNode* next = pos->next;pos->next = next->next;free(next);next = NULL;return NULL;
}/*释放链表缓存*/
SLTNode* SListDestory(SLTNode** ppHead)
{assert(ppHead != NULL);SLTNode* cur = *ppHead;while (cur){SLTNode* next = cur->next;free(cur);cur = next;}*ppHead = NULL;return NULL;
}/*打印链表的值*/
void SListTPrint(SLTNode* pHead)
{SLTNode* cur = pHead;while (cur != NULL){printf("%d->", cur->data);cur = cur->next;}return;
}

10.3 test.c文件

	用来进行相应功能的测试,分别测试尾插、尾删和头插、头删等功能。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include "SList.h"void Test1()
{SLTNode* SList = NULL;/*尾插*/SListPushBack(&SList, 1);SListPushBack(&SList, 2);SListPushBack(&SList, 3);SListPushBack(&SList, 4);/*尾删*/SListPopBack(&SList);/*打印链表*/SListTPrint(SList);printf("NULL\n");return;
}void Test2()
{SLTNode* SList = NULL;/*头插*/SListPushFront(&SList, 1);SListPushFront(&SList, 2);SListPushFront(&SList, 3);/*头删*/SListPopFront(&SList);/*打印*/SListTPrint(SList);printf("NULL");return;
}void Test3()
{SLTNode* SList = NULL;SLTNode* pos = NULL;int i = 1;/*尾插*/SListPushBack(&SList, 1);SListPushBack(&SList, 5);SListPushBack(&SList, 2);SListPushBack(&SList, 3);SListPushBack(&SList, 2);/*查找数字的位置*/pos = SListFind(SList, 2);while (pos)/*查找到数据为2的节点的地址*/{printf("第%d个pos节点的:%p->%d\n", i++, pos->next, pos->data);if (pos->next){pos = SListFind(pos->next, 2);}else/*为空指针时,直接跳出循环*/{break;}}/*改变对应节点位置的数据,将5位置前边的位置添加个20*/pos = SListFind(SList, 5);if (pos)/*在5的位置之前插入20*/{SListInsert(&SList, pos, 20);}pos = SListFind(SList, 5);if (pos)/*在5的位置之后插入100*/{SListInsertAfter(pos, 100);}/*打印*/SListTPrint(SList);printf("NULL");return;
}int main()
{Test1();/*尾插+尾删*///Test2();/*头插+头删*///Test3(); /*指定位置前插入、后插入、寻找指定数据节点的位置*/return 0;
}
	这里代码大家可以自己拷贝到VS编译器中,Test1(),Test2(),Test3(),分别打开注释看一下效果,本人亲测过,可以直接运行出结果的。

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

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

相关文章

配置hikari数据库连接池时多数据源不生效

1.原始配置&#xff0c;改造前&#xff1a; spring:# 配置数据源信息datasource:dynamic:#设置默认的数据源或者数据源组,默认值即为masterprimary: masterstrict: truedatasource:#这里采用了配置文件取值的方式&#xff0c;可以直接替换为数据库连接master:url: jdbc:postgr…

【LLS-Player】音视频帧的回调过程

RtdSinkInterface 实现者用于从SDK获取音视频帧 class RtdSinkInterface {public:virtual ~RtdSinkInterface() = default;virtual void OnAudioFrame(const RtdAudioFrame& fra

电子学会C/C++编程等级考试2023年03月(一级)真题解析

C/C++等级考试(1~8级)全部真题・点这里 第1题:字符长方形 给定一个字符,用它构造一个长为4个字符,宽为3个字符的长方形,可以参考样例输出。 时间限制:1000 内存限制:65536输入 输入只有一行, 包含一个字符。输出 该字符构成的长方形,长4个字符,宽3个字符。样例输入…

如何使用Fiddler进行弱网测试

测试APP、web经常需要用到弱网测试&#xff0c;也就是在信号差、网络慢的情况下进行测试。我们自己平常在使用手机APP时&#xff0c;在地铁、电梯、车库等场景经常会遇到会话中断、超时等情况&#xff0c;这种就属于弱网。 普通的弱网测试可以选择第三方工具对带宽、丢包、延时…

python数据类型之字典、元组

一、字典 1、定义字典 字典是 有序&#xff08;3.6以前无序&#xff09;、键不重复 且 元素只能是键值对的可变的 个 容器。键不重复&#xff0c;重复则会被覆盖 如下定义一个字典 # 使用大括号 {} 来创建空字典 test_dic1 {} # 使用内建函数 dict() 创建字典&#xff1a;…

【华为OD题库-032】数字游戏-java

题目 小明玩一个游戏。系统发1n张牌&#xff0c;每张牌上有一个整数。第一张给小明&#xff0c;后n张按照发牌顺序排成连续的一行。需要小明判断&#xff0c;后n张牌中&#xff0c;是否存在连续的若干张牌&#xff0c;其和可以整除小明手中牌上的数字. 输入描述: 输入数据有多组…

嵌入式基础知识学习:Flash、EEPROM、RAM、ROM

https://blog.csdn.net/y673533511/article/details/87913989 FLASH存储器又称闪存&#xff0c;它结合了ROM和RAM的长处&#xff0c;不仅具备电子可擦出可编程(EEPROM) 的性能&#xff0c;还不会断电丢失数据同时可以快速读取数据 (NVRAM 的优势)&#xff0c;U 盘和MP3 里用的…

[论文笔记]MatchPyramid

引言 又一篇文本匹配论文Text Matching as Image Recognition,论文题目是 文本匹配当成图像识别。 挺有意思的一篇工作,我们来看它是如何实现的。 作者受到卷积神经网络在图像识别中成功应用的启发,其中神经元可以捕获很多复杂的模式,作者提出将文本匹配看作是图像识别任…

DDD落地:从网易新闻APP重构,看DDD的巨大价值

尼恩说在前面 在40岁老架构师 尼恩的读者交流群(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、滴滴、极兔、有赞、希音、百度、网易、美团的面试资格&#xff0c;遇到很多很重要的面试题&#xff1a; 谈谈你的DDD落地经验&#xff1f; 谈谈你对DDD的理解&#x…

GEE:梯度提升树(Gradient Boosting Tree)分类教程(样本制作、特征添加、训练、精度、参数优化、贡献度、统计面积)

作者:CSDN @ _养乐多_ 本文将介绍在Google Earth Engine (GEE)平台上进行梯度提升树(Gradient Boosting Tree)分类的方法和代码,其中包括制作样本点教程(本地、在线和本地在线混合制作样本点,合并样本点等),加入特征变量(各种指数、纹理特征、时间序列特征、物候特征…

OpenStack云计算平台-启动一个实例

目录 一、创建虚拟网络 ​二、创建m1.nano规格的主机 三、生成一个键值对 四、增加安全组规则 ​五、启动一个实例 1、确定实例选项 2、创建实例 3、使用虚拟控制台访问实例 4、验证能否远程访问实例 一、创建虚拟网络 下面的说明和框图使用示例IP 地址范围。你必须依…

Altium Designer学习笔记12

把几个层理解下&#xff1a; layer名称功能说明信息Toplayer信号层铜箔层&#xff0c;电气连接的层Bottomlayer信号层铜箔层&#xff0c;电气连接的层Internal Planes内层连接地和电源上&#xff0c;一般情况下不布线&#xff0c;是由整片铜膜组成的Mechanical 1机械层电路板机…

String 、StringBuffer 和 StringBuilder 的区别?

String 使用 String 声明一个字符串的时候&#xff0c;该字符串会存放在堆中的字符串常量池中。因为在java中所有的String 都是以常量表示&#xff0c;且由 final 修饰&#xff0c;因此在线程池中它的线程是安全的 且 不可变的 。每个 String 在被创建后就不再发生任何变化。 …

mysql按年、季度、月,统计

以下是按年、按季度和按月统计SQL查询语句&#xff1a; 按年统计&#xff1a; SELECTds.checker,YEAR(ds.create_time) AS settleYear,SUM(ds.quantity) AS quantity,SUM(ds.approval_price) AS approvalPrice FROMdata_settle ds WHEREds.delete_flag 0AND ds.approval_sta…

漏洞盒子公益SRC

漏洞盒子公益SRC&#xff0c;小小地记录一下第一个月的成果

数据中台建设方法论

1、数仓的概念和了解--业务的痛点 产生的痛点&#xff1a;数据资产比较模糊、数据的质量比较低、重复建设、代码的耦合性比较强。 2、数据仓库中的常见的模型&#xff1a; 1、心型模型&#xff1a;中间是一张事实表&#xff0c;周围都是维度表。 对于心型模型的主要的特点&a…

面向未来的自动化:拥抱机器人即服务(RaaS)

01. RaaS是什么&#xff1f; 对于希望实现业务流程自动化的公司来说&#xff0c;机器人通常是一笔巨大的资本支出。由于机器人非常昂贵&#xff0c;公司可能需要等待数年才能看到投资回报。正是由于这一现实&#xff0c;许多较小的组织无法投资机器人。 但一些机器人公司正在采…

算法通关村第十二关-青铜挑战字符串

大家好我是苏麟 , 今天带来字符串专题 . 转换成小写字母 描述 : 给你一个字符串 s &#xff0c;将该字符串中的大写字母转换成相同的小写字母&#xff0c;返回新的字符串。 题目 : LeetCode 709.转换成小写字母 : 709. 转换成小写字母 分析 : 这个题可以先遍历整个字符串…

Mybatis和MybatisPlus:数据库操作工具的对比

目录 什么是mybatis 什么是mybatisplus MyBatis-Plus&#xff1a;为简化数据库操作而生的强大工具 一、MyBatis-Plus的背景和概述 二、MyBatis-Plus的主要特点 三、如何使用MyBatis-Plus mybatis-Plus的优势 什么是Hibernate Hibernate&#xff1a;Java开发者的数据持久…

光谱图像超分 Benchmark

光谱图像超分 Benchmark 文章目录 光谱图像超分 Benchmark0. pioneer工作及综述基于深度学习的高光谱多光谱融合&#xff08;updating&#xff09;1. 空间光谱图像超分 &#xff08;to be updated&#xff09;2. 高分辨率多光谱图像超分&#xff08;to be updated&#xff09;3…