【数据结构】(C语言):链表

news2024/10/10 22:25:44

链表:

  • 基本单位是节点。节点至少两部分:数据,下一个数据的地址。
  • 头指针head,始终指向链表的第一个节点。若没有节点,则head=NULL。
  • 链表在内存中是非连续的。不能使用索引(下标)查找元素。只能从头遍历。
  • 链表有单链表、循环单链表、双链表、循环双链表。本文以单链表举例。

添加节点:(注意指向顺序,避免数据丢失)

  • 在链表头部添加:先新节点指向第一个节点,再头指针指向新节点。
  • 在链表尾部添加:最后一个节点指向新节点。
  • 在链表指定位置添加:找到指定位置,先新节点指向下一个节点,再上一个节点指向新节点。

 删除节点:

  • 删除链表头部节点:头指针指向第二个节点。
  • 删除链表尾部节点:倒数第二个节点指向NULL。
  • 删除链表指定位置节点:找到指定位置,上一个节点指向该节点的下一个节点。


 C语言代码:

创建节点(结构体数据类型),并创建具体节点实例的函数:

// 节点(结构体数据类型)
typedef struct Node
{
    int data;                 // 数据为整数
    struct Node *next;        // 指针指向下一个节点
} LinkNode;                   // 别名LinkNode
// 创建具体节点实例的函数
LinkNode * createNode(int data)
{
	LinkNode *node = (LinkNode *)malloc(sizeof(LinkNode));   // 给节点分配内存空间
	if(node == NULL)
	{
		perror("Memory allocation failed");
		exit(-1);
	}
	node->data = data;
	node->next = NULL;
	return node;
}

本文将头指针和链表长度作为全局变量:

LinkNode *header = NULL;		// 头指针,初始化指向NULL
int length = 0;				    // 统计链表元素个数

添加节点:

// 添加节点(链表头部添加)
void addtop(int data)
{
	LinkNode *node = createNode(data);       // 调用createNode函数,创建具体节点
	node->next = header;                     // 先新节点指向头指针指向的节点
	header = node;                           // 再头指针指向新节点
	length++;                                // 每添加一个数据,length+1
}
// 添加节点(链表尾部添加)
void append(int data)
{
	if(length == 0)        // 若空链表,在链表头部添加
	{
		addtop(data);
		return ;
	}

	LinkNode *node = createNode(data);

	LinkNode *cur = header;         // 从头遍历元素,找到最后
	while(cur->next != NULL)
	{
		cur = cur->next;
	}
	cur->next = node;
	length++;
}
// 添加节点(在指定位置,位置从0开始)
void insert(int location, int data)
{
	if(length == 0)    // 若空链表,在链表头部添加
	{
		addtop(data);
		return ;
	}
	if(length <= location)    // 若链表长度<=指定位置,在链表尾部添加
	{
		append(data);
		return ;
	}

	LinkNode *node = createNode(data);

	LinkNode *prev, *cur = header;      // 使用两个指针,遍历链表,找到指定位置
	while(location > 0)
	{	
		prev = cur;
		cur = cur->next;
		location--;
	}
	
	node->next = cur;
	prev->next = node;
	length++;
}

删除节点:

// 删除节点(删除链表头部节点)
void pop(void)
{
	if(length == 0) return ;   // 空链表,直接退出程序

	header = header->next;
	length--;                  // 每删除一个元素,length-1
}
// 删除节点(删除链表尾部节点)
void dellast(void)
{	
	if(length == 0) return ;       // 空链表,直接退出程序
	if(length == 1)                // 一个元素,头指针直接指向NULL
	{
		header = NULL;
		return ;
	}

	LinkNode *prev, *cur = header;     // 使用两个指针,遍历链表,直到最后的位置
	while(cur->next != NULL)
	{
		prev = cur;
		cur = cur->next;
	}
	prev->next = NULL;
	length--;
}
// 删除节点(删除链表指定位置的节点,位置从0开始)
void delat(int location)
{
	if(length == 0) return ;          // 空链表,直接退出程序
	if(length - 1 <= location)        // 链表长度-1<=指定位置,删除链表尾部节点
	{
		dellast();
		return ;
	}

	LinkNode *prev, *cur = header;     // 使用两个指针,遍历链表,直到指定位置
	while(location > 0)
	{
		prev = cur;
		cur = cur->next;
		location--;
	}
	prev->next = cur->next;
	length--;
}
// 删除节点(删除指定数据)
void del(int data)
{
	LinkNode *prev, *cur = header;      // 使用两个指针,遍历链表,比对数据内容
	while(cur != NULL)
	{
		if(cur->data == data)
		{
			if(header == cur)       // 若是第一个节点,头指针直接跳过该节点指向下一个节点
			{
				header = cur->next;
			}
			else                    // 否则 该节点上一个节点,直接跳过该节点指向下一个节点
			{
				prev->next = cur->next;
			}

			length--;
			return ;
		}
		prev = cur;
		cur = cur->next;
	}
	return ;
}

遍历节点:

void travel(void)
{
	if(length == 0) return ;       // 空链表,直接退出程序

	printf("linklist elements: ");
	LinkNode *cur = header;
	while(cur != NULL)
	{
		printf("%d \t", cur->data);
		cur = cur->next;
	}
	printf("\n");
}


完整代码:(linklist.c)

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

/* structure */
typedef struct Node			// node structure
{
	int data;
	struct Node *next;
} LinkNode;

/* global variables */
LinkNode *header = NULL;		// header pointer
int length = 0;				    // the number of linklist elements

/* function prototype */
void addtop(int data);			// add element to the top of the linklist
void append(int data);			// add element to the end of the linklist
void insert(int location, int data);	// add element to the specify location (start with 0)
void travel(void);			// show element one by one
void pop(void);				// delete element from the top of the linklist
void dellast(void);			// delete element from the end of the linklist
void delat(int location);		// delete element from the specify location (start with 0)
void del(int data);			// delete the specify data

/* main function */
int main(void)
{
	addtop(5);
	printf("length is %d \n", length);		
	travel();

	append(9);
	printf("length is %d \n", length);		
	travel();

	insert(1,8);
	printf("length is %d \n", length);		
	travel();

	addtop(3);
	printf("length is %d \n", length);		
	travel();

	pop();	
	printf("length is %d \n", length);		
	travel();

	dellast();
	printf("length is %d \n", length);		
	travel();

	delat(1);
	printf("length is %d \n", length);		
	travel();

	del(7);
	printf("length is %d \n", length);		
	travel();

	del(5);
	printf("length is %d \n", length);		
	travel();
}

/* subfunction */
LinkNode * createNode(int data)		// create a node
{
	LinkNode *node = (LinkNode *)malloc(sizeof(LinkNode));
	if(node == NULL)
	{
		perror("Memory allocation failed");
		exit(-1);
	}
	node->data = data;
	node->next = NULL;
	return node;
}

void addtop(int data)			// add element to the top of the linklist
{
	LinkNode *node = createNode(data);
	node->next = header;
	header = node;
	length++;
}

void append(int data)			// add element to the end of the linklist
{
	if(length == 0)
	{
		addtop(data);
		return ;
	}

	LinkNode *node = createNode(data);

	LinkNode *cur = header;
	while(cur->next != NULL)
	{
		cur = cur->next;
	}
	cur->next = node;
	length++;
}	

void insert(int location, int data)	// add element to the specify location (start with 0)
{
	if(length == 0)
	{
		addtop(data);
		return ;
	}
	if(length <= location)
	{
		append(data);
		return ;
	}

	LinkNode *node = createNode(data);

	LinkNode *prev, *cur = header;
	while(location > 0)
	{	
		prev = cur;
		cur = cur->next;
		location--;
	}
	
	node->next = cur;
	prev->next = node;
	length++;
}

void travel(void)			// show element one by one
{
	if(length == 0) return ;

	printf("linklist elements: ");
	LinkNode *cur = header;
	while(cur != NULL)
	{
		printf("%d \t", cur->data);
		cur = cur->next;
	}
	printf("\n");
}

void pop(void)				// delete element from the top of the linklist
{
	if(length == 0) return ;

	header = header->next;
	length--;
}

void dellast(void)			// delete element from the end of the linklist
{	
	if(length == 0) return ;
	if(length == 1)
	{
		header = NULL;
		return ;
	}

	LinkNode *prev, *cur = header;
	while(cur->next != NULL)
	{
		prev = cur;
		cur = cur->next;
	}
	prev->next = NULL;
	length--;
}

void delat(int location)		// delete element from the specify location (start with 0)
{
	if(length == 0) return ;
	if(length - 1 <= location)
	{
		dellast();
		return ;
	}

	LinkNode *prev, *cur = header;
	while(location > 0)
	{
		prev = cur;
		cur = cur->next;
		location--;
	}
	prev->next = cur->next;
	length--;
}

void del(int data)			// delete the specify data
{
	LinkNode *prev, *cur = header;
	while(cur != NULL)
	{
		if(cur->data == data)
		{
			if(header == cur)
			{
				header = cur->next;
			}
			else
			{
				prev->next = cur->next;
			}

			length--;
			return ;
		}
		prev = cur;
		cur = cur->next;
	}
	return ;
}

编译链接: gcc -o linklist linklist.c

执行可执行文件: ./linklist

 

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

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

相关文章

关于application/x-www-form-urlencoded跟application/json请求的区别

当你的java方法是这样定义的 PostMapping("/rePushMedicalRecord") public String rePushMedicalRecord(RequestParam("topicId") String topicId){ } 参数是RequestParam接收&#xff0c;则请求时需要用application/x-www-form-urlencoded请求 如果是R…

【ARMv8/v9 GIC 系列 2.3 -- GIC SPI 中断的 GICD_CLRSPI_NSR寄存器】

文章目录 GICD_CLRSPIN_NSR寄存器功能INTID 位 [12:0]中断触发类型的影响小结 GICD_CLRSPIN_NSR 在 ARMv9 架构下&#xff0c;GIC&#xff08;Generic Interrupt Controller&#xff09;是负责中断管理的关键组件&#xff0c;它支持复杂的中断处理需求&#xff0c;包括多处理器…

OS中断机制-嵌套和竞争

对于FreeRTOS最好不去用中断嵌套,中断嵌套会增加堆栈空间的使用,因为每个中断服务程序都需要保存和恢复寄存器状态,这可能会耗尽有限的堆栈空间,从而导致系统故障。以及中断嵌套时,不同的中断服务程序可能会竞争访问共享资源,从而增加死锁的风险。这可能会导致系统出现故…

第二节课 6月13日 ssh密钥登陆方式

centos和ubuntu openssh服务的初始安装 一、实验&#xff1a;ubuntu系统激活root用户 ubuntu系统如何激活root用户&#xff0c;允许root用户ssh登陆&#xff1f; 1、ubuntu默认root用户未设置密码&#xff0c;未激活 激活root用户&#xff0c;设置root密码 sudo passwd roo…

从零开始做题:修猫

修猫 1 题目 2 解题 2.1 使用Stegslove分析图片 (base) ┌──(holyeyes㉿kali2023)-[~/Misc/tool-misc] └─$ java -jar Stegsolve.jar 2.2 analyse -frame browser 2.3 得到flag DASCTF{818ca3a840e768da7d5fcdeaedd5012f}

37岁,被裁员,失业三个月,被面试官嫌弃“太水”:就这也叫10年以上工作经验?

今年部门要招两个自动化测试&#xff0c;这几个月我面试了几十位候选人。发现一个很奇怪的现象&#xff0c;面试中一问到元素定位、框架api、脚本编写之类的&#xff0c;很多候选人都对答如流。但是一问到实际项目&#xff0c;比如“项目中UI自动化和接口自动化如何搭配使用&am…

前端:HTML、CSS、JavaScript 代码注释 / 注释与代码规范

一、HTML 行内注释 HTML注释是在HTML代码中添加说明和解释的一种方法&#xff0c;这些注释不会被浏览器渲染或显示在页面上&#xff0c;而是被浏览器忽略。HTML注释对于代码的可读性、可维护性和团队协作非常重要。 1.1、HTML注释的语法 HTML注释的语法是以<!--开始&…

【算法与数据结构】【字符串篇】【String的常见函数】

系列文章 本人系列文章-CSDN博客https://blog.csdn.net/handsomethefirst/article/details/138226266?spm1001.2014.3001.5502 1.string基本概念 string是C风格的字符串&#xff0c;而string本质上是一个类。 string和char * 区别&#xff1a; char * 是一个指针 string是一…

OpenAI 收购桌面实时协作公司 Multi;iOS 18 开放 iPhone 镜像测试丨RTE 开发者日报 Vol.231

开发者朋友们大家好&#xff1a; 这里是 「RTE 开发者日报」 &#xff0c;每天和大家一起看新闻、聊八卦。我们的社区编辑团队会整理分享 RTE&#xff08;Real-Time Engagement&#xff09; 领域内「有话题的 新闻 」、「有态度的 观点 」、「有意思的 数据 」、「有思考的 文…

[深度学习] 卷积神经网络CNN

卷积神经网络&#xff08;Convolutional Neural Network, CNN&#xff09;是一种专门用于处理数据具有类似网格结构的神经网络&#xff0c;最常用于图像数据处理。 一、CNN的详细过程&#xff1a; 1. 输入层 输入层接收原始数据&#xff0c;例如一张图像&#xff0c;它可以被…

图片怎么加水印?快来试试这6个图片加水印方法(2024年新)

图片怎么加水印&#xff1f;作为打工人在日常的工作生活中总会遇到各种各样的工作难题&#xff0c;相信从事电商或者是设计等工作的小伙伴们&#xff0c;遇到最多的问题应该就是给图片添加水印了。为什么要给图片加水印&#xff1f;其实给图片加水印最主要的目的是保护我们的图…

Linux集群自动化维护-Ansible

1.1Ansible概述 自动化运维&#xff1a;批量管理&#xff0c;批量分发&#xff0c;批量执行&#xff0c;维护。。是python写的 批量管理工具&#xff1a; Ansible&#xff08;无客户端&#xff09;&#xff1a;无客户端&#xff0c;基于ssh进行管理与维护 Saltstack &#…

深度之眼(二十五)——研究生学习计划安排

文章目录 一、前言二、结构安排和规划2.1 夯实基础2.2 分方向训练&#xff08;待&#xff09;2.3 进阶训练 三、其他 一、前言 课题组这边是需要对机器视觉有所要求吧&#xff0c;也就是CV方向。这一届研三师兄也都是在大厂拿到30W的年薪了&#xff0c;也是需要拥抱深度学习这…

NineData和华为云在一起!提供一站式智能数据库DevOps平台

以GuassDB数据库为底座 NineData和华为云一起 为企业提供 一站式智能数据库DevOps平台 帮助开发者 高效、安全地完成 数据库SQL审核 访问控制、敏感数据保护等 日常数据库相关开发任务 NineData 智能数据管理平台 NineData 作为新一代的云原生智能数据管理平台&#xf…

SpringCloud:Gateway服务网关

程序员老茶 &#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;程序员老茶 &#x1f64a; P   S : 点赞是免费的&#xff0c;却可以让写博客的作者开心好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#…

聚星文社ai工具下载

您可以在聚星文社官方网站上下载他们的AI工具。请访问他们的官方网站&#xff0c; 然后找到下载页面&#xff0c;从中选择并下载所需的AI工具。下载 如果您对下载过程有任何问题&#xff0c;建议您直接联系聚星文社的客服人员寻求帮助。

统信UOS系统忘记登录密码怎么办

在使用统信操作系统UOS的时候有可能会出现忘记密码的情况&#xff0c;当遇到了用户登录密码忘记时如何修改&#xff1f;今天分享一下忘记超级系统管理员Root以及普通密码时的解决方法。 因为UOS系统版本的原因&#xff0c;UOS 1031操作系统取消了单用户更改密码的方法&#xff…

Sulfo Cy3-NHS Ester生物标记与成像

【星戈瑞stargraydye】以下数据均来自文献资料,星戈瑞暂未进行独立验证, 仅供参考&#xff01; 在生物医学研究的前沿领域&#xff0c;荧光标记技术扮演着科研角色。其中&#xff0c;Sulfo Cy3 NHS Ester作为一种性能的荧光染料&#xff0c;以其高灵敏度、高特异性以及良好的生…

绿色共享购:共创绿色消费新纪元

在当今快节奏的社会中&#xff0c;人们对绿色消费和共享经济的追求愈发凸显其重要性。为了满足这一需求&#xff0c;我们创新推出了“绿色共享购”这一前沿的消费增值模式。该模式不仅有效整合了商家资源&#xff0c;更通过其独特的机制&#xff0c;实现了商家与消费者的双重增…

Unity关于Addressables.Release释放资源内存问题

前言 最近在编写基于Addressables的资源管理器&#xff0c;对于资源释放模块配合MemoryProfiler进行了测试&#xff0c;下面总结下测试Addressables.Release的结论。 总结 使用Addressables.Release释放资源时&#xff0c;通过MemoryProfiler检查内存信息发现加载的内容还在…