C++ 动态单链表基础

CCF-GESP三级C++考试真题解析与备考指南 C++编程语言作为计算机科学教育的核心基础,其指针与内存管理机制是理解程序运行原理的关键技术点。通过动态内存分配和链表操作等实践,开发者能够深入掌握计算机系统的资源管理方式。在算法层面,排序和搜索等基础算法不仅是编程竞赛的常见考点,更是软件开发中的高频应用场景。本文以CCF-GESP三级认证考试为切入点,详细解析了字符串处理、结构体应用、冒泡排序优化等典型题型,特别针对指针操作和内存泄漏等常见问题提供了解决方案。对于准备认证考试的开发者,理解这些基础概念并通过真题训练加以实践,能够有效提升编程能力和问题解决 阅读详情

这篇博客主要是带助教,好多学生提问了,就参考一篇博客稍微修改了一下

1.什么是链表

这里我只用一个简单的例子——线性单向链表为例,说明C语言是如何实现该结构的。
链表的元素是由结构体来实现struct Student *p。结构体中有一个成员是结构体指针struct Student *next,而这个结构体指针的类型和此结构体类型相同。除链表最后一个元素外,每一个结构体的指针都指向链表中下一个元素的结构体,最后一个元素的结构体指针为空(NULL)。保存链表时,只需要记录下链表的头指针,即链表中第一个结构体的地址即可。添加一个链表元素时,都需要单独申请一段内存;删除时则将其释放掉。在查找链表时,只需要顺着结构体指针的顺序一个一个往下查找,直到查找的结构体中的成员指针。

2.链表操作

链表的操作分为——创建表、插入元素、删除元素、清空表、查找表、打印表。其中插入/删除的元素可以是一个也可以说多个。链表从存储类型上来分可以分为静态链表和动态链表,静态链表是事先编写好的链表,占用的内存是静态存储区的内存,使用时不可以对其中的元素进行删减,只能查找;动态链表是按照程序要求生成的链表,存放于动态存储区,结构比较灵活,每一个元素都占据一部分存储空间,如果要删除元素,则释放该位置的内存;如果要添加元素,则申请一个结构体内存区的内存。

3.创建表 input

创建链表需要两个指针,一个作为先行指针(*p1),开辟内存并保存结构体的值;一个作为缓存指针(*p2),保留先行指针的所有值并且将它的next指向先行指针。构建链表时,先行指针赋一个值,后行指针保存一个值并且后行指针的next指向先行指针。赋值终止时,先行指针的next指向NULL,同时将先行指针赋值给后行指针,链表即构建完毕

4.删除元素 deletee

删除元素链表的第n个元素只需要将第n-1个元素的next指针指向第n+1个元素,再将第n个元素的内存释放即可,我这里是写的其中一个例子,根据关键字学号(int stdID)删除表中的某个元素,同时返回删除后的链表首地址(如果删的是第一个元素,则链表首地址会变)

5.插入元素 insertt

插入元素的原理是,假设要在第n个元素前插入一个元素。首先判断它是不是首元素,如果是,则修改头指针指向该元素,并将该元素的next指向原来的头指针。如果不是首元素,是第k个元素之前插入一个元素,则将第k-1个元素的next指针指向插入元素(或者子表)的地址(或者头指针),将插入元素的next指针(或尾指针)指向第k个元素。本示例代码是根据一个学号(主要关键字)插入一个元素(或者子表)的函数,返回链表的首地址(因为如果在第一个元素前面插入,可能改变链表的首地址)。

6.判断某个学生信息是否存在 isexist

在整个链表中通过学号ID查找,查找到了则返回,这里学号是唯一的没有相同的学号。

7.输出整个链表 output

从链表头开始遍历

8.操作流程

在这里插入图片描述
插入元素是指在某个元素之前插入,这里通过学号判断
在这里插入图片描述
在这里插入图片描述
续表是指在当前链表末尾输入元素,和前面的插入不一样
在这里插入图片描述
代码如下:

#include<iostream>
#include <malloc.h>
#include <stdbool.h>
#define LEN sizeof(struct Student)//定义结构体变量的大小为符号常量LEN
using namespace std;

struct Student{
	int ID;//学号
	string name;//姓名
	float height;//身高
	float weight;//体重
	float BMI;//BMI指数,录入时不需要计算
	struct Student *next;//指向下一个结构体
};
struct Student *input();//输入函数
void output(struct Student * head);//输出函数
struct Student *deletee(struct Student *head,int stdID);//删除一个元素,返回删除后表的头指针
struct Student *insertt(struct Student *head,int stdID,struct Student *insertstd);//返回插入元素(子表)后的头指针
int append(struct Student *head);//插入一个链表,从input函数输入
struct Student *isexist(struct Student *head,int stdID);

int main()
{
	struct Student *present;//当前链表的头指针
	int choice;
	bool next;
	int stdID;
	/*
	1:插入一个元素
	2:删除一个元素
	3:续表
	4:查找表
	*/
	printf("**********动态链表实验**********\n初始化一个链表:\n");
	present=input();//当前的链表指针
	do{
		printf("请选择:\n|1:插入元素(子表)\n|2:删除元素\n|3:续表\n|4:查找表\n");
		scanf("%d",&choice);
		switch(choice)
		{
			case 1:
				printf("请输入插入地点的后一个同学的学号: ");
				scanf("%d",&stdID);
				if(isexist(present,stdID)==NULL)
				{
					printf("该学生不存在!\n");
					break;//退出switch语句
				}
				present=insertt(present,stdID,input());
				printf("插入元素后的链表为:\n");
				output(present);
				break;
			case 2:
				printf("请输入删除元素的学号:  ");
				scanf("%d",&stdID);
				if(isexist(present,stdID)==NULL)
				{
					printf("该学生不存在!\n");
					break;//退出switch语句
				}
				present=deletee(present,stdID);
				printf("删除后的链表为:\n");
				output(present);
				break;
			case 3:
				append(present);
				printf("续表后的链表为:\n");
				output(present);
				break;
			case 4:
				printf("当前链表为:\n");
				output(present);
				break;
		}
		printf("是否继续(Yes:1,No:0):  ");
		scanf("%d",&next);
		fflush(stdin);
	}while(next);


	return 0;
}


struct Student * input()
{
	struct Student *p1,*p2,*head=NULL;
	printf("************************动态链表实验***********************\n【输入动态链表】\n");
	printf("请依次输入学号	姓名  身高(cm)  体重(kg)(用空格间隔,学号输入0结束):\n");
	p2=p1=(struct Student *)malloc(LEN);//开辟内存
	scanf("%d %s %f %f",&p1->ID,&p1->name,&p1->height,&p1->weight);
	if(p1->ID==0)return(head);
	else head=p1;
	while(p1->ID!=0)
	{
		p2->next=p1;
		p2=p1;
		p2->BMI=(float)p2->weight/(p2->height/100)/(p2->height/100);//求BMI指数
		p1=(struct Student *)malloc(LEN);//开辟内存
		scanf("%d",&p1->ID);
        if(p1->ID)
            scanf("%s %f %f",&p1->name,&p1->height,&p1->weight);
	}
	p2->next=NULL;
	return(head);//返回链表头指针
}

void output(struct Student *head)
{
	struct Student *p;
	int num=1;
	p=head;//将头指针地址传给p
	printf("【输出动态链表】\n");
	printf("|学号\t\t|姓名\t|身高\t|体重\t|BMI\n");
	while(p!=NULL)
	{
		printf("%3d|%08d\t|%s\t|%5.2f\t|%5.2f\t|%lf\n",num++,p->ID,p->name,p->height,p->weight,p->BMI);
		p=p->next;
	}
}

struct Student *deletee(struct Student *head,int stdID)
{
	struct Student *p1,*p2;
	if(head->ID==stdID)
	{
		p1=head->next;
		free(head);
		return p1;
	}//如果删除的是第一个元素,比较特殊,需要修改头指针,其余不动
	//剩余几种情况都是修改next结构体指针
	for(p1=head;p1!=NULL;p2=p1,p1=p1->next)//p1指针和p2指针同时查找,p1指向当前的学生,p2保指向了上一个学生
	{
		if(p1->ID==stdID)
		{
		 	p2->next=p1->next;//假设找到了需要删除的学生的学号,则让它上一个学生的指针指向跳过他的下一个学生
		 	free(p1);
		 	return head;
		}
	}
	return NULL;//返回NULL代表没找到
}

struct Student *insertt(struct Student *head,int stdID,struct Student *insertstd)
{
	struct Student *p1,*p2,*p;
	for(p=insertstd;p->next!=NULL;p=p->next);//找到insert链表的最后一个元素
	if(head->ID==stdID)
	{
		p->next=head;
		return insertstd;
	}

	for(p1=head;p1!=NULL;p2=p1,p1=p1->next)
	{
		if(p1->ID==stdID)
		{
			p2->next=insertstd;
			p->next=p1;
			return head;
		}
	}
	return NULL;
}

int append(struct Student *head)//插入一个链表,从input函数输入
{
	struct Student *p;
	for(p=head;p->next!=NULL;p=p->next);//找到head链表的最后一个元素
	p->next=input();//从input输入需要添加的元素,可以是1个或者多个
}

struct Student *isexist(struct Student *head,int stdID)
{
	struct Student *p;
	for(p=head;p!=NULL;p=p->next)
	{
		if(p->ID==stdID)
		{
			return p;
		}
	}
	return NULL;
}


C++单链表实现详解与实战应用 单链表是一种常见的数据结构,它是通过一系列节点构成,每个节点包含数据本身和指向下一个节点的指针。相较于静态数组,单链表的长度是不固定的,能够根据需要动态地添加或删除节点。 阅读详情

相关推荐

Flutter UI代码生成实战:Cursor与MCP的企业级规范适配

本文探讨了在企业级Flutter项目中,如何通过配置Cursor Rules与定制Figma MCP工具,为AI代码生成设定严格的开发规范。该方法解决了AI生成代码与现有项目架构、命名约定及资源引用规范脱节的核心痛点,实现了从Figma设计稿到高质量、可维护Flutter UI代码的自动化流程,显著提升团队协作效率与代码一致性。

http9protocoller的博客 280

一篇文章,让你真正弄懂动态链表(c++版本)

动态链表模板

qq_62510419的博客 1086

立创开源:基于STM32F407的大疆M30T无人机PSDK机载开发板硬件设计与飞行控制实现

本文详细介绍了基于STM32F407微控制器为大疆M30T无人机设计PSDK机载开发板的完整流程。从关键的E-Port接口电路设计、电源保护,到STM32最小系统搭建,再到通过PSDK实现与无人机的通信及基础飞行控制,提供了从硬件到软件的全栈实战指南,助力开发者快速入门无人机负载开发。

weixin_35649491的博客 401

动态链表的创建以及对链表的基本操作

动态创建链表,对链表基础的插入,删除等操作

qq_65109416的博客 641

Isograph工具解析:FTA、RBD、FMECA与ETA在可靠性工程中的实战应用

可靠性工程是确保复杂系统安全稳定运行的核心学科,它通过量化方法评估和提升系统在特定条件下的无故障运行能力。其基本原理涉及对系统失效模式、概率及影响进行建模与分析,旨在将定性的工程经验转化为定量的决策依据。在工程实践中,故障树分析(FTA)和可靠性框图(RBD)是两种互为补充的关键技术:FTA采用自上而下的演绎逻辑,追溯导致顶事件发生的所有可能故障组合;RBD则采用自下而上的归纳逻辑,描述系统成功运行所需的功能结构关系。这些分析技术的工程价值在于能够提前识别设计薄弱环节,量化风险,并指导设计优化与维修策略制定

weixin_42522009的博客 317

恶意代码分析实战——使用Apatedns和Inetsim模拟网络环境

恶意代码分析实战——使用Apatedns和Inetsim模拟网络环境 注:本次实验主要是《恶意代码分析实战》一书中进入动态恶意代码分析篇章的开始,主要通过Apatedns以及Inetsim来模拟为恶意代码提供其需要的网络环境,本次实验以Lab01-03.exe为例。 一、实验环境及工具。 Vmware虚拟机:win10(win7)、kali 主要工具:Apatedns、Inetsim 二、工具的安装下载 1、Apatedns:需安装至windows虚拟机客户端(win10,win7均可) 下载地址:http

妙蛙种子吃了都会妙妙秒的妙脆角的博客 7936

共用体

有时需要使几种不同类型的变量存放到同一段内存单元中。例如可以一个整形变量,一个字符型变量,一个实型变量放在同一地址开始的内存单元中。以上3个变量在内存单元中占的字节数不同,但是都从同一地址开始存放。也就是使用覆盖技术,几个变量互相覆盖。 共用体也是一种构造数据类型,它是将不同类型的变量存放在同一内存区域内。共用体也称为联合(union)。共用体的类型定义、变量定义及引用方式与

6069

焦距与视差的关系及其对深度估计的影响

焦距在立体视觉中的作用至关重要,它直接影响视差的大小,从而影响深度估计的精度。焦距越长,视差差异越大,物体的深度估计就越精确。这一关系使得焦距长的相机在一些需要高精度深度估计的应用场景中更加优越。了解焦距与视差的关系,对于优化相机配置和提升深度估计精度具有重要意义。在实践中,选择合适的焦距对于获得精确的深度信息至关重要,特别是在自动驾驶、虚拟现实、三维重建等领域,精确的深度估计能够提供更好的用户体验和技术支持。

计算机科学与技术专业学生的成长之路 1672

7.2 C/C++ 实现动态链表

动态链表是一种常用的动态数据结构,可以在运行时动态地申请内存空间来存储数据,相比于静态数组和静态链表,更加灵活和高效。在动态链表中,数据元素被组织成一条链表,每个元素包含了指向下一个元素的指针,这样就可以通过指针将所有元素串联起来。 使用动态链表存储数据时,不需要预先申请内存空间,而是在需要的时候才向内存申请。当需要添加新的元素时,可以使用`malloc`函数动态地申请内存空间,然后将新的元素插入到链表中;当需要删除元素时,可以使用`free`函数释放元素占用的内存空间,然后将链表中的指针重新连接。

微软技术分享 1万+

仿真模型简单介绍

同时,各种以伯克利的Spice仿真程序的算法为核心的商用Spice电路仿真工具也随之产生,运行在PC和UNIX平台,许多都是基于原始的SPICE2G6版的源代码,这是一个公开发表的版本,它们都在Spice的基础上做了很多实用化的工作,比较常见的Spice仿真软件有HSpice、Pspice、Spectre、Tspice、SmartSpcie、IsSpice等,虽然它们的核心算法雷同,但仿真速度、精度和收敛性却不一样,其中以Synopsys公司的Hspice和Cadence公司的Pspice最为著名。...

小幽余生不加糖 8004

卫朋:IPD流程落地之产品开发验证阶段解读

IPD验证阶段

产品线负责人 1488

动态链表详解:

详细讲解动态链表的建立过程与链表的原理,深度理解链表的基本组成结构

wwx1239021388的博客 5840

R语言机器学习算法实战系列(十一)MLP算法分类器 (Multi-Layer Perceptrons)

本文介绍了多层感知器(MLP)分类算法的原理和计算步骤,并通过R语言实现MLP模型。MLP是一种前馈神经网络,包含输入层、隐藏层和输出层,通过激活函数引入非线性,利用前向传播和反向传播进行训练。文章详细描述了数据预处理、数据切割、模型构建、预测和评估等步骤,并提供了乳腺癌数据集(BreastCancer_clean.csv)的下载链接。通过R包如neuralnet和caret,读者可以逐步实现MLP模型,并评估其分类性能。

专注生信领域 933

【C++】单链表(有指针)

链表是c++的一种数据结构

李嘉佑的博客 1070

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

【数据结构】单链表

在学习数据结构时,单链表可谓是第一个需要跨越的台阶。从C语言到数据结构,单链表能够真正的反映我们C语言到底学的扎不扎实,那是因为,单链表对于C语言中的指针,结构体,以及函数模块的实现有较高的要求。因此,通过本章的学习,要是能够自我实现单链表,那你的C语言功底会厚实,你的代码能力也会提升。当然,从C语言到数据结构阶段,单链表只是第一个需要跨越的台阶,后面还有更难的数据结构在等着大家,后面我会相继出文章。对于单链表来说,其难度主要在于对指针的运用,能够自我实现单链表,对我们代码能力的提升有很大的帮助。

Welcome home | Jian Liao 's blog 1072

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

单链表图解及模板总结

静态链表 如果说用结构体+指针的方式实现链表和栈的话,每次需要new一个新节点,非常慢。笔试题链表大小在10万级别,因此笔试题一般不会采用这种动态链表的方式。通常采用数组模拟链表的方式,这种方式更快。 struct Node { int val; Node *next; }; new Node(); 链表与邻接表 邻接表 邻接表的head[i]存储的是节点i所有的临边。实际上就是一个单链表。 用数组模拟单链表 单链表里常用的是邻接表。邻接表主要用来存储图和数。 双链表常用来优化某些问题。 链表的

timerring的博客 3280

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

单链表(1)-单链表尾插法

摘要:本文介绍了单链表的基本概念和C++实现。单链表由节点组成,每个节点包含数据和指向下个节点的指针。头节点用于简化操作,头指针指向链表的首个节点。文中详细讲解了一个带头节点的单链表类Clink的实现,包括构造函数、尾插法插入节点等核心功能。代码示例展示了如何使用尾插法在链表末尾添加新节点,通过遍历找到尾节点后插入。文章还涉及C++命名空间std的使用及其潜在风险。链表通过动态内存分配实现,但示例中未完成内存释放的析构函数实现。

Sunnyrain_X的博客 1083

蓝桥杯C++基础算法-单链表(数组模拟)

这段代码实现了一个基于单链表的数据结构,支持在头部插入、在指定位置插入以及删除指定位置的元素。以下是代码的详细思路解析

2301_77989601的博客 521

数据结构与算法精解:单链表

本文详细介绍了单链表的实现方法,主要包括以下几个部分:1. 实现思想:单链表是一种线性、动态、非连续存储的数据结构,支持插入、删除、遍历等操作;2. 数据结构设计:定义了结点结构体,包含数据域和指针域;3. 接口函数:实现了初始化、检查、插入(前插/后插)、删除、查找、遍历等20余个核心操作函数;4. 具体实现:提供了带头结点和不带头结点两种实现方式,以及头插法和尾插法两种建立链表的方法。通过详细的函数定义和代码实现,完整展示了单链表的操作逻辑和实现原理。

WildPointer的博客 931

单链表完全指南:从原理到C++实现

本文详细介绍了单链表的C++实现方法,包括其基本结构、核心操作和时间效率分析。主要内容涵盖:单链表的节点结构定义(数据域+指针域)、初始化、判空、销毁等基础操作;查找、插入和删除等核心功能实现;头插法和尾插法两种创建方式;完整代码示例及测试程序。文章还分析了各操作的时间复杂度(初始化O(1),查找/插入/删除O(n)),比较了链表的优缺点(动态扩展优势vs查找效率劣势)。单链表作为基础数据结构,其指针操作原理是学习更复杂结构的重要基础,建议通过实践编码加深理解。

weixin_73292581的博客 797

826. 单链表(数组模拟链表)

826. 单链表 实现一个单链表,链表初始为空,支持三种操作: 向链表头插入一个数; 删除第 k 个插入的数后面的数; 在第 k 个插入的数后插入一个数。 现在要对该链表进行 M 次操作,进行完所有操作后,从头到尾输出整个链表。 注意:题目中第 k 个插入的数并不是指当前链表的第 k 个数。例如操作过程中一共插入了 n 个数,则按照插入的时间顺序,这 n 个数依次为:第 1 个插入的数,第 2 个插入的数,…第 n 个插入的数。 输入格式 第一行包含整数 M,表示操作次数。 接下来 M 行,每行包含一个

是微风,是晚霞,是无可替代 224

数据结构入门|用C++基础实现线性表(顺序表+单链表,新手友好)

本文用C++基础语法实现了线性表的两种形式:顺序表和单链表。顺序表采用动态数组实现,重点解决扩容和元素移动问题;单链表通过节点结构体和指针操作实现,强调指针遍历和节点修改。作者分享了实现过程中的常见错误,如内存泄漏、指针操作错误等,并比较了两种实现方式的优缺点。最后指出顺序表适合频繁查询,链表适合频繁修改的场景。文章采用通俗易懂的语言,适合数据结构初学者理解线性表的基本实现原理。

2502_93058859的博客 1594

day1数组基础实现

每天学一点

2301_80434259的博客 167

数据结构-单链表的使用(附有源码可编译)

数据结构-单链表的使用(附有源码可编译) 以及涉及到链表的引入 1-链表的初始化 2-建立一个单链表 3-插入运算 4-删除运算 5-求表长 6-查找运算的使用

m0_61196970的博客 485

链表详解及C++实现

使用模板类定义节点,确保链表可适配多种数据类型。单链表节点包含数据域和一个后继指针;双向链表节点额外增加一个前驱指针。指针链表是C++中指针应用的经典场景,核心在于通过指针串联离散节点,实现高效的插入/删除操作。本文详细讲解了单链表和双向链表的概念、设计思路,并用模板类实现了完整的链表操作,包括插入、删除、遍历、查找等核心功能,同时提供了测试代码和运行结果。

qq_43402143的博客 1514

AcWing 826. 单链表 (模板题 链表)

实现一个单链表,链表初始为空,支持三种操作: 向链表头插入一个数; 删除第 k 个插入的数后面的数; 在第 k 个插入的数后插入一个数。 现在要对该链表进行 M 次操作,进行完所有操作后,从头到尾输出整个链表。 注意:题目中第 k 个插入的数并不是指当前链表的第 k 个数。例如操作过程中一共插入了 n 个数,则按照插入的时间顺序,这 n 个数依次为:第 1 个插入的数,第 2 个插入的数,…第 n 个插入的数。 输入格式 第一行包含整数 M,表示操作次数。 接下来 M 行,每行包含一个操作命令,操作命令可能

m0_58245389的博客 348
上一篇: ES6初学者环境搭建(Babel)
下一篇: C++ 数组作为函数形参
CT_WJ
博客等级 码龄8年 19粉丝 35原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值