手撕【双向链表】带头双向循环(2)

目录

Test.c

DList.h

DList.c

SLInsert

 SLErase

DList.c总代码

顺序表和链表的对比


今天继续再双向循环链表的基础上做修改。

❓提问:请你在10分钟内写一个带头双向循环链表。

其实我们只要把SLInsert 和 SLErase 写好就大功告成了!🆗

Test.c

#include"Dlist.h"
int main()
{
	SL* phead = SLInit();
	//头插
	SLPushFront(phead, 7);
	SLPushFront(phead, 77);
	SLPushFront(phead, 9);
	SLPushFront(phead, 99);
	SLPrint(phead);
	//头删
	SLPopFront(phead);
	SLPopFront(phead);
	SLPrint(phead);
	//尾插
	SLPushBack(phead,8);
	SLPushBack(phead, 88);
	SLPrint(phead);
	//尾删
	SLPopBack(phead);
	SLPopBack(phead);
	SLPrint(phead);
	//
	SLDestory(phead);
	phead = NULL;
	return 0;
}

DList.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLDataType;
typedef struct SListNode
{
	SLDataType val;
	struct SListNode* prev;
	struct SListNode* next;
}SL;
//初始化
SL* SLInit();
//打印数据
SL* SLPrint(SL* phead);
//查询
SL* SLFind(SL* phead, SLDataType x);
//头插
void SLPushFront(SL* phead, SLDataType x);
//头删
void SLPopFront(SL* phead);
//尾插
void SLPushBack(SL* phead, SLDataType x);
//尾删
void SLPopBack(SL* phead);
//在pos的前面插入
void SLInsert(SL* pos, SLDataType x);
//删除pos位置
void SLErase(SL* pos);
//销毁
void SLDestory(SL* phead);

DList.c

SLInsert

//在pos的前面插入
void SLInsert(SL* pos, SLDataType x)
{
	assert(pos);
	SL* cur = pos->prev;
	SL* newnode = Createnewnode(x);
	newnode->next = pos;
	pos->prev = newnode;
	cur->next = newnode;
	newnode->prev = cur;
}

 SLErase

//删除pos位置
void SLErase(SL* pos)
{
	assert(pos);
	SL* cur = pos->prev;
	SL* tail = pos->next;
	cur->next = tail;
	tail->prev = cur;
	free(pos);
	pos = NULL;
}

DList.c总代码

#include"Dlist.h"
//创建新的节点
SL* Createnewnode(SLDataType x)
{
	SL* newnode = (SL*)malloc(sizeof(SL));
	newnode->val = x;
	newnode->prev = NULL;
	newnode->next = NULL;
	return newnode;
}
//初始化
SL* SLInit()
{
	SL* phead = Createnewnode(-1);
	phead->prev = phead;
	phead->next = phead;
	return phead;
}
//打印
SL* SLPrint(SL* phead)
{
	assert(phead);
	assert(phead->next != phead);//不打印头节点
	SL* cur = phead->next;
	while (cur != phead)
	{
		printf("<=%d=>", cur->val);
		cur = cur->next;
	}
	printf("\n");
}
//查询
SL* SLFind(SL* phead, SLDataType x)
{
	assert(phead);
	SL* cur = phead->next;
	while (cur != phead)
	{
		if (cur->val == x)
		{
			return cur;
		}
	}
	return NULL;
}
//在pos的前面插入
void SLInsert(SL* pos, SLDataType x)
{
	assert(pos);
	SL* cur = pos->prev;
	SL* newnode = Createnewnode(x);
	newnode->next = pos;
	pos->prev = newnode;
	cur->next = newnode;
	newnode->prev = cur;
}
//删除pos位置
void SLErase(SL* pos)
{
	assert(pos);
	SL* cur = pos->prev;
	SL* tail = pos->next;
	cur->next = tail;
	tail->prev = cur;
	free(pos);
	pos = NULL;
}
//头插
void SLPushFront(SL* phead, SLDataType x)
{
	SLInsert(phead->next, x);
}
//头删
void SLPopFront(SL* phead)
{
	assert(phead->next != phead);//不删除头节点
	SLErase(phead->next);
}
//尾插
void SLPushBack(SL* phead, SLDataType x)
{
	SLInsert(phead, x);
}
//尾删
void SLPopBack(SL* phead)
{
	assert(phead->next != phead);//不删除头节点
	SLErase(phead->prev);
}
//销毁
void SLDestory(SL* phead)
{
	assert(phead);
	SL* cur = phead->next;
	while (cur != phead)
	{
		SL* tmp = cur->next;
		free(cur);
		cur = tmp;
	}
	free(phead);
	cur = NULL;
}

 

 🙂🙂是不是很简单,动手快速写一写吧!!

顺序表和链表的对比

链表(双向)的优势:

  • 任意位置插入删除都是O(1)
  • 知道pos位置并且插入和删除,都是O(N)  //后期学习哈希可以达到O(1)
  • 按需求申请释放,合理利用空间,不存在浪费

链表(双向)劣势:

  • 下标随机访问不方便O(N) //不支持高效排序

顺序表优势:

  • 支持下标随机访问O(1)
  • CPU高速缓存命中率比较高 

 顺序表劣势:

  • 头部或者中间插入删除效率低,要挪动数据。O(N)
  • 空间不够需要扩容,扩容有一定的消耗,且可能存在一定的空间浪费
  • 只适合尾插尾删

有人可能问CPU高速缓存命中率比较高是什么?

 电脑中负责运算就是 CPUGPU(显卡等)。负责存储就是内存硬盘(磁盘/固态)。内存是带电暂时存储,速度相对较快硬盘是不带电,永久存储,读写速度相对慢。

当然除了内存和硬盘这两个存储介质,还有其他的存储介质。就是缓存  虽然内存速度相较于硬盘快,但是对于CPU来说还是慢了,于是就有围绕在CPU附近的缓存。

缓存中,缓存的存储数据越少,速度越快。所以,小的数据会放到寄存器大的数据会放到高速缓存中去。像顺序表/链表/数组这样的数据存储,当然是放到高速缓存中。

那么数据是怎样放入缓存,CPU怎样去访问高速缓存中的数据呢?

  • 首先CPU会到高速缓存中去查看需要访问的数据是否在缓存中
  • 如果在就访问成功(命中)
  • 如果不在(没命中)就把数据 加载 高速缓存中(不是一个一个加载,而是一段一段的加载)
  • 加载之后再去访问

对于顺序表来说,物理结构上的连续,加载和访问时的命中率更高

对于链表来说,只是逻辑上的连续,物理空间可能相隔很远,所以命中率相对没有那么高,而且很容易造成缓存污染(空间存储都是一些无用的数据)

这个也叫:局部性原理

 想要更加深入的了解【戳一戳】:与程序员相关的CPU缓存知识 | 酷 壳 - CoolShell

✔✔✔✔✔最后感谢大家的阅读,若有错误和不足,欢迎指正!乖乖敲代码哦! 

代码---------→【唐棣棣 (TSQXG) - Gitee.com】

联系---------→【邮箱:2784139418@qq.com】

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Salmon-超快速、准确的基因丰度计算

文章目录 Salmon简介文章引用及适用物种获取转录组并建立索引比较salmon和coverm定量差异 Salmon简介 Salmon 是一款速度极快的程序&#xff0c;能从 RNA-seq 数据中生成高精度的转录本水平的量化估计值。Salmon 通过一系列不同的创新实现了其准确性和速度&#xff0c;包括使用…

预发部署时机器总是重启两次的“简单”排查

作者&#xff1a;曲池 一、问题 前天同学反馈&#xff0c; 搜索业务的核心应用 magellan 在预发环境部署时总是重启两次&#xff0c;刚部署好&#xff0c;开始联调&#xff0c;突然又重启了&#xff0c;也导致老是被人抱怨搜索环境不稳定。 第一反应是&#xff0c;大概率是应用…

下载huggingface预训练模型到本地并调用

写在前面 在大模型横行的时代&#xff0c;无法在服务器上连接外网的研究僧真的是太苦逼了&#xff0c;每次想尝试类似于CLIP&#xff0c;BLIP之类的大模型都会得到“requests.exceptions.ConnectionError: (MaxRetryError("HTTPSConnectionPool(host‘huggingface.co’, …

【Spring】加载properties文件

文章目录 在Spring Context中加载properties文件测试总结 在Spring Context中加载properties文件 分为三步&#xff0c;如下图所示&#xff1a; 完整代码&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.…

2019年12月 Scratch(二级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 以下程序执行后,角色面向的方向是? A:右上 B:右下 C:左上 D:左下 答案:B 面向-135度,是面向左下角,向右旋转-90度等于向左旋转90度。所以会旋转到右下角。 第2题 以下程…

opencv dnn模块 示例(23) 目标检测 object_detection 之 yolov8

文章目录 1、YOLOv8介绍1.1、概述1.2、骨干网络和 Neck1.3、Loss 计算1.4、数据增强1.5、训练策略1.6、推理过程 2、测试2.1、官方Python测试2.2、Opencv dnn测试2.3、测试统计 3、训练4、Yolov8-pose 简单使用 1、YOLOv8介绍 YOLOv3之前的所有YOLO对象检测模型都是用C语言编写…

从算法到应用:直播美颜滤镜SDK的全面解读与评测

直播美颜滤镜SDK技术逐渐成为直播平台不可或缺的一环。本文将对直播美颜滤镜SDK进行全面解读&#xff0c;深入探讨其算法原理和应用效果&#xff0c;并通过评测分析展现其在直播领域的实际价值。 一、算法原理解读 直播美颜滤镜的背后是复杂而精密的算法&#xff0c;旨在提升…

OpenCV快速入门:绘制图形、图像金字塔和感兴趣区域

文章目录 前言一、绘制图形1. 绘制直线2. 绘制圆3. 绘制矩形4. 绘制椭圆5. 绘制多边形6. 绘制文字7. 可选参数8. 手工绘制OpenCV的logo 二、图像金字塔1. 高斯金字塔2. 拉普拉斯金字塔 三、感兴趣区域&#xff08;ROI&#xff09;数组切片方式OpenCV截取方式 总结 前言 OpenCV…

修改服务器端Apache默认根目录

目标&#xff1a;修改默认Apache网站根目录 /var/www/html 一、找到 DocumentRoot “/var/www/html” 这一段 apache的根目录&#xff0c;把/var/www/html 这个目录改 #DocumentRoot "/var/www/html" DocumentRoot "/home/cloud/tuya_mini_h5/build" 二、…

echarts 横向柱状图示例

该示例有如下几个特点&#xff1a; ①实现tooltip自定义样式&#xff08;echarts 实现tooltip提示框样式自定义-CSDN博客&#xff09; ②实现数据过多时滚动展示&#xff08;echarts 数据过多时展示滚动条-CSDN博客&#xff09; ③柱状图首尾展示文字&#xff0c;文字内容嵌入图…

【C++】内存管理

目录 C/C内存分布 C语言中动态内存管理方式 C内存管理方式 operator new与 operator delete函数 匹配使用的相关问题-内存泄漏: delete与delete [ ] malloc/free和 new/delete的区别 内存泄漏 C/C内存分布 栈又叫堆栈--非静态局部变量/函数参数/返回值等等&#xff0c;栈…

人工智能引领环境保护的新浪潮:技术应用及其影响

在全球范围内&#xff0c;环境保护已经成为一个迫切的话题。随着人工智能技术的发展&#xff0c;它开始在环境保护领域扮演越来越重要的角色。AI不仅能够帮助更有效地监测环境变化&#xff0c;还能提出解决方案来应对环境问题。 污染监测与控制&#xff1a; AI系统可以分析来自…

redis运维(十)列表

一 列表 强调&#xff1a; 知道原生redis具备的能力,以便后续API调用 ① 基础概念 备注&#xff1a; 单个list最多2^32-1个元素 列表操作常用命令,涉及&#xff1a;CURD ② lpush 左插入 说明&#xff1a; 如果key不存在就会初始化,否则就是插入元素备注&#xff1a; l…

指针——C语言初阶

一.指针基本概念&#xff1a; 指针是内存中一个最小单元的编号&#xff0c;也就是地址平时口语中说的指针&#xff0c;通常指的是指针变量&#xff0c;是用来存放地址的变量 #include<stdio.h> int main() {int a 0;//a是整型变量&#xff0c;占用四个字节的内存空间&a…

Linux系统(CentOS7)上安装MYSQL8.x

Linux系统是CentOS7版本&#xff0c;今天在新电脑上安装MYSQL&#xff0c;跟着网上的文章&#xff0c;尝试了好几次&#xff0c;都是启动失败&#xff0c;删了安&#xff0c;安了删&#xff0c;搞了一下午&#xff0c;头昏脑胀&#xff0c;网上的一些文章太乱了&#xff0c;每种…

SSM框架

SSM SSM框架说明SpringBootMyBatis整合MyBatis数据库中表的设计Pojo对象设计Dao接口设计Dao单元方法进行测试 XML管理整合MyBatis框架映射配置文件的位置XML配置SQL标签常用的SQL标签 动态SQL语句动态删除数据动态修改数据 SSM框架说明 Spring 指 Spring Framework&#xff0c…

前段-用面向对象的方式开发一个水管小鸟的游戏

首先准备好各类空文件 index.js css html 和图片 图片是下面这些&#xff0c;如果没有的可在这里下载 2 开发开始 好了&#xff0c;基础准备工作完毕&#xff0c;开发开始&#xff0c; 首先&#xff0c;先把天空&#xff0c;大地&#xff0c;小鸟的盒子准备好&#xff0c;并…

Redis数据库双写一致性解决方案

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一份大厂面试资料《史上最全大厂面试题》&#xff0c;Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等 …

好用的企业防泄密软件盘点

企业防泄密软件是专门设计用于保护企业敏感信息不被泄露的软件产品。这类软件通常采用多种安全技术和策略&#xff0c;以增强企业数据的安全性和保密性&#xff0c;防止核心知识产权和商业机密的泄露。 企业防泄密软件的主要功能包括数据加密、访问控制、审计和监控、文件和数据…

CSS样式穿透

当我们在vue项目中使用第三方组件时&#xff0c;有时候需要去修改某些元素的样式&#xff0c;但有时写的css样式不会覆盖组件的样式&#xff0c;所以要用到样式穿透。 常用的方法有这几种&#xff1a;&#xff08;1&#xff09;>>> &#xff08;2&#xff09;/deep/ …