基础链表代码实现

news2024/11/26 4:42:23

我们以题目为切入点,深入了解链表代码实现。

题目(单项链表)

题目描述

实现一个数据结构,维护一张表(最初只有一个元素 1)。需要支持下面的操作,其中 x 和 y 都是 1 到 1000000 范围内的正整数,且保证任何时间表中所有数字均不相同,操作数量不多于 100000:

  • 1 x y :将元素 y 插入到 x 后面;
  • 2 x :询问 x 后面的元素是什么。如果 x 是最后一个元素,则输出 0;
  • 3 x:从表中删除元素 x 后面的那个元素,不改变其他元素的先后顺序。

输入格式

第一行一个整数 q 表示操作次数。

接下来 q 行,每行表示一次操作,操作具体间题目描述。

输出格式

对于每个操作 2,输出一个数字,用换行隔开。

输入输出样例

输入 #1

6
1 1 99
1 99 50
1 99 75
2 99
3 75
2 1

输出 #1

75
99

代码解析:

首先说清楚,这道题我并没有完完全全写出来,时间超限了。我觉得这道题比较经典,所以写这篇博客。主要是用来捋清楚链表代码流程。

头文件

#include <stdio.h>//c语言一般都要有
#include <stdlib.h>//链表的实现需要这个库函数的free和malloc函数
free函数

free 函数在 C 语言中用于释放之前通过 malloccalloc 或 realloc 函数分配的内存。当你不再需要一块动态分配的内存时,应当使用 free 来释放它,以避免内存泄漏

函数原型:

void free(void *ptr);

其中,ptr 是一个指向之前分配的内存块的指针。这个指针必须是 malloccalloc 或 realloc 返回的指针,或者是这些指针的副本(即,指向相同内存地址的指针)。

//释放特定内存
int *ptr = (int *)malloc(sizeof(int));  
if (ptr != NULL) {  
    // 使用 ptr  
    free(ptr); // 释放内存  
    ptr = NULL; // 将指针设为 NULL,防止悬挂指针  
}
//释放连续内存
int *array = (int *)malloc(10 * sizeof(int));  
if (array != NULL) {  
    // 使用 array  
    free(array); // 释放整个数组  
    array = NULL; // 将指针设为 NULL  
}
malloc函数

malloc 是 C 语言标准库中的一个函数,用于在堆区分配指定大小的内存空间。

函数原型:

void* malloc(size_t size);

其中,size 是要分配的内存块的大小(以字节为单位)。malloc 函数返回一个指向新分配内存的指针,如果分配成功,该指针指向被分配的内存的首地址;如果分配失败,则返回 NULL

数组内存分配

int *array = (int *)malloc(10 * sizeof(int));

检查返回值:始终检查 malloc 的返回值是否为 NULL。如果返回 NULL,则表示内存分配失败,可能是因为内存不足。如下:

int *array = (int *)malloc(10 * sizeof(int));  
if (array == NULL) {  
    // 处理错误,例如输出错误信息并退出程序  
    fprintf(stderr, "Memory allocation failed.\n");  
    exit(EXIT_FAILURE);  
}

在使用 malloc 时,请确保在程序的适当位置释放所有分配的内存,以避免内存泄漏。此外,由于 malloc 只负责分配内存,不负责初始化内存,因此在使用分配的内存之前,请确保对其进行适当的初始化。 

exit函数

exit 函数是 C 语言标准库中的一个函数,用于立即终止程序的执行。

函数原型:

void exit(int status);

其中,status 是一个整数值,通常用于向操作系统返回程序的退出状态。通常,如果程序正常退出,status 应该是 EXIT_SUCCESS(在 <stdlib.h> 中定义,通常为 0);如果程序因为某种错误而退出,status 应该是 EXIT_FAILURE(同样在 <stdlib.h> 中定义,通常为 1)。

使用例子:

#include <stdio.h>  
#include <stdlib.h>  
  
int main() {  
    // 假设发生了某种错误  
    if (/* 错误条件 */) {  
        fprintf(stderr, "An error occurred, exiting the program.\n");  
        exit(EXIT_FAILURE); // 退出程序,返回错误状态码  
    }  
  
    // 程序继续执行...  
  
    exit(EXIT_SUCCESS); // 程序正常退出  
}

此外,exit 函数与 return 语句不同。return 语句用于从当前函数中返回,而 exit 则用于终止整个程序。如果你在 main 函数中使用 return 语句,它的效果与调用 exit 是相同的,都会结束程序的执行。然而,exit 可以在任何函数中被调用,而不仅仅是 main 函数。

结构体的建立

typedef struct Node {
	int value;
	struct Node* next;
}Node;

Node* head = NULL;//链表的表头

主函数

主函数是主干。

int main()
{
	head = (Node*)malloc(sizeof(Node));
	head->value = 1;//题目要求第一个为1
	head->next = NULL;//初始化

	int n;//操作次数
	scanf("%d", &n);//输入
	while (n--) {
		int m, x, y;//m为操作指令,可以用switch语句来实现
		scanf("%d%d", &m, &x);
		switch (m)
		{
		case 1://元素插入
			scanf("%d", &y);
			charu(x, y);
			break;//不要忘了
		case 2://元素查找
			printf("%d\n",chaxun(x));
			break;//不要忘了
		case 3://元素删除
			shanchu(x);
			break;//不要忘了
		default:printf("Invalid operation.\n");//翻译过来是无效操作。
		}
	}
	return 0;
}

函数

插入函数
void charu(int x, int y)//插入
{
	Node* newNode = (Node*)malloc(sizeof(Node));
	if (newNode == NULL) {
		printf("Memory allocation failed.\n");//翻译过来是内存分配失败
		exit(1);
	}
	newNode->value = y;
	Node* p = head;
	while (p != NULL&&p->value !=x) {//如果不是空链表进入寻找x的位置
		p = p->next;
	}
	if (p->value != NULL) {//如果找到了
		newNode->next = p->next;
		p->next = newNode;
	}
	else {//如果没有找到
		printf("Element %d not found in the list.\n", x);//翻译过来是元素x未在列表中找到。
	}
}
查询函数
int chaxun(int x)
{
	Node* p = head;
	while (p != NULL && p->value != x) //如果不是空链表进入寻找x的位置
		p = p->next;
	if (p != NULL && p->next != NULL) {//如果都没有超出链表长度的话就找到查询的数字了
		return p->next->value;
	}
	else return 0;
}
删除函数
void shanchu(int x)
{
	Node* p = head;
	while (p != NULL && p->value != x) //如果不是空链表进入寻找x的位置
		p = p->next;
	if (p != NULL && p->next != NULL) {
		Node* q = p->next;
		p->next = q->next;//删除的精髓
		free(q);//空间释放
	}
	else  printf("Element %d or its successor is not found in the list.\n", x);//自己翻译吧
}

完整代码 

#include<stdio.h>
#include<stdlib.h>

typedef struct Node {
	int value;
	struct Node* next;
}Node;

Node* head = NULL;

void charu(int x, int y)//插入
{
	Node* newNode = (Node*)malloc(sizeof(Node));
	if (newNode == NULL) {
		printf("Memory allocation failed.\n");//翻译过来是内存分配失败
		exit(1);
	}
	newNode->value = y;
	Node* p = head;
	while (p != NULL&&p->value !=x) {//如果不是空链表进入寻找x的位置
		p = p->next;
	}
	if (p->value != NULL) {//如果找到了
		newNode->next = p->next;
		p->next = newNode;
	}
	else {//如果没有找到
		printf("Element %d not found in the list.\n", x);//翻译过来是元素x未在列表中找到。
	}
}

int chaxun(int x)
{
	Node* p = head;
	while (p != NULL && p->value != x) //如果不是空链表进入寻找x的位置
		p = p->next;
	if (p != NULL && p->next != NULL) {//如果都没有超出链表长度的话就找到查询的数字了
		return p->next->value;
	}
	else return 0;
}


void shanchu(int x)
{
	Node* p = head;
	while (p != NULL && p->value != x) //如果不是空链表进入寻找x的位置
		p = p->next;
	if (p != NULL && p->next != NULL) {
		Node* q = p->next;
		p->next = q->next;//删除的精髓
		free(q);//空间释放
	}
	else  printf("Element %d or its successor is not found in the list.\n", x);//自己翻译吧
}
int main()
{
	head = (Node*)malloc(sizeof(Node));
	head->value = 1;//题目要求第一个为1
	head->next = NULL;//初始化

	int n;//操作次数
	scanf("%d", &n);//输入
	while (n--) {
		int m, x, y;//m为操作指令,可以用switch语句来实现
		scanf("%d%d", &m, &x);
		switch (m)
		{
		case 1://元素插入
			scanf("%d", &y);
			charu(x, y);
			break;//不要忘了
		case 2://元素查找
			printf("%d\n", chaxun(x));
			break;//不要忘了
		case 3://元素删除
			shanchu(x);
			break;//不要忘了
		default:printf("Invalid operation.\n");//翻译过来是无效操作。
		}
	}
	return 0;
}

最后,如果有时间,我会另一种方法重新敲写一遍再发布出来。

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

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

相关文章

Java 基于 SpringBoot+Vue 的智慧外贸平台的研究与实现,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

vuex中mutations详解,与actions的区别

Vuex 的 Mutations 是用于改变 Vuex Store 中状态的一种方式。它是一个同步的操作&#xff0c;用于直接修改 Store 中的状态。 Mutations 有以下特点&#xff1a; 同步操作&#xff1a;Mutations 是同步的&#xff0c;这意味着它们会立即执行并修改状态。原子性&#xff1a;…

数据库从入门到精通(一)数据库基础操作

mysql数据库基础操作 cmd下启动mysql数据库操作命令数据库重要的删除操作数据库增删改查操作插入数据更新数据删除数据查询数据查询指定记录in查询满足指定范围之内的条件记录not in查询不在指定范围之内的条件记录带between and 的范围查询带like的字符匹配查询(d%以d开头,%d以…

猫头虎分享:2024年值得程序员关注的技术发展动向分析

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

Hadoop:认识MapReduce

MapReduce是一个用于处理大数据集的编程模型和算法框架。其优势在于能够处理大量的数据&#xff0c;通过并行化来加速计算过程。它适用于那些可以分解为多个独立子任务的计算密集型作业&#xff0c;如文本处理、数据分析和大规模数据集的聚合等。然而&#xff0c;MapReduce也有…

cron表达式介绍和使用

Cron表达式是一种用于配置定时任务的字符串&#xff0c;它由数字、字符和符号组成&#xff0c;用于指定任务在某个时间点或周期性地执行。其通常包含六个或七个字段&#xff0c;每个字段代表一个时间单位&#xff0c;如下表所示&#xff1a; 域必须取值范围特殊字符秒是[0, 59…

OpenGL-ES 学习(2)---- DepthTest

深度测试 OpenGL-ES 深度测试是指在片段着色器执行之后&#xff0c;利用深度缓冲区所保存的深度值决定当前片段是否被丢弃的过程 深度缓冲区通常和颜色缓冲区有着相同的宽度和高度&#xff0c;一般由窗口系统自动创建并将其深度值存储为 16、 24 或 32 位浮点数。(注意只保存…

EasyRecovery2024全新官方汉化中文版下载

确实&#xff0c;EasyRecovery以其强大的功能而闻名。以下是它的一些主要功能特点&#xff1a; 全面恢复能力&#xff1a;EasyRecovery可以恢复从各种存储设备中丢失的数据&#xff0c;包括硬盘、U盘、SD卡、数码相机、手机等。无论是因为误删除、格式化、分区丢失、病毒攻击还…

2-7基础算法-位运算

一.基础 位运算经常考察异或的性质、状态压缩、与位运算有关的特殊数据结构、构造题。 位运算只能应用于整数&#xff0c;且一般为非负整数&#xff0c;不能应用于字符、浮点等类型。 左移操作相当于对原数进行乘以2的幂次方的操作&#xff0c;低位补0 右移操作相当于对原数进…

Elasticsearch使用场景深入详解

Elasticsearch是一个开源的、分布式的、RESTful风格的搜索和数据分析引擎。它能够解决越来越多的用例&#xff0c;并不仅仅局限于全文搜索。以下是Elasticsearch的一些主要使用场景及其深入详解。 1. 全文搜索 Elasticsearch最初和最基本的应用场景就是全文搜索。全文搜索是指…

上位机图像处理和嵌入式模块部署(上位机主要功能)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 目前关于机器视觉方面&#xff0c;相关的软件很多。比如说商业化的halcon、vision pro、vision master&#xff0c;当然也可以用opencv、pytorch自…

第18讲 投票帖子管理实现

后端&#xff1a; /*** 删除指定id的投票信息* param id* return*/ GetMapping("/delete/{id}") Transactional public R delete(PathVariable(value "id")Integer id){voteDetailService.remove(new QueryWrapper<VoteDetail>().eq("vote_id…

clang前端

Clang可以处理C、C和Objective-C源代码 Clang简介 Clang可能指三种不同的实体&#xff1a; 前端&#xff08;在Clang库中实现&#xff09;编译驱动程序&#xff08;在clang命令和Clang驱动程序库中实现&#xff09;实际的编译器&#xff08;在clang-ccl命令中实现&#xff0…

Codeforces Round 925 (Div. 3) E. Anna and the Valentine‘s Day Gift (Java)

Codeforces Round 925 (Div. 3) E. Anna and the Valentine’s Day Gift (Java) 比赛链接&#xff1a;Codeforces Round 925 (Div. 3) E题传送门&#xff1a;E. Anna and the Valentine’s Day Gift 题目&#xff1a;E. Anna and the Valentine’s Day Gift 样例 #1 样例输…

DS:二叉树的顺序结构及堆的实现

创作不易&#xff0c;兄弟们给个三连&#xff01;&#xff01; 一、二叉树的顺序存储 顺序结构指的是利用数组来存储&#xff0c;一般只适用于表示完全二叉树&#xff0c;原因如上图&#xff0c;存储不完全二叉树会造成空间上的浪费&#xff0c;有的人又会问&#xff0c;为什么…

JVM(1)基础篇

1 初始JVM 1.1 什么是JVM JVM 全称是 Java Virtual Machine&#xff0c;中文译名 Java虚拟机。JVM 本质上是一个运行在计算机上的程序&#xff0c;他的职责是运行Java字节码文件。 Java源代码执行流程如下&#xff1a; 分为三个步骤&#xff1a; 编写Java源代码文件。 使用…

SpringBoot+Vue3 完成小红书项目

简介 该项目采用微服务架构&#xff0c;实现了前后端分离的系统设计。在前端&#xff0c;我们选择了 Vue3 配合 TypeScript 和 ElementUi 框架&#xff0c;以提升开发效率和用户体验。而在后端&#xff0c;则是运用 SpringBoot 和 Mybatis-plus 进行开发&#xff0c;保证了系统…

CFS三层靶机

参考博客&#xff1a; CFS三层内网靶场渗透记录【详细指南】 - FreeBuf网络安全行业门户 CFS三层靶机搭建及其内网渗透【附靶场环境】 | TeamsSix CFS三层网络环境靶场实战 - PANDA墨森 - 博客园 (cnblogs.com) CFS三层靶机实战--内网横向渗透 - 知乎 (zhihu.com) CFS靶机…

C++类和对象-C++对象模型和this指针->成员变量和成员函数分开存储、this指针概念、空指针访问成员函数、const修饰成员函数

#include<iostream> using namespace std; //成员变量 和 成员函数 分开储存的 class Person { public: Person() { mA 0; } //非静态成员变量占对象空间 int mA; //静态成员变量不占对象空间 static int mB; //函数也不占对象空间…

安卓价值1-如何在电脑上运行ADB

ADB&#xff08;Android Debug Bridge&#xff09;是Android平台的调试工具&#xff0c;它是一个命令行工具&#xff0c;用于与连接到计算机的Android设备进行通信和控制。ADB提供了一系列命令&#xff0c;允许开发人员执行各种操作&#xff0c;包括但不限于&#xff1a; 1. 安…