c语言——数据结构【链表:单向链表】

 上篇→快速掌握C语言——数据结构【创建顺序表】多文件编译-CSDN博客

一、链表

二、单向链表

2.1 概念

2.2 单向链表的组成

2.3 单向链表节点的结构体原型

//类型重定义,表示存放的数据类型
typedef int DataType;//定义节点的结构体类型
typedef struct node
{union{int len; //头结点的数据域,表示链表的长度DataType data;//普通节点的数据域};struct node *next; //节点的指针域
}linkList,*linkListPtr;

2.4 单向链表的相关操作 (功能函数的封装)

1>创建

#include "test.h"//创建链表==创建头结点
linklistPtr create()
{//在堆区申请节点大小空间,将地址放回给主程序使用linklistPtr H=(linklistPtr)malloc (sizeof(linklist));if (NULL==H){printf("创建失败\n");return NULL;}
//申请成功,将头节点的数据域为0,指针域NULLH->len=0;H->next=NULL;printf("创建成功\n");return H;}

2>判空

//判空
int  empty(linklistPtr H)
{if (NULL==H){printf("判空失败");return -1;}return H->len==0;}

3>申请节点,封装数据

//申请节点封装数据
linklistPtr create_node(int e)
{linklistPtr p=(linklistPtr)malloc (sizeof(linklist));if(NULL==p){printf("申请失败");return NULL;}p->data=e;p->next=NULL;return p;
}

4>头插

//头插
int   head_add(linklistPtr H,int e)
{if (NULL==H){printf("插入失败");return 0;}//申请节点封装数据linklistPtr p=create_node(e);
//头插p->next =H->next;H->next =p;
//插入成功长度自增H->len++;return 1;
}

 5>遍历

void show (linklistPtr H)
{if (NULL==H ||empty(H)){printf("遍历失败");return ;}
//定义一个指针指向头结点linklistPtr p =H;for (int i=0;i<H->len;i++){p=p->next;printf("%d ",p->data);}
putchar(10);
}

6>尾插

//尾插
int tail_add(linklistPtr H,int e)
{if (NULL== H){printf("插入失败");return 0;}
//申请节点封装数据linklistPtr p=create_node(e);linklistPtr q=H;while(q->next !=NULL){q= q->next;}
//尾插q->next =p;//插入成功长度自增H->len++;return 1;
}

7>任意位置插入

//任意位置插入
int insert(linklistPtr H,int index , int e)
{//链表是否合法//插入位置是否合理if (NULL==H || index <1 ||index>H->len+1){printf("插入失败\n");return 0;}
//申请节点封装数据 linklistPtr p=create_node(e);//定义一个指针指向要插入位置的前一个节点linklistPtr q=H;for (int i=0;i<index-1;i++){q=q->next ;}//插入(头插)p->next =q->next;q->next =p;//插入成功长度自增 H->len++;return 1;
}

8>头删

//头删
int head_del(linklistPtr H)
{//判空 //判断合法性if (NULL==H ||empty(H)){printf(" 删除失败\n");	return 0;}//定义一个指针指向普通节点的第一个节点linklistPtr q= H->next;//删除 (孤立)H->next=q->next ;//释放空间free(q);q=NULL;//删除成功 链表长度自减H->len--;return 1;
}

9>尾删

//尾删
int tail_del(linklistPtr H)
{if(NULL==H ||empty(H)){printf("删除失败 ");return 0;}
//定义一个指针,指向 最后一个节点的 前一个节点linklistPtr q=H;for (int i=0;i<H->len-1;i++){q=q->next;}
//删除free(q->next);q->next=NULL;
//删除成功 长度自减H->len--;return 1;
}

10>任意位置删除

//任意位置删除
int index_del(linklistPtr H ,int index)
{if (NULL==H ||empty(H)||index<0||index>H->len){printf("删除失败");return 0;}//定义指针,指向要删除的节点linklistPtr p=NULL;//定义一个指针,指向要删除的前一个节点linklistPtr q=H;for (int i=0;i<index-1;i++){q=q->next;}if (p=NULL){printf("删除失败");return  0;}//保存删除节点的位置p=q->next;q->next=p->next;//删除节点的内存free (p);
//删除成功 长度自减H->len--;return 1;
}

11>按位置修改

//按位置修改
int index_change(linklistPtr H,int index ,int e)
{if (NULL==H||empty(H)){printf("修改失败");return 0;}//定义一个指针,指向要修改的前一个节点linklistPtr q=H;
//定义指针,指向要修改的节点linklistPtr p=NULL;for (int i=0;i<index;i++){q=q->next;}//保存修改节点的位置p=q->next;//修改值p->data=e;return 1;}

12>按值查找返回地址

//按值查找返回
linklistPtr  index_find(linklistPtr H,int e)
{if (NULL==H||empty(H)){printf("查找失败");return NULL;}//定义一个指针指向头结点 linklistPtr p=H->next;while(p!=NULL){if (p->data==e){printf("%p\n",p);return p;}p=p->next;}//没找到printf("没找到目标值\n");return NULL;}

13>反转

//反转 
void reverse(linklistPtr H)
{if(NULL==H || H->len<=1){return ;}//定义一个指针,指向头结点的后一个节点linklistPtr H2=H->next;//头指针的next置空H->next=NULL;while (H2 !=NULL){//标记要插入的节点linklistPtr p=H2;H2=H2->next;//头插p->next =H->next ;H->next =p;}
}

14>销毁

//销毁void my_free(linklistPtr H)
{if (NULL==H){printf("销毁失败");return;}while (H->next !=NULL)//意味着还有节点{//头删head_del(H);}free (H);//释放头结点H=NULL;printf("销毁成功");
}

三、完整代码

1>头文件test.h

#ifndef __TEST_H__
#define __TEST_H__#include <stdio.h>
#include <stdlib.h>//定义节点的结构体类型
typedef struct node
{union{int len;//头结点的数据域,表示链表的长度int data;//普通节点的数据域};struct node *next;//节点的指针域
}linklist,*linklistPtr;//创建链表==创建头结点
linklistPtr create();int  empty(linklistPtr H);linklistPtr create_node(int e);int   head_add(linklistPtr How,int e);void show (linklistPtr H);int tail_add(linklistPtr H,int e);int insert(linklistPtr H,int index , int e);//头删
int head_del(linklistPtr H);//尾删
int tail_del(linklistPtr H);int index_del(linklistPtr H ,int index);
//按位置修改
int index_change(linklistPtr H,int index ,int e);
//按值查找返回
linklistPtr  index_find(linklistPtr H,int e);
//反转
void reverse(linklistPtr H);
//销毁
void my_free(linklistPtr H);#endif

2>源文件test.c

#include "test.h"//创建链表==创建头结点
linklistPtr create()
{//在堆区申请节点大小空间,将地址放回给主程序使用linklistPtr H=(linklistPtr)malloc (sizeof(linklist));if (NULL==H){printf("创建失败\n");return NULL;}
//申请成功,将头节点的数据域为0,指针域NULLH->len=0;H->next=NULL;printf("创建成功\n");return H;}
//判空
int  empty(linklistPtr H)
{if (NULL==H){printf("判空失败");return -1;}return H->len==0;}
//申请节点封装数据
linklistPtr create_node(int e)
{linklistPtr p=(linklistPtr)malloc (sizeof(linklist));if(NULL==p){printf("申请失败");return NULL;}p->data=e;p->next=NULL;return p;
}//头插
int   head_add(linklistPtr H,int e)
{if (NULL==H){printf("插入失败");return 0;}//申请节点封装数据linklistPtr p=create_node(e);
//头插p->next =H->next;H->next =p;
//插入成功长度自增H->len++;return 1;
}void show (linklistPtr H)
{if (NULL==H ||empty(H)){printf("遍历失败");return ;}
//定义一个指针指向头结点linklistPtr p =H;for (int i=0;i<H->len;i++){p=p->next;printf("%d ",p->data);}
putchar(10);
}
//尾插
int tail_add(linklistPtr H,int e)
{if (NULL== H){printf("插入失败");return 0;}
//申请节点封装数据linklistPtr p=create_node(e);linklistPtr q=H;while(q->next !=NULL){q= q->next;}
//尾插q->next =p;//插入成功长度自增H->len++;return 1;
}
//任意位置插入
int insert(linklistPtr H,int index , int e)
{//链表是否合法//插入位置是否合理if (NULL==H || index <1 ||index>H->len+1){printf("插入失败\n");return 0;}
//申请节点封装数据 linklistPtr p=create_node(e);//定义一个指针指向要插入位置的前一个节点linklistPtr q=H;for (int i=0;i<index-1;i++){q=q->next ;}//插入(头插)p->next =q->next;q->next =p;//插入成功长度自增 H->len++;return 1;
}//头删
int head_del(linklistPtr H)
{//判空 //判断合法性if (NULL==H ||empty(H)){printf(" 删除失败\n");	return 0;}//定义一个指针指向普通节点的第一个节点linklistPtr q= H->next;//删除 (孤立)H->next=q->next ;//释放空间free(q);q=NULL;//删除成功 链表长度自减H->len--;return 1;
}
//尾删
int tail_del(linklistPtr H)
{if(NULL==H ||empty(H)){printf("删除失败 ");return 0;}
//定义一个指针,指向 最后一个节点的 前一个节点linklistPtr q=H;for (int i=0;i<H->len-1;i++){q=q->next;}
//删除free(q->next);q->next=NULL;
//删除成功 长度自减H->len--;return 1;
}//任意位置删除
int index_del(linklistPtr H ,int index)
{if (NULL==H ||empty(H)||index<0||index>H->len){printf("删除失败");return 0;}//定义指针,指向要删除的节点linklistPtr p=NULL;//定义一个指针,指向要删除的前一个节点linklistPtr q=H;for (int i=0;i<index-1;i++){q=q->next;}if (p=NULL){printf("删除失败");return  0;}//保存删除节点的位置p=q->next;q->next=p->next;//删除节点的内存free (p);
//删除成功 长度自减H->len--;return 1;
}//按位置修改
int index_change(linklistPtr H,int index ,int e)
{if (NULL==H||empty(H)){printf("修改失败");return 0;}//定义一个指针,指向要修改的前一个节点linklistPtr q=H;
//定义指针,指向要修改的节点linklistPtr p=NULL;for (int i=0;i<index;i++){q=q->next;}//保存修改节点的位置p=q->next;//修改值p->data=e;return 1;}
//按值查找返回
linklistPtr  index_find(linklistPtr H,int e)
{if (NULL==H||empty(H)){printf("查找失败");return NULL;}//定义一个指针指向头结点 linklistPtr p=H->next;while(p!=NULL){if (p->data==e){printf("%p\n",p);return p;}p=p->next;}//没找到printf("没找到目标值\n");return NULL;}//反转 void reverse(linklistPtr H)
{if(NULL==H || H->len<=1){return ;}//定义一个指针,指向头结点的后一个节点linklistPtr H2=H->next;//头指针的next置空H->next=NULL;while (H2 !=NULL){//标记要插入的节点linklistPtr p=H2;H2=H2->next;//头插p->next =H->next ;H->next =p;}
}
//销毁
void my_free(linklistPtr H)
{if (NULL==H){printf("销毁失败");return;}while (H->next !=NULL)//意味着还有节点{//头删head_del(H);}free (H);//释放头结点H=NULL;printf("销毁成功");
}

3>测试文件main.c

#include "test.h"int main(int argc, const char *argv[])
{//创建linklistPtr H=create();//头插 head_add(H,10);head_add(H,20);head_add(H,30);head_add(H,40);head_add(H,50);show(H);
//尾插 tail_add(H,11);tail_add(H,22);tail_add(H,33);tail_add(H,44);tail_add(H,55);show(H);//任意位置插入insert(H,3,888);show (H);	//头删  	head_del(H);show(H);head_del(H);show(H);tail_del(H);show(H);index_del(H,3);show(H);index_change (H,5,666);show(H);index_find (H,666);reverse(H);show(H);return 0;
}

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

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

相关文章

【AI图像生成网站Golang】项目测试与优化

AI图像生成网站 目录 一、项目介绍 二、雪花算法 三、JWT认证与令牌桶算法 四、项目架构 五、图床上传与图像生成API搭建 六、项目测试与优化 六、项目测试与优化 在开发过程中&#xff0c;性能优化是保证项目可扩展性和用户体验的关键步骤。本文将详细介绍我如何使用一…

Mybatis映射关系

目录 多对一 方式一&#xff1a;一条sql语句&#xff08;级连属性映射&#xff09; 方式二&#xff1a;一条sql语句&#xff08;association&#xff09; 方式三&#xff1a;两条sql语句&#xff0c;分步查询 一对多 方式一&#xff1a;collection 方式二&#xff1a;分…

隐私清理工具Goversoft Privazer

PrivaZer 是一款专为隐私保护而生的 Windows 系统清理工具&#xff0c;支持深度扫描、清除无用文件和隐私痕迹。 PrivaZer - 深度扫描磁盘&#xff0c;自动清理上网痕迹&#xff0c;全面保护 Windows 的网络隐私 释放磁盘空间 硬盘空间告急&#xff0c;想清理却又无从下手&…

基于Spring Boot的医院质控上报系统

一、系统背景与意义 医院质控上报系统旨在通过信息化手段&#xff0c;实现医院质量控制的标准化、流程化和自动化管理。该系统能够帮助医院实时监控医疗质量数据&#xff0c;及时发现和处理潜在的质量问题&#xff0c;从而确保医疗服务的安全性和有效性。同时&#xff0c;系统…

Java-30 深入浅出 Spring - IoC 基础 启动IoC 纯XML启动 Bean、DI注入

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 大数据篇正在更新&#xff01;https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了&#xff1a; MyBatis&#xff…

Python-基于Pygame的小游戏(坦克大战-1.0(世界))(一)

前言:创作背景-《坦克大战》是一款经典的平面射击游戏&#xff0c;最初由日本游戏公司南梦宫于1985年在任天堂FC平台上推出。游戏的主题围绕坦克战斗&#xff0c;玩家的任务是保卫自己的基地&#xff0c;同时摧毁所有敌人的坦克。游戏中有多种地形和敌人类型&#xff0c;玩家可…

【达梦数据库】Coredump文件生成与分析

目录 背景参考链接分析Coredump文件获取问题SQL1、查看Coredump文件生成路径2、使用gdb工具读取Coredump文件3、记录崩溃线程堆栈4、记录当前崩溃线程号5、使用dmrdc工具分析Coredump文件6、寻找线程号对应SQL7、重新执行SQL&#xff0c;复现问题 记录Coredump文件中所有线程的…

【爬虫一】python爬虫基础合集一

【爬虫一】python爬虫基础合集一 1. 网络请求了解1.1. 请求的类型1.2. 网络请求协议1.3. 网络请求过程简单图解1.4. 网络请求Headers(其中的关键字释义)&#xff1a;请求头、响应头 2. 网络爬虫的基本工作节点2.1. 了解简单网络请求获取响应数据的过程所涉及要点 1. 网络请求了…

基于SCUI的后台管理系统

一、SCUI Admin 官方地址&#xff1a;https://python-abc.xyz/scui-doc/ 高性能中后台前端解决方案&#xff0c;基于 Vue3、elementPlus 持续性的提供独家组件和丰富的业务模板帮助你快速搭建企业级中后台前端任务。 预览地址&#xff1a;https://python-abc.xyz/scui-doc/de…

vscode不同的项目使用不同的环境变量或编译环境

转载请标明出处&#xff1a;小帆的帆的博客 假如电脑中安装的两套C编译环境&#xff0c;想要切换编译环境时可以在操作系统的环境变量中调整顺序&#xff0c;然后排在前面的环境就会被使用。 这样做的弊端&#xff1a; 麻烦容易忘&#xff0c;忘了项目不报错就可能就不会发现…

知网研学 | 知网文献(CAJ+PDF)批量下载

知网文献&#xff08;CAJPDF&#xff09;批量下载 一、知网研学安装二、插件及脚本安装三、CAJ批量下载四、脚本下载及PDF批量下载浏览器取消拦截窗口 一、知网研学安装 批量下载知网文件&#xff0c;格式为es6文件&#xff0c;需使用知网研学软件打开&#xff0c;故需先安装该…

运输时间超声波流量计基本原理解析

通过从上游传感器向下游传感器发送超声波脉冲并再次返回来测量流体速度。这些信号沿流向和逆流向交替发射。由于信号在其中传播的流体正在流动&#xff0c;因此超声信号沿流向的传播时间比逆流向的传播时间短。测量由此产生的传输时间差 Δt&#xff0c;并允许流量计确定沿超声…

<mutex>注释 11:重新思考与猜测、补充锁的睡眠与唤醒机制,结合 linux0.11 操作系统代码的辅助(上)

&#xff08;46&#xff09;问题的起源&#xff1a; 因为上面的内核代码&#xff0c;我们编写多线程代码时&#xff0c;对手里的家伙事不那么自信。但我们知道&#xff0c;多线程在竞争锁时&#xff0c;若得不到锁&#xff0c;会进入睡眠&#xff0c;并会在被唤醒后重新尝试得…

flask_socketio 以继承 Namespace方式实现一个网页聊天应用

点击进入上一篇&#xff0c;可作为参考 实验环境 python 用的是3.11.11 其他环境可以通过这种方式一键安装&#xff1a; pip install flask3.1.0 Flask-SocketIO5.4.1 gevent-websocket0.10.1 -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple pip list 详情如下&am…

LOS/NLOS环境建模与三维TOA定位,MATLAB仿真程序,可自定义锚点数量和轨迹点长度

本代码的主要功能是建模 LOS&#xff08;视距&#xff09;和 NLOS&#xff08;非视距&#xff09;环境下的定位系统&#xff0c;估计目标的动态位置&#xff0c;三维空间 文章目录 运行结果源代码代码介绍 总结 运行结果 10个点的轨迹定位&#xff1a; 50个点的轨迹定位&#…

Centos创建共享文件夹拉取文件

1.打开VMware程序&#xff0c;鼠标右检你的虚拟机&#xff0c;打开设置 2.点击选项——共享文件夹——总是启用 点击添加&#xff0c;设置你想要共享的文件夹在pc上的路径&#xff08;我这里已经添加过了就不加了&#xff09; 注意不要中文&#xff0c;建议用share&#xff0c…

C++算法第十一天

本篇文章我们继续学习动态规划 目录 第一题 题目链接 题目解析 代码原理 代码编写 第二题 题目链接 题目解析 代码原理 代码编写 第三题 题目链接 题目解析 代码原理 代码编写 第四题 题目链接 题目解析 代码原理 代码编写 第五题 题目链接 题目解析 代…

[x86 ubuntu22.04]投影模式选择“只使用外部”,外部edp屏幕无背光

1 问题描述 CPU&#xff1a;G6900E OS&#xff1a;ubuntu22.04 Kernel&#xff1a;6.8.0-49-generic 系统下有两个一样的 edp 屏幕&#xff0c;投影模式选择“只使用外部”&#xff0c;内部 edp 屏幕灭&#xff0c;外部 edp 屏幕无背光。DP-1 是外部 edp 屏幕&#xff0c;eDP-1…

【ETCD】【实操篇(二)】如何从源码编译并在window上搭建etcd集群?

要在 Windows 上编译 etcd 及 etcdctl 工具&#xff0c;并使用 bat 脚本启动 etcd 集群&#xff0c;首先需要准备好开发环境并确保依赖项正确安装。下面是从 etcd 3.5 源码开始编译和启动 etcd 集群的详细步骤&#xff1a; 目录 1. 安装 Go 环境2. 获取 etcd 源码3. 编译 etcd…

34. Three.js案例-创建球体与模糊阴影

34. Three.js案例-创建球体与模糊阴影 实现效果 知识点 WebGLRenderer WebGLRenderer 是 Three.js 中用于渲染 3D 场景的核心类。它负责将场景中的对象绘制到画布上。 构造器 new THREE.WebGLRenderer(parameters)参数类型描述parametersObject可选参数对象&#xff0c;包…