2024.11.29(单链表)
思维导图


声明文件
#ifndef __LINKLIST_H__
#define __LINKLIST_H__#include <myhead.h>typedef char datatype; //数据元素类型
//定义节点类型
typedef struct Node
{union{int len; //头节点数据域datatype data; //普通节点数据域};struct Node *next; //指针域}Node ,*Node_ptr;//创建链表
Node_ptr list_create();//链表判空操作
int list_empty(Node_ptr L);//定义申请节点封装数据函数
static Node_ptr node_apply(datatype e);//单向链表头插
int list_insert_head(Node_ptr L,datatype e);//单向链表的按位置查找返回节点
Node_ptr list_find_node(Node_ptr L,int pos);//单链表遍历
void list_show(Node_ptr L);//单向链表任意位置插入
int list_insert_anypos(Node_ptr L,int pos,datatype e);//单链表头删
int list_head_delete(Node_ptr L);//任意位置删除
int list_delete_anywhere(Node_ptr L,int pos);//按位置进行修改
int list_update_pos(Node_ptr L,int pos,datatype e);//单向链表翻转
int list_reverse(Node_ptr L);//销毁单链表
void list_destroy(Node_ptr L);//单链表尾插
int list_insert_tail(Node_ptr L,datatype e);//单链表的尾删
int list_delete_tail(Node_ptr L);//单链表按值查找返回位置
int list_find_value(Node_ptr L,int e);//单链表按值修改
int list_edit_value(Node_ptr L,int w,datatype e);//单链表的排序
int list_sort(Node_ptr L);//单链表的去重
int list_duplicate_removal(Node_ptr L);//清空单链表
int list_clear(Node_ptr L);//返回单链表的长度
int list_len(Node_ptr L);#endif
测试文件
#include "linklist.h"
int main(int argc, const char *argv[])
{//调用链表创建函数Node_ptr L = list_create();if(NULL == L){return -1;}//调用头插函数list_insert_head(L,'A');list_insert_head(L,'B');list_insert_head(L,'C');list_insert_head(L,'D');list_insert_head(L,'A');list_insert_head(L,'B');list_insert_head(L,'C');list_insert_head(L,'D');//调用遍历函数list_show(L);/* //调用任意插入函数list_insert_anypos(L,1,'u');list_show(L);list_insert_anypos(L,L->len+1,'P');list_show(L);list_insert_anypos(L,3,'9');list_show(L);//调用头删函数list_head_delete(L);list_show(L);//调用任意位置删除list_delete_anywhere(L,3);list_show(L);list_delete_anywhere(L,2);list_show(L);//调用按位置修改函数list_update_pos(L,2,'H');list_show(L);//调用翻转函数list_reverse(L);list_show(L);//调用尾插法list_insert_tail(L,'e');list_show(L);//调用尾删除list_delete_tail(L);list_show(L);//调用按值查找函数int a = list_find_value(L,'H');printf("位置为%d\n",a);//调用单链表按值修改list_edit_value(L,'H','A'); list_show(L);//调用排序函数list_sort(L);list_show(L);//调用去重函数list_duplicate_removal(L);list_show(L);printf("%d",L->len);//调用清空函数list_clear(L);list_show(L);
printf("%d",L->len);//调用销毁函数list_destroy(L);L = NULL;list_show(L);*/printf("链表长度为:%d\n",list_len(L));return 0;
}
功能函数文件
#include "linklist.h"
//创建链表
Node_ptr list_create()
{//在堆区申请一个头结点的空间Node_ptr L = (Node_ptr)malloc(sizeof(Node));if(L == NULL){printf("创建失败\n");return NULL;}//程序执行至此,一个头结点就申请成功//有了头结点就有了一条2链表//初始化操作L->len = 0; //表示链表长度为0L->next = NULL; //防止野指针printf("链表创建成功\n");return L;}//链表判空操作
//如果链表为空,返回1,非空返回0
int list_empty(Node_ptr L)
{//判断逻辑if(NULL == L){printf("链表不合法\n");return -1;}return 0;}//定义申请节点封装数据函数
static Node_ptr node_apply(datatype e)
{//在堆区申请一个节点的空间Node_ptr P = (Node_ptr)malloc(sizeof(Node));if(NULL == P){printf("节点申请失败\n");return NULL;}//将数据封装进节点的数据域P->data = e;P->next = NULL; //防止野指针return P; //将封装好的节点地址返回
}//单向链表头插
int list_insert_head(Node_ptr L,datatype e)
{//判断逻辑if(NULL == L){printf("链表不合法\n");return -1;}//申请节点封装数据Node_ptr P = node_apply(e);if(NULL ==P ){return -1;}//程序执行至此,表示节点申请成功//头插逻辑P->next = L->next;L->next = P;//表长变化L->len++;printf("插入成功\n");}//单向链表的按位置查找返回节点
Node_ptr list_find_node(Node_ptr L,int pos)
{//判断逻辑、if( NULL == L||pos <0||pos>L->len){printf("查找失败\n");return NULL;}//查找逻辑Node_ptr Q = L; //定义遍历指针for(int i=0;i<pos;i++){Q = Q->next; //将指针偏移到下一个节点位置}//返回节点return Q;}//单链表遍历
void list_show(Node_ptr L)
{//判断逻辑if(list_empty(L)){printf("遍历失败\n");return ;}/*遍历所有节点printf("链表中的元素分别是:");for(int i=1;i<L->len;i++){Node_ptr Q = list_find_node(L,i); //找到第i个节点printf("%c\t",Q->data);}*/printf("链表中的元素分别是:");Node_ptr Q = L->next; //定义遍历指针从第一个节点出发/*for(int i=0;i<L->len;i++){Q = Q->next;printf("%c\t",Q->data);}*/while(Q){//当前节点不为空,输出数据域printf("%c\t",Q->data);Q = Q->next; //继续遍历下一个节点}printf("输出完成\n");
}//单向链表任意位置插入
int list_insert_anypos(Node_ptr L,int pos,datatype e)
{//判断逻辑if(pos>L->len+1||pos<1||NULL == L){printf("插入失败\n");return -1;}//判断逻辑//找到要插入位置的前一个节点Node_ptr Q = list_find_node(L,pos-1);//插入逻辑Node_ptr W = node_apply(e);if(NULL == W){return -1;}W->next = Q->next;Q->next = W;//表长变化L->len++;printf("插入成功\n");
}//单链表头删
int list_head_delete(Node_ptr L)
{//判断逻辑if(NULL == L||list_empty(L)){printf("删除失败\n");return -1;}Node_ptr Q = L->next;L->next = Q->next;free(Q);Q = NULL;//表长变化L->len--;printf("删除成功\n");return 0;
}//任意位置删除
int list_delete_anywhere(Node_ptr L,int pos)
{//判断逻辑if(NULL==L||list_empty(L)||pos<1||pos>L->len){printf("删除失败\n");return -1;}//删除逻辑Node_ptr Q = list_find_node(L,pos-1); //找到前驱Node_ptr W = Q->next; //标记要删除的节点Q->next = W->next; //孤立要删除的节点free(W); //释放要删除的节点W = NULL;//表长变化L->len--;printf("删除成功\n");return 0;
}//按位置进行修改
int list_update_pos(Node_ptr L,int pos,datatype e)
{//判断逻辑 if(NULL==L||list_empty(L)||pos<1||pos>L->len){printf("删除失败\n");return -1;}//查找指定节点Node_ptr Q = list_find_node(L,pos-1); //找到前驱//进行修改Q->data = e;printf("修改成功\n");return 0;
}//单向链表翻转
int list_reverse(Node_ptr L)
{//判断逻辑 if(NULL==L||list_empty(L)||L->len == 1){printf("翻转失败\n");return -1;}//翻转逻辑Node_ptr H = L->next; //用头指针托管链表L->next = NULL; //清空当前链表while(H!=NULL){Node_ptr Q = H; //挖墙脚H= H->next; //管理下一位//以头插法的形式将Q插入到L中Q->next = L->next;L->next = Q;}printf("翻转成功\n");return 0;
}//销毁单链表
void list_destroy(Node_ptr L)
{//判断逻辑if(NULL == L||L->next == NULL){printf("销毁失败\n");return ;}Node_ptr Q = L->next;while(Q!=NULL){Node_ptr temp = Q;Q = Q->next;free(temp);}L->next = NULL;printf("销毁成功\n");/*//释放逻辑//将所有普通节点释放while(!list_empty(L)){//调用头删除函数list_head_delete(L);}//释放头节点free(L);L = NULL;printf("销毁成功\n");*/
}//单链表尾插
int list_insert_tail(Node_ptr L,datatype e)
{//判断逻辑if(NULL == L){printf("单链表不合法\n");return -1;}//插入逻辑Node_ptr Q = list_find_node(L,L->len);Node_ptr W = node_apply(e);Q->next = W;//长度变化L->len++;printf("添加成功\n");return 0;
}//单链表的尾删
int list_delete_tail(Node_ptr L)
{if(NULL == L||L->len<1){printf("删除失败\n");return -1;}//删除逻辑Node_ptr Q = list_find_node(L,L->len-1);Node_ptr W = Q->next;Q->next = NULL;free(W);W = NULL;//长度变化L->len--;printf("删除成功\n");return 0;}//单链表按值查找返回位置
int list_find_value(Node_ptr L,int e)
{//判断逻辑if(NULL == L||list_empty(L)){printf("查找失败\n");return -1;}//查找逻辑Node_ptr Q = L->next;for(int i=0;i<L->len;i++){if(Q->data == e){printf("查找成功\n");return i+1;}Q = Q->next;}printf("未查找到该值\n");return 0;
}//单链表按值修改
int list_edit_value(Node_ptr L,int w,datatype e)
{//判断逻辑if(NULL == L||list_empty(L)){printf("查找失败\n");return -1;}//修改逻辑int flag = 0; //检测是否修改Node_ptr Q = L->next;for(int i=0;i<L->len;i++){if(Q->data == w){flag = 1;Q->data = e;}Q = Q->next;}if(flag == 0){printf("未查找到该值\n");return 0;}else{printf("修改成功\n");return 0;}}//单链表的排序
int list_sort(Node_ptr L)
{if(NULL == L||list_empty(L)){printf("排序失败\n");return -1;}//排序逻辑Node_ptr Q = NULL;Node_ptr T = NULL;Node_ptr W = NULL;//冒泡排序for(int i=1;i<L->len;i++){Q = L;T = Q->next;W = T->next;for(int j=0;j<L->len-i;j++){//升序if(T->data > W->data){T->next = W->next;//链接后面节点W->next = Q->next;Q->next = W;//便于下次交换Q=Q->next;//p已经被交换到后面W = T->next;}else{//不满足条件继续后移比较Q = Q->next;T = T->next;W = W->next;}}}return 0;
}//单链表的去重
/*
int list_duplicate_removal(Node_ptr L)
{if(NULL == L||L->len<2||list_empty(L)){printf("去重失败\n");return -1;}//去重逻辑Node_ptr Q = L;Node_ptr T = NULL;Node_ptr W = NULL;//外层循环避免多个重复元素,控制趟数
for(int i=1;i<L->len-1;i++)//for(int i=1;Q!=NULL||Q->next !=NULL;i++){T = Q;//内层循环结束,重新指向W = Q->next;for(int j=0;j<L->len-2-i;j++)//for(int j=0;W!=NULL;j++){if(T->data == W->data){Node_ptr Temp = W->next;free(W);//删除重复部分,释放内存T->next = Temp;//长度变化L->len--;printf("%d\n",L->len);}else{W = W->next; //移动到下一个节点}}Q = Q->next;//内层循环结束向前移动一次}printf("去重成功\n");return 0;
}
*/
int list_duplicate_removal(Node_ptr L) {if (NULL == L || L->len < 2 || list_empty(L)) {printf("去重失败\n");return -1;}Node_ptr T, W, prev;int i;// 遍历链表,T为当前节点,W为T的下一个节点for (T = L->next, prev = L; T != NULL && T->next != NULL; ) {W = T->next; // W指向T的下一个节点// 检查W是否与T之后的节点有重复while (W != NULL) {if (T->data == W->data) {Node_ptr temp = W->next; // 保存W的下一个节点prev->next = temp; // 跳过W节点free(W); // 释放W节点的内存L->len--; // 更新链表长度W = temp; // W更新为新的节点,继续检查} else {prev = W; // 更新prev为W,W移动到下一个节点W = W->next;}}T = T->next; // T移动到下一个节点}printf("去重成功\n");return 0;
}//清空单链表
int list_clear(Node_ptr L)
{if(NULL == L||list_empty(L)){printf("单链表不存在或为空\n");return -1;}while(L->next!=NULL){list_head_delete(L);}printf("清空完成\n");return 0;
}
//返回单链表的长度
int list_len(Node_ptr L)
{if(NULL == L){printf("该链表不存在\n");return -1;}Node_ptr Q = L->next;int num = 0;while(Q){Q = Q->next;num++;}return num;
}
相关文章:
2024.11.29(单链表)
思维导图 声明文件 #ifndef __LINKLIST_H__ #define __LINKLIST_H__#include <myhead.h>typedef char datatype; //数据元素类型 //定义节点类型 typedef struct Node {union{int len; //头节点数据域datatype data; //普通节点数据域};struct Node *next; //指针域…...
基于深度学习和卷积神经网络的乳腺癌影像自动化诊断系统(PyQt5界面+数据集+训练代码)
乳腺癌是全球女性中最常见的恶性肿瘤之一,早期准确诊断对于提高生存率具有至关重要的意义。传统的乳腺癌诊断方法依赖于放射科医生的经验,然而,由于影像分析的复杂性和人类判断的局限性,准确率和一致性仍存在挑战。近年来…...
opengl 三角形
最后效果: OpenGL version: 4.1 Metal 不知道为啥必须使用VAO 才行。 #include <glad/glad.h> #include <GLFW/glfw3.h>#include <iostream> #include <vector>void framebuffer_size_callback(GLFWwindow *window, int width, int heigh…...
23种设计模式-抽象工厂(Abstract Factory)设计模式
文章目录 一.什么是抽象工厂设计模式?二.抽象工厂模式的特点三.抽象工厂模式的结构四.抽象工厂模式的优缺点五.抽象工厂模式的 C 实现六.抽象工厂模式的 Java 实现七.代码解析八.总结 类图: 抽象工厂设计模式类图 一.什么是抽象工厂设计模式?…...
手机上怎么拍证件照,操作简单且尺寸颜色标准的方法
在数字化时代,手机已成为我们日常生活中不可或缺的一部分。它不仅是通讯工具,更是我们拍摄证件照的便捷利器。然而,目前证件照制作工具鱼龙混杂,很多打着免费名号的拍照软件背后却存在着泄漏用户信息、照片制作不规范导致无法使用…...
IDEA报错: java: JPS incremental annotation processing is disabled 解决
起因 换了个电脑打开了之前某个老项目IDEA启动springcloud其中某个服务直接报错,信息如下 java: JPS incremental annotation processing is disabled. Compilation results on partial recompilation may be inaccurate. Use build process “jps.track.ap.depen…...
OCR实现微信截图改名
pip install paddlepaddle -i https://pypi.tuna.tsinghua.edu.cn/simple/ ──(Sat,Nov30)─┘ pip install shapely -i https://pypi.tuna.tsinghua.edu.cn/simple/ pip install paddleo…...
第一届“吾杯”网络安全技能大赛 Writeup
战队信息 战队名称:在你眼中我是誰,你想我代替誰? 战队排名:13 Misc Sign Hex 转 Str,即可得到flag。 原神启动! 不好评价,stegsolve 秒了: WuCup{7c16e21c-31c2-439e-a814-b…...
再谈Java中的String类型是否相同的判断方法
目录 第一部分 代码展示 画图展示 第二部分 代码展示 画图展示 第一部分 代码展示 画图展示 第二部分 代码展示 画图展示...
<一>51单片机环境
目录 1,51单片机开发语言是C,环境keil 1.1,工程创建 1.2用什么把代码放进单片机里面 2,初识代码 1,51单片机开发语言是C,环境keil 1.1,工程创建 1. 创建项目工程文件夹,可以当作模板Template 2. 创建文件,取名main.c 3,编译,选择输出文…...
【0x0001】HCI_Set_Event_Mask详解
目录 一、命令概述 二、命令格式 三、命令参数说明 四、返回参数说明 五、命令执行流程 5.1. 主机准备阶段 5.2. 命令发送阶段 5.3. 控制器接收与处理阶段 5.4. 事件过滤与反馈阶段 5.5. 主机处理(主机端) 5.6. 示例代码 六、命令应用场景 …...
第三方Express 路由和路由中间件
文章目录 1、Express 应用使用回调函数的参数: request 和 response 对象来处理请求和响应的数据。2、Express路由1.路由方法2.路由路径3.路由处理程序 3. 模块化路由4. Express中间件1.中间件简介2.中间件分类3.自定义中间件 1、Express 应用使用回调函数的参数&am…...
七、Python —— 元组、集合和字典
文章目录 一、元组1.1、元组的初始化1.2、元组的解包1.3、元组的比较运算1.4、元组的其他操作 二、集合 set2.1、集合的初始化2.2、集合的常用操作2.3、使用 for 循环遍历集合 三、字典 map3.1、字典的初始化3.2、字典的常用操作3.3、使用 for 循环遍历字典 四、补充 一、元组 …...
Aes加解密
加解密概念 加密AES加密填充模式加密模式示例 加密 通过一系列计算将明文转换成一个密文。 加密和解密的对象通常是字节数组(有的语言动态数组类比切片) 加密后的数据,可能有很多是不可读字符。通常会将其转换为可见的字符串。 直接将字节…...
【时时三省】Tessy 故障入侵 使用教程
目录 1,故障入侵 介绍 故障入侵适用场景: 打故障入侵的方法和选项介绍: 2,打单个函数的故障入侵 3,打整体用例的故障入侵 4,一个函数打多个故障入侵 山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 1,故障入侵 介绍 故障入侵适用场景: 故障入侵 …...
.NET 9 AOT的突破 - 支持老旧Win7与XP环境
引言 随着技术的不断进步,微软的.NET 框架在每次迭代中都带来了令人惊喜的新特性。在.NET 9 版本中,一个特别引人注目的亮点是 AOT( Ahead-of-Time)支持,它允许开发人员将应用程序在编译阶段就优化为能够在老旧的 Win…...
CondaValueError: Malformed version string ‘~‘: invalid character(s).
问题描述:在window下使用conda安装任何包都会报错。报错信息是CondaValueError: Malformed version string ~: invalid character(s). 解决办法:把.condarc文件的源地址删除(八成是源地址访问不了了),只保存默认的&am…...
01-Ubuntu24.04LTS上安装PGSQL
目录 一、准备工作 1.1、系统要求 1.2 、更新 Ubuntu 系统 1.3 、安装依赖 1.4 、添加 PostgreSQL 16 软件源 二、安装 PostgreSQL 16 数据库 三、管理 PostgreSQL 服务 四、PostgreSQL 管理操作 4.1 、访问 Postgres 超级用户账户 4.2 、创建数据库并设置管理权限 4…...
Esp32使用micropython基于espnow实现语音对讲机
ESP-NOW协议介绍 ESP-NOW 是乐鑫自主研发的无连接通信协议,具有短数据包传输功能。该协议使多个设备能够以简单的方式相互通信。ESP-NOW 支持以下功能: 加密和未加密的单播通信; 混合加密和未加密的对等设备; 最多可携带 250 字节 的有效载荷; 发送回调功能,可以设置用于…...
Docker 容器隔离关键技术:SELinux
Docker 容器隔离关键技术:SELinux SELinux(Security-Enhanced Linux) 是 Linux 内核中的一项安全机制,用于实现强制访问控制(MAC)。Docker 利用了 SELinux 来增强容器的隔离性,通过对文件、进程…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
Django RBAC项目后端实战 - 03 DRF权限控制实现
项目背景 在上一篇文章中,我们完成了JWT认证系统的集成。本篇文章将实现基于Redis的RBAC权限控制系统,为系统提供细粒度的权限控制。 开发目标 实现基于Redis的权限缓存机制开发DRF权限控制类实现权限管理API配置权限白名单 前置配置 在开始开发权限…...
第2课 SiC MOSFET与 Si IGBT 静态特性对比
2.1 输出特性对比 2.2 转移特性对比 2.1 输出特性对比 器件的输出特性描述了当温度和栅源电压(栅射电压)为某一具体数值时,漏极电流(集电极电流...
论文笔记:Large Language Models for Next Point-of-Interest Recommendation
SIGIR 2024 1 intro 传统的基于数值的POI推荐方法在处理上下文信息时存在两个主要限制 需要将异构的LBSN数据转换为数字,这可能导致上下文信息的固有含义丢失仅依赖于统计和人为设计来理解上下文信息,缺乏对上下文信息提供的语义概念的理解 ——>使用…...
基于微信小程序的作业管理系统源码数据库文档
作业管理系统 摘 要 随着社会的发展,社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景,运用软件工程原理和开发方法,它主要是采用java语言技术和微信小程序来完成对系统的…...
从零开始学Flink:揭开实时计算的神秘面纱
一、为什么需要Flink? 当你在电商平台秒杀商品时,1毫秒的延迟可能导致交易失败;当自动驾驶汽车遇到障碍物时,10毫秒的计算延迟可能酿成事故。这些场景揭示了一个残酷事实:数据的价值随时间呈指数级衰减。 传统批处理…...
