单链表操作 C实现
struct LNode { //定义一个节点
int data; //数据域
struct LNode *next; //指针域
};
0.初始化
typedef sturct LNode{ //定义单链表结点类型 int date ; //每个结点存放一个数据元素struct LNode *next; //指针指向下一个结点
}LNodes, *LinkList;
typedef LNode{ //定义单链表结点类型 int date ; //每个结点存放一个数据元素struct LNode *next; //指针指向下一个结点
};//typedef struct LNode LNodes;
//typedef struct LNOde *LinkList;
//上面俩个是等价的1)不带头结点的单链表
bool InitList(LinkList &L) //初始化空链表
{L = NULL; //空表没有任何结点return true;
}void test()
{LinkList L ; //声明一个指向单链表的指针//初始化一个空表InitList (L);
}判断是否为空
bool Empty(LinkList L){if(L == NULL)return true;else return false;
}
//或:
bool Empty(LinkList L){return (L == NULL);
}2)带头节的单链表
//初始化一个单链表(带头结点)
bool InitList (LinkList &L){L = (LNode * ) malloc (sizeof(LNode)); //分配一个头结点if (L == NULL) //内存不足分配失败return false; L->next = NULL;return true;
}判断是否为空
bool Empty(LinkList L){if(L->next == NULL)return true;else return false;
}
1.尾插法建立链表
struct LNode *CreateLinkList1(void){ //尾插法创建链表struct LNode *head=(struct LNode *)malloc(LEN); //创建一个头节点head->next=NULL; //开始时头节点指针指向NULLstruct LNode *h=head,*s;struct LNode info;//接收从键盘输入每个节点的数据scanf("%d",&info.data);while(info.data!=0){ //创建链表,直到输入数据为0结束s=(struct LNode *)malloc(LEN);s->data=info.data; //节点s接收输入数据h->next=s; //尾插如链表尾部h=h->next; //保持h位于链表末尾,方便接收下一个节点数据scanf("%d",&info.data);}h->next=NULL; //链表末尾指向NULLreturn head;
}
typedef struct LNode {int data; //数据域struct LNode *next; //指针域}LNodes,*LinkList;LNodes *insertFront(LNodes *head, LNodes *newNode)
{newNode->next = head->next;head->next = newNode;return head;
}
2.头插法建立链表
struct LNode *CreateLinkList2(void){ //头插法创建链表struct LNode *head=(struct LNode *)malloc(LEN);head->next=NULL;struct LNode *h=head,*s;struct LNode info;scanf("%d",&info.data);while(info.data!=0){ //创建链表,直到输入数据为0结束s=(struct LNode *)malloc(LEN);s->data=info.data;//节点s接收输入数据s->next=h->next; //头插插入头节点尾部,插入节点要始终跟着头节点后面h->next=s; scanf("%d",&info.data);}return head;
}
typedef struct LNode {int data; //数据域struct LNode *next; //指针域}LNodes,*LinkList;LNodes *insertBack(LNodes *head, LNodes *tail, LNodes *newNode)
{newNode->next = NULL;tail->next = newNode;tail = newNode;return head;
}
3.链表结点删除操作
struct LNode *Delete(struct LNode *head,int x){ //删除链表中值为x的节点struct LNode *p=head->next,*pre=head,*q;while(p!=NULL){if(p->data==x){q=p;pre->next=p->next;p=p->next;free(q);}else{pre=p;p=p->next;}}return head;
}
4.在有序链表中插入一个结点
struct LNode *Insert(struct LNode *head,int x){ //创建一个递增链表,将x插入链表,并保持有序struct LNode *p=head->next,*pre=head,*q;while(p!=NULL){if(x<p->data){q=(struct LNode *)malloc(LEN); //为插入值分配一个节点空间q->data=x;pre->next=q;q->next=p;break;}else{pre=p;p=p->next;}}return head;
}
5.遍历
void print(struct LNode *head){ //遍历链表并输出各个节点的数据struct LNode *p=head->next;while(p!=NULL){printf("%d->",p->data);p=p->next;}printf("NULL\n");
}
运行程序结果:
尾插法:1 2 3 4 6 7 8 9 0
1->2->3->4->6->7->8->9->NULL
头插法:1 2 3 4 6 7 8 9 0
9->8->7->6->4->3->2->1->NULL
删除节点8:1->2->3->4->6->7->9->NULL
插入节点5:1->2->3->4->5->6->7->9->NULL
Press any key to continue...
完整的代码如下:
#include <stdio.h>
#include <stdlib.h>
#define LEN sizeof(struct LNode) //LEN表示一个节点大小
struct LNode{ //定义一个节点int data; //数据域struct LNode *next; //指针域
};
struct LNode *CreateLinkList1(void){ //尾插法创建链表struct LNode *head=(struct LNode *)malloc(LEN); //创建一个头节点head->next=NULL; //开始时头节点指针指向NULLstruct LNode *h=head,*s;struct LNode info;//接收从键盘输入每个节点的数据scanf("%d",&info.data);while(info.data!=0){ //创建链表,直到输入数据为0结束s=(struct LNode *)malloc(LEN);s->data=info.data; //节点s接收输入数据h->next=s; //尾插如链表尾部h=h->next; //保持h位于链表末尾,方便接收下一个节点数据scanf("%d",&info.data);}h->next=NULL; //链表末尾指向NULLreturn head;
}
struct LNode *CreateLinkList2(void){ //头插法创建链表struct LNode *head=(struct LNode *)malloc(LEN);head->next=NULL;struct LNode *h=head,*s;struct LNode info;scanf("%d",&info.data);while(info.data!=0){ //创建链表,直到输入数据为0结束s=(struct LNode *)malloc(LEN);s->data=info.data;//节点s接收输入数据s->next=h->next; //头插插入头节点尾部,插入节点要始终跟着头节点后面h->next=s; scanf("%d",&info.data);}return head;
}
struct LNode *Delete(struct LNode *head,int x){ //删除链表中值为x的节点struct LNode *p=head->next,*pre=head,*q;while(p!=NULL){if(p->data==x){q=p;pre->next=p->next;p=p->next;free(q);}else{pre=p;p=p->next;}}return head;
}
struct LNode *Insert(struct LNode *head,int x){ //创建一个递增链表,将x插入链表,并保持有序struct LNode *p=head->next,*pre=head,*q;while(p!=NULL){if(x<p->data){q=(struct LNode *)malloc(LEN); //为插入值分配一个节点空间q->data=x;pre->next=q;q->next=p;break;}else{pre=p;p=p->next;}}return head;
}
void print(struct LNode *head){ //遍历链表并输出各个节点的数据struct LNode *p=head->next;while(p!=NULL){printf("%d->",p->data);p=p->next;}printf("NULL\n");
}
int main(void){struct LNode *p1,*p2,*q,*y;printf("尾插法:");p1=CreateLinkList1(); //p1接收尾插法传回的头节点print(p1);printf("头插法:");p2=CreateLinkList2(); //p2接收头插法传回的头节点print(p2);printf("删除节点8:");q=Delete(p1,8);print(p1);printf("插入节点5:");y=Insert(p1,5);print(y);
}
头插法和尾插法详解
头插法
核心代码:
head->next = NULL;
s->next = head->next;
head->next = s;
单个结点
原始状态
第一个元素插入的过程(注意:1和2的顺序不能颠倒,不然会导致链表缺失)
第一个元素插入后
第二个元素插入的过程(其余元素插入的过程也类似)
第二个元素插入后
尾插法
核心代码:
tail = head;
s->next = NULL;
tail->next = s;
tail = s;
原始状态
第一个元素插入的过程(注意:2和3的顺序不能颠倒,不然会导致链表的生成出错)
第一个元素插入后
第二个元素插入的过程(其余元素插入的过程也类似)
第二个元素插入后
头插法和尾插法的对比
头插法建立链表的算法简短易懂,但是生成链表的结点顺序与原来输入的顺序相反,而用尾插法建立链表可使输入和生成的结点顺序相同
为什么会这样呢?
根据上面的头插法和尾插法的算法,我们很容易知道,当用头插法依次插入值分别为1,2,3,4,5的结点(也叫做元素)后,单链表会如下图所示:
但是用尾插法同样插入值分别为1,2,3,4,5的结点后,单链表却会如下图所示:
而在这两个链表中,输出链表中各个元素的值只能从已知的头结点head开始遍历,所以分别用头插法和尾插法创建链表后,依次输出的元素的值刚好是相反的
验证小例子:
#include <stdio.h>
#include <malloc.h>typedef struct node
{struct node* next;int data;}LinkList; //定义LinkList为struct node类型,即struct node可直接用LinkList来表示,方便定义//头插法创建单链表
int main (void)
{int i, len = 5;
//len表示链表的长度 LinkList* head, * s;
//head为LinkList*类型的指针变量,表示头指针head = (LinkList*)malloc (sizeof (LinkList));
//malloc (sizeof (LinkList))意思是让系统分配内存大小为sizeof (LinkList)的空间head->next = NULL;
//令头指针的所指向结点的指针域为空for (i = 0; i < len; i++){s = (LinkList*)malloc (sizeof (LinkList));printf ("请输入该元素的值:");scanf ("%d", &s->data);s->next = head->next;head->next = s;}
//以下代码是为了将单链表中各个元素的值依次打印出来 LinkList* q;q = (LinkList*)malloc (sizeof (LinkList));q = head->next;while (q != NULL){printf ("%d", q->data);q = q->next;}return 0;
}
结果:
请输入该元素的值:1
请输入该元素的值:2
请输入该元素的值:3
请输入该元素的值:4
请输入该元素的值:5
54321
#include <stdio.h>
#include <malloc.h>typedef struct node
{struct node* next;int data;}LinkList; //尾插法创建单链表
int main (void)
{int i, len = 5;LinkList* head,* s,* tail;
//tail表示尾指针 head = (LinkList*)malloc (sizeof (LinkList));tail = head;for (i = 0; i < len; i++){s = (LinkList*)malloc (sizeof (LinkList));printf ("请输入该元素的值:");scanf ("%d", &s->data); s->next = NULL;tail->next = s;tail = s;}//以下代码是将单链表中各个元素的值依次打印出来 LinkList* q;q = head->next;while (q != NULL){printf ("%d", q->data);q = q->next;}return 0;}
结果:
请输入该元素的值:1
请输入该元素的值:2
请输入该元素的值:3
请输入该元素的值:4
请输入该元素的值:5
12345
————————————————
相关文章:

单链表操作 C实现
struct LNode { //定义一个节点 int data; //数据域 struct LNode *next; //指针域 }; 0.初始化 typedef sturct LNode{ //定义单链表结点类型 int date ; //每个结点存放一个数据元素struct LNode *next; //指针指向下…...

WordPress主题网站首页添加好看的四格小工具教程
直接到网站根目录创建一个css文件(文件名:sige.css),文件名可自定义(注意文件名一致) <link rel"stylesheet" href"你的网站/sige.css" type"text/css" > 然后在header.php模板最上方添加引入代码 也可自定义HTML里添加css代码最上方写…...

unittest自动化测试框架讲解以及实战
为什么要学习unittest 按照测试阶段来划分,可以将测试分为单元测试、集成测试、系统测试和验收测试。单元测试是指对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,通常指函数或者类,一般是开发完成的。 单元…...

数学建模之Matlab基础操作
作者由于后续课程也要学习Matlab,并且之前也进行了一些数学建模的练习(虽然是论文手),所以花了几天零碎时间学习Matlab的基础操作,特此整理。 基本运算 a55 %加法,同理减法 b2^3 %立方 c5*2 %乘法 x 1; …...
【Nuxt】04 Nuxt2-SEO: sitemap.xml、seo优化、robots.txt
1 SiteMap设置 环境准备 注意生成sitemap依赖于nuxtjs/sitemap,并且需要用axios进行请求,不要使用nuxtjs/axios,不然会报错 sitemap.xml配置 在nuxt.config.js中配置下面的内容 npm install nuxtjs/sitemap npm install axios在static/s…...

VMware VSAN 入门
一、虚拟化的存储 1.1、对于数据中心来说最重要的是数据,而承载数据的设备就是存储设备(Storage) 1.2、物理服务器的本地存储阵列 与 虚拟化服务器的本地存储阵列 对比 1.3、避免单台服务器故障的虚拟化高级特性:vSphere HA技术 …...

【设计模式】备忘录模式
文章目录 1.备忘录模式定义2.备忘录模式的角色3.备忘录模式实现3.1.场景说明3.2.结构类图3.3.代码实现 4.备忘录模式优缺点5.备忘录模式适用场景6.备忘录模式总结 主页传送门:💁 传送 1.备忘录模式定义 备忘录(Memento Pattern)模…...
vue3+elementUiPlus表格导出功能
1.下载需要的组件包 npm install file-saver xlsx 2.页面中导入 import FileSaver from file-saver import * as XLSX from xlsx; 3.页面中的表格加一个id <el-table :data"tableData" ref"multipleTableRef" style"width…...

专题五:优先级队列
"你了解我,最干净的轮廓, 握住小小风车和放肆的梦~" 堆是一个不错的数据结构,而在计算机中,无法表示二叉分支结构,因此我们经常会看到使用线性表来作为堆的存储容器。在接触堆的时候,我们是把它…...

游戏设计模式专栏(一):工厂方法模式
引言 大家好,我是亿元程序员,一位有着8年游戏行业经验的主程。 本系列是《和8年游戏主程一起学习设计模式》,让糟糕的代码在潜移默化中升华,欢迎大家关注分享收藏订阅。 在游戏开发中,代码的组织和结构对于项目的可…...

element中使用el-steps 进度条效果demo(整理)
<template><div class"margin-top20"><!-- align-center 不要居中就去掉 --><!-- process-status 这几个参数值:改变颜色 wait / process / finish / error / --><!-- active 到第几个是绿色 --><el-steps :space&qu…...

038:mapboxGL 旋转地图(rotateTo)
第038个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+mapbox中旋转地图。 直接复制下面的 vue+mapbox源代码,操作2分钟即可运行实现效果 文章目录 示例效果配置方式示例源代码(共68行)相关API参考:专栏目标示例效果 配置方式 1)查看基础设置:https://xiaozhuan…...

java遇到的问题
java遇到的问题 Tomcat与JDK版本问题 当使用Tomcat10的版本用于springmvc借用浏览器调试时,使用JDK8浏览器会报异常。 需要JDK17(可以配置多个JDK环境,切换使用)才可以使用,配置为JAVA_HOME路径,否则&a…...

LLM(二)| LIMA:在1k高质量数据上微调LLaMA1-65B,性能超越ChatGPT
本文将介绍在Lit-GPT上使用LoRA微调LLaMA模型,并介绍如何自定义数据集进行微调其他开源LLM 监督指令微调(Supervised Instruction Finetuning) 什么是监督指令微调?为什么关注它? 目前大部分LLM都是decoder-only&…...
Android AMS——创建Application(七)
与在 App 内部启动一个 Activity 的不同之处在于,点击桌面 Launcher 首次启动一个应用程序的时候,会先去创建一个该应用程序对应的进程,然后执行 ActivityThread 的 main() 方法去创建该应用对应的 Application,然后再去启动首页 Activity。前面已经分析了进程的创建和启动…...

html 边缘融合加载
html 代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>边缘融合加载</title><style>* {margin: 0;padding: 0;box-sizing: border-box;}body {height: 100vh;padding-bottom: 80px;b…...

ElasticSearch - 在 微服务项目 中基于 RabbitMQ 实现 ES 和 MySQL 数据异步同步(考点)
目录 一、数据同步 1.1、什么是数据同步 1.2、解决数据同步面临的问题 1.3、解决办法 1.3.1、同步调用 1.3.2、异步通知(推荐) 1.3.3、监听 binlog 1.3、基于 RabbitMQ 实现数据同步 1.3.1、需求 1.3.2、在“酒店搜索服务”中 声明 exchange、…...

Springboot+vue的企业人事管理系统(有报告),Javaee项目,springboot vue前后端分离项目。
演示视频: Springbootvue的企业人事管理系统(有报告),Javaee项目,springboot vue前后端分离项目。 项目介绍: 本文设计了一个基于Springbootvue的前后端分离的企业人事管理系统,采用M(model&am…...

初识Java 11-1 函数式编程
目录 旧方式与新方式 lambda表达式 方法引用 Runnable 未绑定方法引用 构造器方法引用 函数式接口 带有更多参数的函数式接口 解决缺乏基本类型函数式接口的问题 本笔记参考自: 《On Java 中文版》 函数式编程语言的一个特点就是其处理代码片段的简易性&am…...

【Ambari】银河麒麟V10 ARM64架构_安装Ambari2.7.6HDP3.3.1问题总结
🍁 博主 "开着拖拉机回家"带您 Go to New World.✨🍁 🦄 个人主页——🎐开着拖拉机回家_大数据运维-CSDN博客 🎐✨🍁 🪁🍁 希望本文能够给您带来一定的帮助🌸文…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
oracle与MySQL数据库之间数据同步的技术要点
Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异,它们的数据同步要求既要保持数据的准确性和一致性,又要处理好性能问题。以下是一些主要的技术要点: 数据结构差异 数据类型差异ÿ…...
数据链路层的主要功能是什么
数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...
C++八股 —— 单例模式
文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全(Thread Safety) 线程安全是指在多线程环境下,某个函数、类或代码片段能够被多个线程同时调用时,仍能保证数据的一致性和逻辑的正确性…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...