上机实验二 设计单循环链表 西安石油大学数据结构
实验名称:设计单循环链表
(1)实验目的:掌握线性表的链式存储结构;掌握单循环链表及其基本操作的实现。
(2)主要内容:实现单循环链表的初始化、求数据元素个数、插入、删除、取数据元素等操作;用插入法建立带头结点的单循环链表;设计一个测试主函数验证所设计单循环链表的正确性。
1.实验目的
掌握线性表的链式存储结构;掌握单循环链表及其基本操作的实现。
2.问题描述
利用C语言设计实现单循环链表,并实现初始化、求数据元素个数、插入、删除、取数据元素等基本操作。使用插入法建立带头结点的单循环链表,并设计一个测试主函数验证所设计单循环链表的正确性。
3.基本要求
具体要求如下:
-
设计一个结构体表示链表的节点,包括数据域和指针域。
-
实现单循环链表的初始化操作,即创建一个空链表。
-
实现求数据元素个数的操作,即统计链表中已有的节点数。
-
实现插入操作,在指定位置插入一个节点,并将新节点链接到链表中。
-
实现删除操作,删除指定位置的节点。
-
实现取数据元素的操作,返回指定位置的节点值。
-
使用插入法建立带头结点的单循环链表,即通过用户输入逐个插入节点来创建链表,直到用户结束输入。
-
编写一个测试主函数,验证所设计单循环链表的正确性,包括对各个操作的测试。测试包括但不限于以下内容:创建一个空链表并输出链表元素个数。
插入若干节点,并验证插入后链表的正确性。
删除某个位置的节点,并验证删除后链表的正确性。
取某个位置的节点值,并输出验证结果。
4.测试数据
初始链表为空,链表元素个数为:0
插入后的链表元素:10
插入后的链表元素:5 15 10 20
删除后的链表元素:15 20
取节点值的结果:
Position 0: 15
Position 1: 20
Position 2: -1
5.算法思想
链表数据结构的基本操作,包括初始化链表、获取链表元素个数、在指定位置插入节点、删除指定位置的节点、获取指定位置节点的值以及打印链表中的元素。其中,链表是一种线性结构,每个节点包括数据和指向下一个节点的指针,头结点不包含数据。
该算法通过遍历链表的方式来找到指定位置的节点,然后进行相应的操作。具体实现方法包括:在空链表中插入第一个节点时,直接将头结点指向新节点;在链表头部插入节点时,将新节点的指针指向原头结点,再将头结点指向新节点;在链表中间和尾部插入节点时,在找到插入位置的前一个节点后,将新节点的指针指向原位置的节点,再将前一个节点的指针指向新节点;删除节点时,首先找到要删除节点的前一个节点,将前一个节点的指针指向要删除节点的下一个节点,然后释放要删除节点的内存空间;获取节点值时,找到指定位置的节点,返回其数据域的值。
6.模块划分
initList()
:初始化链表,返回头结点。listLength(Node* head)
:获取链表的元素个数。insertNode(Node* head, int position, int data)
:在链表指定位置插入节点。deleteNode(Node* head, int position)
:删除链表指定位置的节点。getNodeData(Node* head, int position)
:获取链表指定位置节点的值。printList(Node* head)
:打印链表中的元素。main()
:主函数。
7.数据结构
(1) 数据类型DataType定义如下:
typedef struct {int number;int cipher;
} DataType;
这个定义表示DataType结构体包含两个成员变量,即number
和cipher
,分别表示一个整数的数字和位数。
(2) 带头结点单循环链表结点的结构体定义如下:
typedef struct SCLNode {DataType data;struct SCLNode* next;
} SCLNode;
这个定义表示SCLNode结构体是一个带头结点的单循环链表的节点,包含两个成员变量。其中,data
是存储数据元素的DataType类型的变量。next
是指向下一个节点的指针,类型为指向SCLNode结构体的指针。
通过这样的定义,可以创建一个带头结点的单循环链表,每个节点存储一个数据元素,并且通过next指针连接起来形成循环链表。头结点的作用是指示链表的起始位置,尾节点的next指针指向头结点,形成循环。
8.源程序
#include <stdio.h>
#include <stdlib.h>typedef struct Node {int data;struct Node* next;
} Node;// 初始化链表,返回头结点
Node* initList() {Node* head = (Node*)malloc(sizeof(Node));head->next = NULL; // 初始化时头结点指向NULL,形成空链表return head;
}// 获取链表的元素个数
int listLength(Node* head) {int count = 0;Node* current = head->next;while (current != NULL) {count++;current = current->next;}return count;
}// 在链表指定位置插入节点
void insertNode(Node* head, int position, int data) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = data;Node* current = head;int count = 0;while (current != NULL && count < position) {current = current->next;count++;}newNode->next = current->next;current->next = newNode;
}// 删除链表指定位置的节点
void deleteNode(Node* head, int position) {Node* current = head;int count = 0;while (current->next != NULL && count < position) {current = current->next;count++;}if (current->next != NULL) {Node* temp = current->next;current->next = temp->next;free(temp);}
}// 获取链表指定位置节点的值
int getNodeData(Node* head, int position) {Node* current = head->next;int count = 0;while (current != NULL && count < position) {current = current->next;count++;}if (current != NULL)return current->data;elsereturn -1; // 返回-1表示节点不存在
}// 打印链表中的元素
void printList(Node* head) {Node* current = head->next;while (current != NULL) {printf("%d ", current->data);current = current->next;}printf("\n");
}int main() {Node* head = initList();printf("初始链表为空,链表元素个数为:%d\n", listLength(head));insertNode(head, 0, 10); // 在空链表中插入第一个节点printf("插入后的链表元素:");printList(head);insertNode(head, 0, 5); // 在链表头部插入节点insertNode(head, 1, 15); // 在链表中间插入节点insertNode(head, 3, 20); // 在链表尾部插入节点printf("插入后的链表元素:");printList(head);deleteNode(head, 0); // 删除头结点deleteNode(head, 1); // 删除链表中的某个节点deleteNode(head, 2); // 删除尾节点printf("删除后的链表元素:");printList(head);int data1 = getNodeData(head, 0); // 取链表头结点的数据int data2 = getNodeData(head, 1); // 取链表中间某个节点的数据int data3 = getNodeData(head, 2); // 取链表尾节点的数据printf("取节点值的结果:\n");printf("Position 0: %d\n", data1);printf("Position 1: %d\n", data2);printf("Position 2: %d\n", data3);return 0;
}
9.测试情况
进行测试结果分析
初始化链表后,链表为空,元素个数为0。
在空链表中插入第一个节点,插入后的链表元素为10。可以看到插入操作正常。
在链表头部插入节点5,链表中间插入节点15,链表尾部插入节点20。插入后的链表元素为5 15 10 20。可以看到在不同位置插入节点的操作正常。
删除头结点,删除链表中的某个节点,删除尾节点。删除后的链表元素为5 10。可以看到删除操作正常。
取链表头结点的数据,取链表中间某个节点的数据,取链表尾节点的数据。取节点值的结果如下:
Position 0: 5
Position 1: 10
Position 2: -1
可以看到,成功获取了节点的值,并且当位置越界时返回了-1。说明获取节点值的功能正常。
综上所述,根据测试结果,代码实现了链表的基本操作,并且功能正常。
描述存在的问题及建议
存在的问题是在插入和删除节点时没有进行越界检查,可能导致访问非法内存。建议在插入和删除节点的代码中增加对位置的合法性检查,确保不会越界。
另外,代码中的打印函数printList()可以优化,避免每次都要遍历整个链表才能打印出结果。可以考虑在插入、删除和修改节点时维护链表的长度,并在需要打印时直接使用链表长度进行循环打印。这样可以提高效率。
相关文章:

上机实验二 设计单循环链表 西安石油大学数据结构
实验名称:设计单循环链表 (1)实验目的:掌握线性表的链式存储结构;掌握单循环链表及其基本操作的实现。 (2)主要内容:实现单循环链表的初始化、求数据元素个数、插入、删除、取数据元素等操作;用插入法建立带头结点的单循环链表;设计一个测试主函数验证…...

小谈设计模式(28)—解释器模式
小谈设计模式(28)—解释器模式 专栏介绍专栏地址专栏介绍 解释器模式角色分析抽象表达式(Abstract Expression)终结符表达式(Terminal Expression)非终结符表达式(Non-terminal Expression&…...
Access denied for user ‘root‘@‘xxx‘ (using password: YES)
Access denied for user rootxxx (using password: YES) 这表示MySQL服务端拒绝来自xxx主机的root用户登录,尽管我检查了一下,root的用户名和密码都没错,还是拒绝。 解决方案: select user,host from mysql.user; 执行发现&am…...
对象与成员函数指针 function+bind
functionbind的理解 function模板类的构造函数,把对象与成员函数绑定,重载了(),利用对象调用成员函数 bind模板函数,把对象与成员函数绑定,返回function对象,成员函数传参代码链接点…...

如何在 PyTorch 中冻结模型权重以进行迁移学习:分步教程
一、说明 迁移学习是一种机器学习技术,其中预先训练的模型适用于新的但类似的问题。迁移学习的关键步骤之一是能够冻结预训练模型的层,以便在训练期间仅更新网络的某些部分。当您想要保留预训练模型已经学习的特征时,冻结至关重要。在本教程中…...

代码随想录算法训练营第六十二、六十三天 | 单调栈 part 2 | 503.下一个更大元素II 、42. 接雨水、84.柱状图中最大的矩形
目录 503.下一个更大元素II思路代码 42. 接雨水思路一 双指针思路二 单调栈代码 84.柱状图中最大的矩形思路一 双指针思路二 单调栈代码 503.下一个更大元素II Leetcode 思路 将数组乘2来遍历即可,就是加长版的每日温度。 但是处理起来会有细节,如果…...

c#设计模式-行为型模式 之 迭代器模式
🚀简介 提供一个对象来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。 迭代器模式主要包含以下角色: 抽象聚合(Aggregate)角色:定义存储、添加、删除聚合元素以及创建迭代器对象的接口…...

SSM整合RabbitMQ,Spring4.x整合RabbitMQ
SSM整合RabbitMQ目录 前言版本实现目录参考pom.xml依赖rabbitmq.properties配置文件spring-rabbitmq.xmlspring-mvc.xml或applicationContext.xmlrabbitmq目录下MessageConsumer.javaMessageConsumer2.javaMessageProducer.javaMessageConstant.java 测试调用 扩展消息重发方式…...

【2023研电赛】商业计划书赛道上海市一等奖:基于双矢量优化谐波预测控制的MMC-PET光伏储能系统
该作品参与极术社区组织的2023研电赛作品征集活动,欢迎同学们投稿,获取作品传播推广,并有丰富礼品哦~ 团队介绍 参赛单位:上海理工大学 参赛队伍:Dream explorers 参赛队员:吕哲 李天皓 赵安杰 项目意义…...

minio桶命名规则
一、背景 今天做项目需要上传图片到minio,上传失败,查看错误是桶未创建成功。 minio桶的创建具有自己的命名规则,不符合则无法创建。 二、命名规则 1、存储桶名称的长度必须介于 3(最小)到 63(最大&…...

【教学类-35-04】学号+姓名+班级(中3班)学号字帖(A4竖版2份 竖版长条)
图片展示: 背景需求: 2022年9-2023年1月我去过小3班带班,但是没有在这个班级投放过学具,本周五是我在本学期第一次带中3班,所以提供了一套学号描字帖。先让我把孩子的名字和脸混个眼熟。 之前试过一页两套名字的纸张切割方法有:…...

什么叫AI自动直播?
AI自动直播是一种使用人工智能技术进行自动直播的程序或系统。 它可以自动录制视频,并在直播平台上进行展示,以吸引观众并提高品牌知名度。AI自动直播通常需要使用特定的软件或平台来实现,并且需要具备一定的编程和人工智能知识。 AI自动直…...

LLaMA Adapter和LLaMA Adapter V2
LLaMA Adapter论文地址: https://arxiv.org/pdf/2303.16199.pdf LLaMA Adapter V2论文地址: https://arxiv.org/pdf/2304.15010.pdf LLaMA Adapter效果展示地址: LLaMA Adapter 双语多模态通用模型 为你写诗 - 知乎 LLaMA Adapter GitH…...

高压放大器在软体机器人领域的应用
软体机器人是一种新型机器人技术,与传统的硬体机器人有着很大的不同。软体机器人通常由柔软的材料制成,具有高度的柔韧性和灵活性,并且可以实现多种形状和动作。但是,软体机器人的发展面临很多技术挑战,其中之一就是控…...
《Linux C/C++服务器开发实践》之第4章 TCP服务器编程
《Linux C/C服务器开发实践》之第4章 TCP服务器编程 4.1 套接字的基本概念4.2 网络程序的架构4.3 IP地址的格式转换4.1.c 4.4 套接字的类型4.5 套接字地址4.5.1 通用socket地址4.5.2 专用socket地址4.5.3 获取套接字地址4.2.c 4.6 主机字节序和网络字节序4.3.c 4.7 协议族和地址…...
HCIA---静态路由扩展配置
静态的扩展配置: 1、负载均衡:当访问相同目标,具有多条开销相似路径时;可以让设备将流量拆分后延多条路径同时传输;起到带宽叠加的作用; 2、环回接口-- 创建后,可用于路由器测试TCP/IP协议组件…...

OCP Java17 SE Developers 复习题04
答案 F. Line 5 does not compile. This question is checking to see whether you are paying attention to the types. numFish is an int, and 1 is an int. Therefore, we use numeric addition and get 5. The problem is that we cant store an int in a String variab…...

spark中使用flatmap报错:TypeError: ‘int‘ object is not subscriptable
1、背景描述 菜鸟笔者在运行下面代码时发生了报错: from pyspark import SparkContextsc SparkContext("local", "apple1012")rdd sc.parallelize([[1, 2], 3, [7, 5, 6]])rdd1 rdd.flatMap(lambda x: x) print(rdd1.collect())报错描述如…...
node.js知识系列(5)-每天了解一点
目录 21. RESTful API 设计中的 HTTP 动词22. 中间件链和回调地狱23. Express.js 的 ORM 经验24. 错误处理中间件和 HTTP 状态码25. 事件循环(Event Loop)在异步编程中的作用26. Node.js 缓存机制27. Node.js 全局对象28. 性能分析和调优经验29. Express…...
Linux服务器(银河麒麟、CentOS 7+、CentOS 7+ 等)修改IP地址
打开终端或控制台,以root或具有sudo权限的用户身份登录。根据你的Linux发行版和网络管理工具的不同,相应的命令可能略有不同。使用以下命令编辑网络配置文件,例如eth0网卡的配置文件: 注意:ifcfg-eth0 可能会有不同的命…...
[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解
突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 安全措施依赖问题 GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

超短脉冲激光自聚焦效应
前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应,这是一种非线性光学现象,主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场,对材料产生非线性响应,可能…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
高防服务器能够抵御哪些网络攻击呢?
高防服务器作为一种有着高度防御能力的服务器,可以帮助网站应对分布式拒绝服务攻击,有效识别和清理一些恶意的网络流量,为用户提供安全且稳定的网络环境,那么,高防服务器一般都可以抵御哪些网络攻击呢?下面…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...

认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...

【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...
用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章
用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章 摘要: 操作系统内核的安全性、稳定性至关重要。传统 Linux 内核模块开发长期依赖于 C 语言,受限于 C 语言本身的内存安全和并发安全问题,开发复杂模块极易引入难以…...