【数据结构】04.单链表

news2024/11/24 10:26:46

一、链表的概念及结构

概念:链表是⼀种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
在这里插入图片描述
节点的组成主要有两个部分:当前节点要保存的数据和保存下⼀个节点的地址(指针变量)。

补充说明:
1.链式机构在逻辑上是连续的,在物理结构上不⼀定连续
2、节点⼀般是从堆上申请的
3、从堆上申请来的空间,是按照⼀定策略分配出来的,每次申请的空间可能连续,可能不连续

二、单链表的实现

2.1节点的定义

typedef int SLDataType;
//定义链表结构体
typedef struct SList
{
	SLDataType data;//数据域
	struct SList* next;//指针域
}SL;

2.2单链表的打印

void SLPrint(SL** pphead)
{
	SL* cur = *pphead;
	while (cur)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

2.3单链表的增删查改

这里由于申请结点使用较多,我们将其封装为一个函数。

//获得新节点
SL* SListBuynode(SLDataType x)
{
	SL* newnode = (SL*)malloc(sizeof(SL));
	if (newnode == NULL)
	{
		perror("SListBuyNode is failed");
		return 1;
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
//尾插
void  SLPushBack(SL** pphead, SLDataType x)
{
	assert(pphead);
 
	SL* newnode = SListBuynode(x);
	//链表没有元素时
	if (*pphead == NULL)
	{
		*pphead = newnode;
		return;
	}
 	//链表有元素时
	SL* tail = *pphead;
	while (tail->next)
	{
		tail = tail->next;
	}
	tail->next = newnode;
}
 
//尾删
void SLPopBack(SL** pphead)
{
	assert(*pphead);
	assert(pphead);
 	
 	//删除的时头结点
	if ((*pphead)->next==NULL)
	{
		free(*pphead);
		*pphead = NULL;
		return;
	}
 	//删除的不是头结点
	SL* cur_tail = *pphead;
	SL* cur = NULL;
	while (cur_tail->next)
	{
		cur = cur_tail;
		cur_tail = cur_tail->next;
	}
	cur->next = NULL;
 
	free(cur_tail);
	cur_tail = NULL;
}
 
//头插
void SLPushFront(SL** pphead, SLDataType x)
{
	assert(pphead);
	
	SL* newnode = SListBuynode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}
 
//头删
void SLPopFront(SL** pphead)
{
	assert(pphead);
	assert(*pphead);
 
	SL* cur_head = (*pphead)->next;
	free(*pphead);
	*pphead = cur_head;
}
 
//查找
SL* SLFind(SL** pphead, SLDataType x)
{
	assert(pphead);
 
	SL* cur = *pphead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
 
//任意位置之前插入
void SLInsert(SL** pphead, SL* pos, SLDataType x)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
 
	SL* newnode = SListBuynode(x);
	//pos是头结点
	if (*pphead == pos)
	{
		newnode->next = *pphead;
		*pphead = newnode;
		return;
	}
	//pos不是头结点 
	SL* cur = *pphead;
	while (cur->next != pos)
	{
		cur = cur->next;
	}
	newnode->next =pos;
	cur->next = newnode;
}
 
//指定位置之后插入
void SLInsertAfter(SL* pos, SLDataType x)
{
	assert(pos);
 
	SL* newnode = SListBuynode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}
 
//任意位置删除
void SLErase(SL** pphead, SL* pos)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	//pos是头结点
	if (*pphead == pos)
	{
		SL* newhead = (*pphead)->next;
		free(*pphead);
		*pphead = NULL;
		*pphead = newhead;
 
		return;
	}
	//pos不是头结点
	SL* cur = *pphead;
	while (cur->next != pos)
	{
		cur = cur->next;
	}
	cur->next = pos->next;
	free(pos);
	pos = NULL;
}
 
//删除指定位置之后的元素
void SLEraseAfter(SL* pos)
{
	assert(pos);
	assert(pos->next);
 
	SL* cur = pos->next;
	pos->next = cur->next;
	free(cur);
	cur = NULL;
 
}

2.4单链表的销毁

//销毁链表
void SLDestroy(SL** pphead)
{
	SL* cur = *pphead;
	while (cur)
	{
		SL* next = cur->next;
		free(cur);
		cur = next;
	}
	*pphead = NULL;
}

2.5 单链表的源代码

//SingleList.h
#pragma once
 
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
 
 
typedef int SLDataType;
 
typedef struct SList
{
	SLDataType data;
	struct SList* next;
}SL;
 
 
void SLPrint(SL** pphead);//打印
 
 
void  SLPushBack(SL** pphead, SLDataType x);//尾插
void SLPopBack(SL** pphead);//尾删
 
void SLPushFront(SL**  pphead, SLDataType x);//头插
void SLPopFront(SL** pphead);//头删
 
void SLInsert(SL** pphead, SL* pos, SLDataType x);//指定位置之前插入
void SLInsertAfter( SL* pos, SLDataType x);//指定位置之后插入
 
SL* SLFind(SL** pphead, SLDataType x);//查找
 
void SLErase(SL** pphead, SL* pos);//指定位置元素删除
void SLEraseAfter(SL* pos);//删除指定位置之后的元素 
 
void SLDestroy(SL** pphead);//销毁链表
//SingleList.c
 
#define _CRT_SECURE_NO_WARNINGS 
 
#include"SL.h"
 
 
void SLPrint(SL** pphead)
{
	SL* cur = *pphead;
	while (cur)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}
 
 
SL* SListBuynode(SLDataType x)//获得新节点
{
	SL* newnode = (SL*)malloc(sizeof(SL));
	if (newnode == NULL)
	{
		perror("SListBuyNode is failed");
		return 1;
	}
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
 
 
void  SLPushBack(SL** pphead, SLDataType x)//尾插
{
	assert(pphead);
 
	SL* newnode = SListBuynode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
		return;
	}
 
	SL* tail = *pphead;
	while (tail->next)
	{
		tail = tail->next;
	}
	tail->next = newnode;
}
 
void SLPopBack(SL** pphead)//尾删
{
	assert(*pphead);
	assert(pphead);
 
	if ((*pphead)->next==NULL)
	{
		free(*pphead);
		*pphead = NULL;
		return;
	}
 
	SL* cur_tail = *pphead;
	SL* cur = NULL;
	while (cur_tail->next)
	{
		cur = cur_tail;
		cur_tail = cur_tail->next;
	}
	cur->next = NULL;
 
	free(cur_tail);
	cur_tail = NULL;
}
 
 
void SLPushFront(SL** pphead, SLDataType x)//头插
{
	assert(pphead);
	SL* newnode = SListBuynode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}
 
void SLPopFront(SL** pphead)//头删
{
	assert(pphead);
	assert(*pphead);
 
	SL* cur_head = (*pphead)->next;
	free(*pphead);
	*pphead = cur_head;
}
 
SL* SLFind(SL** pphead, SLDataType x)//查找
{
	assert(pphead);
 
	SL* cur = *pphead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;
}
 
void SLInsert(SL** pphead, SL* pos, SLDataType x)//任意位置插入
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
 
	SL* newnode = SListBuynode(x);
	if (*pphead == pos)//pos是头结点
	{
		newnode->next = *pphead;
		*pphead = newnode;
		return;
	}
	//pos不是头结点 
	SL* cur = *pphead;
	while (cur->next != pos)
	{
		cur = cur->next;
	}
	newnode->next =pos;
	cur->next = newnode;
}
 
 
void SLInsertAfter(SL* pos, SLDataType x)//指定位置之后插入
{
	assert(pos);
 
	SL* newnode = SListBuynode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}
 
void SLErase(SL** pphead, SL* pos)//任意位置删除
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	//pos是头结点
	if (*pphead == pos)
	{
		SL* newhead = (*pphead)->next;
		free(*pphead);
		*pphead = NULL;
		*pphead = newhead;
 
		return;
	}
	//pos不是头结点
	SL* cur = *pphead;
	while (cur->next != pos)
	{
		cur = cur->next;
	}
	cur->next = pos->next;
	free(pos);
	pos = NULL;
}
 
void SLEraseAfter(SL* pos)//删除指定位置之后的元素
{
	assert(pos);
	assert(pos->next);
 
	SL* cur = pos->next;
	pos->next = cur->next;
	free(cur);
	cur = NULL;
 
}
 
 
void SLDestroy(SL** pphead)//销毁链表
{
	SL* cur = *pphead;
	while (cur)
	{
		SL* next = cur->next;
		free(cur);
		cur = NULL;
		cur = next;
	}
	*pphead = NULL;
}

三、链表的分类

链表的结构非常多样,以下情况组合起来就有8种(2x2x2)链表结构:
在这里插入图片描述
在这里插入图片描述

虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构:单链表和双向带头循环链表

  1. 无头单向非循环链表:结构简单,⼀般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。
  2. 带头双向循环链表:结构最复杂,⼀般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现了就知道了。

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

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

相关文章

Postman使用教程

传统接口风格 RESTful风格 使用Postman完成测试用例目标&#xff1a; Postman教程 &#xff08;1&#xff09;准备工作&#xff0c;下载Postman新建 &#xff08;2&#xff09;登录接口调试-获取验证码 &#xff08;3&#xff09;登录接口调试-登录 &#xff08;4&#xff09;…

Android - Json/Gson

Json数据解析 json对象&#xff1a;花括号开头和结尾&#xff0c;中间是键值对形式————”属性”:属性值”” json数组&#xff1a;中括号里放置 json 数组&#xff0c;里面是多个json对象或者数字等 JSONObject 利用 JSONObject 解析 1.创建 JSONObject 对象&#xff0c;传…

工厂方法模式:概念与应用

目录 工厂方法模式工厂方法模式结构工厂方法适合的应用场景工厂方法模式的优缺点练手题目题目描述输入描述输出描述**提示信息**解题&#xff1a; 工厂方法模式 工厂方法模式是一种创建型设计模式&#xff0c; 其在父类中提供一个创建对象的方法&#xff0c; 允许子类决定实例…

无法启动此程序,因为计算机中丢失 api-ms-win-crt-string-11-1-0.dl。尝试重新安装该程序以解决此问题。

在windows server2012系统中利用WinSW部署jar包时&#xff0c;报错&#xff1a;无法启动此程序&#xff0c;因为计算机中丢失 api-ms-win-crt-string-11-1-0.dl。尝试重新安装该程序以解决此问题。 原因&#xff1a; 缺少Microsoft Visual C 2015运行库或者已安装低版本运行库…

提升TK直播体验:使用美国直播网络的六大优势

国内有许多公司想在TikTok上进行美国直播&#xff0c;但由于TikTok的政策限制&#xff0c;在国内直接访问存在困难。然而&#xff0c;通过使用Ogcloud的美国直播网络&#xff0c;这一问题得以解决。那么&#xff0c;TikTok海外直播使用美国直播网络具体有哪些优势呢&#xff1f…

【Koa】KOA 基础-掌握基于koa2搭建web应用的基础

目录 KOA 基础框架介绍与环境搭建koa2 基本介绍Node.JS 环境安装创建 Hello World 程序 Web 应用开发基础处理get请求参数处理post请求参数响应一个页面处理静态资源 中间件基本概念和执行过程中间件概念理解Koa 中间件执行模型-洋葱圈模型Koa洋葱圈设计理解 用 koa-body 处理 …

【掌握C++ string 类】——【高效字符串操作】的【现代编程艺术】

专栏&#xff1a;C学习笔记 上一篇&#xff1a;【C】——【 STL简介】——【详细讲解】 1. 为什么要学习 string 类&#xff1f; 1.1 C 语言中的字符串 在 C 语言中&#xff0c;字符串是以 \0 结尾的字符集合。如下所示&#xff1a; #include <stdio.h>int main() {c…

【第五节】C/C++数据结构之图

目录 一、图的基本概念 1.1 图的定义 1.2 图的其他术语概念 二、图的存储结构 2.1 邻接矩阵 2.2 邻接表 三、图的遍历 3.1 广度优先遍历 3.2 深度优先遍历 四、最小生成树 4.1 最小生成树获取策略 4.2 Kruskal算法 4.3 Prim算法 五、最短路径问题 5.1 Dijkstra算…

springboot+vue人事管理系统 +LW +PPT+源码+讲解

3系统分析 3.1可行性分析 在开发系统之前要进行系统可行性分析&#xff0c;目的是在用最简单的方法去解决最大的问题&#xff0c;程序一旦开发出来满足了员工的需要&#xff0c;所带来的利益也很多。下面我们将从技术、操作、经济等方面来选择这个系统最终是否开发。 3.1.1技…

米国政府呼吁抛弃 C 和 C++

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「C的资料从专业入门到高级教程」&#xff0c; 点个关注在评论区回复“888”之后私信回复“888”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; 很多观点认为C 或 C永远不可被…

C++那些事之小项目实战-进程间通信

小项目实战之进程间通信 进程间通信是一个非常重要的话题&#xff0c;特别是像一些大型项目都有它的影子&#xff0c;例如&#xff1a;PostgreSQL使用了管道完成copy的进程间通信&#xff0c;那么本节也将基于这个主题&#xff0c;使用C去搭建一个进程间通过管道通信的demo出来…

Angluar 实现pdf页面预览以及编辑

之前用过一个pdf预览的lib&#xff0c;并且还支持在线编辑&#xff0c;和直接下载编辑之后的pdf和直接打印&#xff0c;还不错&#xff0c;记录下 PdfShowcase 首先安装依赖 npm install ngx-extended-pdf-viewer 然后引入 import { NgxExtendedPdfViewerModule } from &q…

软件研发标准化流程文件

为了规范化系统开发流程&#xff0c;我们精心制定了一套详尽的规范文档。该文档旨在通过标准化、系统化的方法来显著提升开发效率与项目质量。流程始于明确需求阶段&#xff0c;通过深入细致的设计规划来确保解决方案既可行又具有前瞻性。随后&#xff0c;我们进入高效的编码实…

【懒删除堆 优先队列】1172. 餐盘栈

本文涉及知识点 懒删除堆 优先队列 LeetCode1172. 餐盘栈 我们把无限数量 ∞ 的栈排成一行&#xff0c;按从左到右的次序从 0 开始编号。每个栈的的最大容量 capacity 都相同。 实现一个叫「餐盘」的类 DinnerPlates&#xff1a; DinnerPlates(int capacity) - 给出栈的最大…

Linux开发讲课29---Linux USB 设备驱动模型

Linux 内核源码&#xff1a;include\linux\usb.h Linux 内核源码&#xff1a;drivers\hid\usbhid\usbmouse.c 1. BUS/DEV/DRV 模型 "USB 接口"是逻辑上的 USB 设备&#xff0c;编写的 usb_driver 驱动程序&#xff0c;支持的是"USB 接口"&#xff1a; US…

向量数据库、主键存储引擎、高速网络 RDMA 框架……DolphinDB 版本更新啦!

盛夏已至&#xff0c;炎热的七月伊始&#xff0c;DolphinDB 也迎来了版本的更新。此次更新的 3.00.1 与 2.00.13 版本从多个维度进行了优化扩展&#xff0c;进一步深化了 DolphinDB 在机器学习、数据分析等领域的尝试与探索。 为了响应用户日益增长的 AI 运算需求&#xff0c;…

XJTUSE-数据结构-homework2

当时写的还挺痛苦的 不过现在看&#xff0c;原老师布置的作业真的有水平 现在来看大二数据结构的作业&#xff0c;真的很锻炼代码能力。有些题目&#xff0c;我现在写也不一定能很快写出来hhhh 当时写的作业感觉还是存在问题的&#xff01; 任务概述 任务 1 &#xff1a;指定的…

JSON字符串中获取一个指定字段的值

一、方式一&#xff0c;引用gson工具 测试报文&#xff1a; {"account":"yanxiaosheng","password":"123456" } 引入pom <!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> <dependency><gr…

无人机测绘需要注意什么?

无人机测绘是一项高精度的测量工作&#xff0c;需要注意以下四点&#xff1a; 一、作业前准备&#xff1a;沟通相关事宜&#xff0c;现场勘查&#xff0c;飞行环境检查等&#xff1b; 二、航线规划与像控点布设&#xff1a;航线规划是任务规划的核心内容&#xff0c;需要综合…

【web APIs】快速上手Day05(Bom操作)

目录 Web APIs - 第5天笔记js组成window对象BOM定时器-延迟函数案例-5秒钟之后消失的广告 JS执行机制location对象案例-5秒钟之后跳转的页面 navigator对象histroy对象 本地存储&#xff08;今日重点&#xff09;localStorage&#xff08;重点&#xff09;sessionStorage&#…