当前位置: 首页 > news >正文

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;
}

相关文章:

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

上篇→快速掌握C语言——数据结构【创建顺序表】多文件编译-CSDN博客 一、链表 二、单向链表 2.1 概念 2.2 单向链表的组成 2.3 单向链表节点的结构体原型 //类型重定义,表示存放的数据类型 typedef int DataType;//定义节点的结构体类型 typedef struct node {union{int l…...

​Python 标识符是啥?​

Python 的标识符就是我们写代码时用来给变量、函数、类等取名字的东西。 你写的 my_variable 是个标识符&#xff0c; 定义的 add_numbers 函数名也是个标识符&#xff0c; 甚至你写的 Cat 类名&#xff0c;也是标识符。 一句话总结&#xff1a;标识符就是代码里给“东西”起…...

视频及JSON数据的导出并压缩

npm下载安装 jszip 和 file-saver 这两个库来实现文件的压缩和保存功能&#xff1a; npm install jszip npm install file-saver 导入依赖库&#xff1a; import JSZip from jszip; import { saveAs } from file-saver; 方法实现&#xff1a; batchDownload() {const zip…...

VScode使用教程(菜鸟版)

目录 1.VScode是什么&#xff1f; 2.VScode的下载和安装&#xff1f; 2.1下载和安装 下载路径&#xff1a; 安装流程&#xff1a; 一、点击【Download for Windows】 二、等一小会儿的下载&#xff0c;找到并双击你下载好的.exe文件&#xff0c;开始进入安装进程 三、点…...

【漏洞复现】Grafana 安全漏洞(CVE-2024-9264)

🏘️个人主页: 点燃银河尽头的篝火(●’◡’●) 如果文章有帮到你的话记得点赞👍+收藏💗支持一下哦 一、漏洞概述 1.1漏洞简介 漏洞名称:Grafana 安全漏洞 (CVE-2024-9264)漏洞编号:CVE-2024-9264 | CNNVD-202410-1891漏洞类型:命令注入、本地文件包含漏洞威胁等级:…...

Android AOSP 源码中批量替换“phone“为“tablet“的命令详解

我来帮你写一篇关于这条命令的分析博客。 Android 项目中批量替换"phone"为"tablet"的命令详解 前言 在 Android 开发中,有时我们需要批量修改资源文件中的某些文本内容。今天我们来分析一条结合了 grep 和 sed 的强大命令,该命令用于将项目中的 “ph…...

基于JavaWeb(SSM+MySQL)问卷调查管理系统设计与实现毕业论文

标题:基于 JavaWeb&#xff08;SSMMySQL&#xff09;问卷调查管理系统设计与实现 内容:1.摘要 摘要&#xff1a;本文介绍了一个基于 JavaWeb&#xff08;SSMMySQL&#xff09;的问卷调查管理系统的设计与实现。该系统旨在为用户提供一个高效、便捷的问卷调查工具&#xff0c;帮…...

域内用户枚举与密码喷洒与密码爆破

域控&#xff1a;192.168.72.163 攻击者&#xff1a;192.168.72.162 域&#xff1a;hacker.com 用户枚举 as-rep 回复状态判断域用户 用户存在且启用&#xff1a;KDC_ERR_PREAUTH_REQUIRED (需要额外的预认证) 用户存在但禁用&#xff1a;KDC_ERR_CLIENT_REVOKED NT Stat…...

DIY 集合求并集(union)运算的代码 ← Python

【算法分析】 已知 Python 提供了求并集运算的函数 union。代码示例如下; >>> s1{1,2,3} >>> s2{2,3,7,1,9} >>> s1.union(s2) {1, 2, 3, 7, 9} >>> 不过&#xff0c;知其然也要知其所以然。 本例自己 DIY 集合求并集&#xff08;union…...

Redis bitmaps 使用

应用场景&#xff1a; 记录id为 1 的用户&#xff0c;2024年12月签到情况&#xff0c;并统计&#xff1b; 记录 1号签到 zxys-redis:0>setbit 1:202412 1 1 记录 2号签到 zxys-redis:0>setbit 1:202412 2 1 记录 3号未签到 zxys-redis:0>setbit 1:202412 3 0 …...

vue深层数据响应的问题

vue版本为v2.16 数据是数组数据&#xff0c;且初始数据为空&#xff1b; 当接口返回的数据直接赋值到字段之后导致深层的子项数据无法被监听到&#xff1b; 数据结构如下&#xff1a; //数据结构//初始化数据 data:[] 接口返回数据 resData:[{id:"",name:"&quo…...

解决Nginx + Vue.js (ruoyi-vue) 单页应用(SPA) 404问题的指南

问题描述 在使用Vue.js构建的单页应用&#xff08;SPA&#xff09;中&#xff0c;特别是像ruoyi-vue这样的框架&#xff0c;如果启用了HTML5历史记录模式进行路由管理&#xff0c;那么用户直接访问子路径或刷新页面时可能会遇到404错误。这是因为当用户尝试访问一个非根路径时…...

项目计划表如何制作?使用甘特图制作项目计划表的步骤

在项目管理中&#xff0c;项目计划是项目的核心要素&#xff0c;它详细记录了项目任务详情、责任人、时间规划以及所需资源。 这份计划不仅为项目推进提供指引&#xff0c;更是控制范围蔓延、争取更多支持的有力工具。 然而&#xff0c;如同项目管理的其他环节一样&#xff0…...

Flutter-底部分享弹窗(showModalBottomSheet)

showModalBottomSheet 构造函数的样式 Future<T?> showModalBottomSheet<T>({required BuildContext context, // 上下文对象&#xff0c;通常是当前页面的上下文bool isScrollControlled false, // 控制底部弹窗的大小&#xff0c;如果为…...

初学stm32 --- 时钟配置

目录 stm32时钟系统 时钟源 &#xff08;1&#xff09; 2 个外部时钟源&#xff1a; &#xff08;2&#xff09;2 个内部时钟源&#xff1a; 锁相环 PLL PLLXTPRE&#xff1a; HSE 分频器作为 PLL 输入 (HSE divider for PLL entry) PLLSRC&#xff1a; PLL 输入时钟源 (PL…...

LeetCode:226.翻转二叉树

跟着carl学算法&#xff0c;本系列博客仅做个人记录&#xff0c;建议大家都去看carl本人的博客&#xff0c;写的真的很好的&#xff01; 代码随想录 LeetCode&#xff1a;226.翻转二叉树 给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 …...

(css)鼠标移入或点击改变背景图片

(css)鼠标移入或点击改变背景图片 html <div class"mapTip"><divv-for"(item, index) of legendList":key"index"class"mapTipOne":class"{ active: change index }"click"legendHandle(item, index)"…...

Unbuntu下怎么生成SSL自签证书?

环境&#xff1a; WSL2 Unbuntu 22.04 问题描述&#xff1a; Unbuntu下怎么生成SSL自签证书&#xff1f; 解决方案&#xff1a; 生成自签名SSL证书可以使用OpenSSL工具&#xff0c;这是一个广泛使用的命令行工具&#xff0c;用于创建和管理SSL/TLS证书。以下是生成自签名…...

OpenGL ES 03 加载3张图片并做混合处理

OpenGL ES 02 加载3张图片并做混合处理 什么是纹理单元纹理单元的作用使用纹理单元的步骤详细解释加载图片并绑定到到GPU纹理单元采样器的设置1.设置采样器变量的纹理单元编号&#xff0c;目的是为了告诉纹理采样器&#xff0c;从哪个纹理单元采集数据2.如果你没有显式地设置采…...

深度学习-74-大语言模型LLM之基于API与llama.cpp启动的模型进行交互

文章目录 1 大模型量化方法1.1 GPTQ(后训练量化)1.2 GGUF(支持CPU)1.3 AWQ(后训练量化)2 llama.cpp2.1 功能2.1.1 Chat(聊天)2.1.2 Completion(补全)2.2 运行开源LLM2.2.1 下载安装llama.cpp2.2.2 下载gguf格式的模型2.2.3 运行大模型3 API访问3.1 调用补全3.2 调用聊天3.3 提取…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

Android 之 kotlin 语言学习笔记三(Kotlin-Java 互操作)

参考官方文档&#xff1a;https://developer.android.google.cn/kotlin/interop?hlzh-cn 一、Java&#xff08;供 Kotlin 使用&#xff09; 1、不得使用硬关键字 不要使用 Kotlin 的任何硬关键字作为方法的名称 或字段。允许使用 Kotlin 的软关键字、修饰符关键字和特殊标识…...

ip子接口配置及删除

配置永久生效的子接口&#xff0c;2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

Golang——7、包与接口详解

包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...