当前位置: 首页 > news >正文

双链表详解

一、双向链表介绍

二、实现双向链表

1.定义双向链表的结构

2.双向链表的初始化

3.双向链表的尾插

4.双向链表的头插

5.双向链表的打印

6.双向链表的尾删

7.双向链表的头删

8.查找指定位置的数据

9.在指定位置之后插入数据

10.删除指定位置的数据

11.链表的销毁

三、代码展示

一、双向链表介绍

双向链表就是带头双向循环链表,带头链表里的头结点,实际为"哨兵位",哨兵位节点不存储任何有效元素,它存在的意义是遍历循环链表避免死循环。哨兵位节点不能被删除,节点的地址也不能发生改变。

二、实现双向链表

1.定义双向链表的结构

我们看一张图,会发现,每个节点由三个部分组成:1.节点的数据 2.节点存放着指向下一个节点的指针next  3.节点存放着指向上一个节点的指针prev,所以我们定义如下:

typedef int LTData;//便于应用各种数据
typedef struct ListNode
{LTData data;//数据struct ListNode* next;//指向下一个节点的指针struct ListNode* prev;//指向上一个节点的指针
}LTNode;//重命名为LTNode方便表达

这个放在list.h里面,我们一共有三个文件,list.h list.c和test.c

2.双向链表的初始化

双向链表初始化,我们要初始化哨兵位,哨兵位没有值,所以节点里面没有有效的数据,那我们先完成一个前置函数LTBuyNode,用它来创建节点,步骤很简单:malloc开辟,然后检查是否开辟成功,成功就传数据。

注意:链表循环的条件是尾结点的next指针不为空,所以这里初始化的prev和next都指向节点本身,代码如下:

接着调用一下这个前置函数就可以了:

LTNode* LTBuyNode(LTData x)//创建节点
{LTNode* node = (LTNode*)malloc(sizeof(LTNode));//malloc开辟一块空间if (node == NULL)//判断空间是否为空{perror("malloc fail!");exit(1);}node->data = x;//将数据给data//这里prev和next不能指向NULL,不然就是不循环了,所以让他们指向本身node->next = node->prev = node;return node;//返回节点
}
void LTInit(LTNode** pphead)
{*pphead = LTBuyNode(-1);//给双向链表创建一个哨兵位//哨兵位没有值,所以传一个-1
}

3.双向链表的尾插

双向链表的尾插有些复杂

1.双向链表是带环链表,所以是头尾相连的,如果设指向头结点的指针是phead,那么phead的prev指针指向的也就是尾结点。

2.尾插一个新节点,叫做newnode,那需要建立一个新节点,调用函数LTBuyNode();

3.现在有三个节点,分别是phead指向的头结点,phead->prev指向的尾结点以及要插入的节点newnode

4.newnode有两个指针,它现在是新的尾结点,所以她的next指针指向头结点phead,它的prev指针指向前一个节点也是就phead->prev指向的节点,那原来的尾结点的next指针也要改变,改完指向下一个节点也就是newnode,头结点的prev指针也要改变,现在它指向新的尾结点也就是newnode。

代码如下:     

void LTPushBack(LTNode* phead, LTData x)//传一级就够了,因为不用改变哨兵位的地址
{assert(phead);//断言确定不为空LTNode* newnode = LTBuyNode(x);//创建新节点//phead phead->prev newnodenewnode->prev = phead->prev;newnode->next = phead;phead->prev->next = newnode;phead->prev = newnode;
}

4.双向链表的头插

头插基本思路和尾插一样,需要注意的是头插是插在第一个有效节点之前,也就是哨兵位之后

1.先调用LTBuyNode()函数创建一个新节点newnode

2.要将newnode插在phead和phead->next之间

3.newnode的next指针指向phead->next;newnode的prev指针指向phead

4.phead->next指针指向的节点的prev指针改变指向,现在指向newnode,phead指向节点的next指针改变指向,现在指向newnode。

代码如下:

void LTPushFront(LTNode* phead, LTData x)
{assert(phead);LTNode* newnode = LTBuyNode(x);//创建新节点//phead newnode phead->nextnewnode->next = phead->next;newnode->prev = phead;phead->next->prev = newnode;phead->next = newnode;
}

5.双向链表的打印

双向链表的打印很简单,只需要遍历链表就可以,因为双向链表的第一个节点是哨兵位,不存储数据,所以我们只需要定义一个指针pcur指向头结点的下一个节点,然后循环就可以了,但是我们要知道循环的条件是什么,由于双向链表是带环链表,所以只需要让pcur不重新指回头结点即可。

代码如下:

        

void LTPrint(LTNode* phead)
{LTNode* pcur = phead->next;//第一个节点是哨兵位,不需要打印while (pcur != phead)//如果没有遍历回头结点,就不用停{printf("%d->", pcur->data);//打印每个节点的数据pcur = pcur->next;//节点往后遍历}printf("\n");
}

6.双向链表的尾删

1.明确要删的节点,头结点是phead,那phead->prev就是尾结点,也就是要删除的节点

2.定义一个新的指针del来接受phead->prev,那删除后,del->prev就是新节点

3.现在尾结点是del->prev,那它的next指针就是头结点,那头结点的prev指针也就是新的尾结点

4.记得释放掉del,并且将他置为空

代码如下:

void LTPopBack(LTNode* phead)
{//链表必须有效且链表不能为空assert(phead && phead->next != phead);LTNode* del = phead->prev;//phead del->prev deldel->prev->next = phead;phead->prev = del->prev;free(del);del = NULL;
}

7.双向链表的头删

头删思路和尾删差不多

1.定义一个新指针del是phead->next,也就是del要被删除

2.现在处理三个节点,分别是phead,del,del->next;

3.phead的next指针指向改变,改为指向del->next

4.del->next的prev指针指向改变,改为指向phead

5.最后记得free掉del,并将他置为NULL

代码如下:

void LTPopFront(LTNode* phead)
{//链表必须有效且链表不能为空assert(phead && phead->next != phead);LTNode* del = phead->next;phead->next = del->next;del->next->prev = phead;//删除del节点free(del);del = NULL;
}

8.查找指定位置的数据

查找就是遍历链表,定义一个指针pcur,当他没有循环一圈等于头结点phead的时候,就一直遍历;如果pcur指向的节点的data是要查找的数据,就返回,如果遍历完还是找不到,就返回NULL。

代码如下:

LTNode* LTFind(LTNode* phead, LTData x)
{LTNode* pcur = phead->next;//定义一个新指针,指向第一个有效的节点while (pcur != phead)//遍历双向链表{if (pcur->data == x)//如果找到了就返回pcur{return pcur;}pcur = pcur->next;//pcur每次向后移动一格}//没有找到return NULL;
}

在test.c里面测试一下:

9.在指定位置之后插入数据

这里就是三个节点:pos newnode pos->next

1.先用LTBuyNode()函数创立一个新节点newnode;

2.newnode的next指针指向pos->next

3.newnode的prev指针指向pos

4.pos->next指针指向的节点的prev改为指向newnode

5.pos指针指向的节点的next改为指向newnode

代码如下:

void LTInsert(LTNode* pos, LTData x)
{assert(pos);//断言防止为空LTNode* newnode = LTBuyNode(x);//pos newnode pos->nextnewnode->next = pos->next;newnode->prev = pos;pos->next->prev = newnode;pos->next = newnode;
}

10.删除指定位置的数据

删除pos,就要关注三个节点,pos->prev、pos、pos->next

1.首先pos->next的这个节点的prev指向改变,改为指向pos->prev

2.pos->prev指向的节点的next改变,改为指向pos->next

3.记得销毁pos

代码如下:

void LTErase(LTNode* pos)
{assert(pos);//断言防止为空//pos->prev pos pos->nextpos->next->prev = pos->prev;pos->prev->next = pos->next;//销毁posfree(pos);pos = NULL;
}

11.链表的销毁

最后一步是链表销毁,那只需要遍历双向链表,然后一个一个free就可以了,注意哨兵位也是初始化时候创建的,也要销毁。

代码如下:

void LTDestroy(LTNode* phead)
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){LTNode* next = pcur->next;free(pcur);pcur = pcur->next;}free(phead);phead = NULL;
}

三、代码展示

list.h:

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int LTData;//便于应用各种数据
typedef struct ListNode
{LTData data;//数据struct ListNode* next;//指向下一个节点的指针struct ListNode* prev;//指向上一个节点的指针
}LTNode;//重命名为LTNode方便表达void LTInit(LTNode** pphead);
void LTPrint(LTNode* phead);
void LTPushBack(LTNode* phead, LTData x);//传一级就够了
void LTPushFront(LTNode* phead, LTData x);
void LTPopBack(LTNode* phead);
void LTPopFront(LTNode* phead);void LTInsert(LTNode* pos, LTData x);
void LTErase(LTNode* pos);
LTNode* LTFind(LTNode* phead, LTData x);
void LTDestroy(LTNode* phead);	 

list.c:

#include "list.h"void LTPrint(LTNode* phead)
{LTNode* pcur = phead->next;//第一个节点是哨兵位,不需要打印while (pcur != phead)//如果没有遍历回头结点,就不用停{printf("%d->", pcur->data);//打印每个节点的数据pcur = pcur->next;//节点往后遍历}printf("\n");
}LTNode* LTBuyNode(LTData x)//创建节点
{LTNode* node = (LTNode*)malloc(sizeof(LTNode));//malloc开辟一块空间if (node == NULL)//判断空间是否为空{perror("malloc fail!");exit(1);}node->data = x;//将数据给data//这里prev和next不能指向NULL,不然就是不循环了,所以让他们指向本身node->next = node->prev = node;return node;//返回节点
}
void LTInit(LTNode** pphead)
{*pphead = LTBuyNode(-1);//给双向链表创建一个哨兵位//哨兵位没有值,所以传一个-1
}void LTPushBack(LTNode* phead, LTData x)//传一级就够了,因为不用改变哨兵位的地址
{assert(phead);//断言确定不为空LTNode* newnode = LTBuyNode(x);//创建新节点//phead phead->prev newnodenewnode->prev = phead->prev;newnode->next = phead;phead->prev->next = newnode;phead->prev = newnode;
}
void LTPushFront(LTNode* phead, LTData x)
{assert(phead);LTNode* newnode = LTBuyNode(x);//创建新节点//phead newnode phead->nextnewnode->next = phead->next;newnode->prev = phead;phead->next->prev = newnode;phead->next = newnode;
}void LTPopBack(LTNode* phead)
{//链表必须有效且链表不能为空assert(phead && phead->next != phead);LTNode* del = phead->prev;//phead del->prev deldel->prev->next = phead;phead->prev = del->prev;free(del);del = NULL;
}void LTPopFront(LTNode* phead)
{//链表必须有效且链表不能为空assert(phead && phead->next != phead);LTNode* del = phead->next;phead->next = del->next;del->next->prev = phead;//删除del节点free(del);del = NULL;
}LTNode* LTFind(LTNode* phead, LTData x)
{LTNode* pcur = phead->next;//定义一个新指针,指向第一个有效的节点while (pcur != phead)//遍历双向链表{if (pcur->data == x)//如果找到了就返回pcur{return pcur;}pcur = pcur->next;//pcur每次向后移动一格}//没有找到return NULL;
}void LTInsert(LTNode* pos, LTData x)
{assert(pos);//断言防止为空LTNode* newnode = LTBuyNode(x);//pos newnode pos->nextnewnode->next = pos->next;newnode->prev = pos;pos->next->prev = newnode;pos->next = newnode;
}void LTErase(LTNode* pos)
{assert(pos);//断言防止为空//pos->prev pos pos->nextpos->next->prev = pos->prev;pos->prev->next = pos->next;//销毁posfree(pos);pos = NULL;
}void LTDestroy(LTNode* phead)
{assert(phead);LTNode* pcur = phead->next;while (pcur != phead){LTNode* next = pcur->next;free(pcur);pcur = pcur->next;}free(phead);phead = NULL;
}

test.c:

#include "list.h"void test01()
{LTNode* plist = NULL;LTInit(&plist);LTPushBack(plist, 1);LTPushBack(plist, 1);LTPushBack(plist, 1);LTPushFront(plist, 3);LTPrint(plist);LTPopFront(plist);LTPrint(plist);
}void test02()
{LTNode* plist = NULL;LTInit(&plist);LTPushBack(plist, 1);LTPushBack(plist, 2);LTPushBack(plist, 3);LTPrint(plist);LTNode* find = LTFind(plist, 1);if (find == NULL){printf("找不到!\n");}else{printf("找到了!\n");}}
int main()
{//test01();test02();return 0;
}

相关文章:

双链表详解

一、双向链表介绍 二、实现双向链表 1.定义双向链表的结构 2.双向链表的初始化 3.双向链表的尾插 4.双向链表的头插 5.双向链表的打印 6.双向链表的尾删 7.双向链表的头删 8.查找指定位置的数据 9.在指定位置之后插入数据 10.删除指定位置的数据 11.链表的销毁 三、…...

6.9.单源最短路径问题-BFS算法

一.前言&#xff1a; 问题1&#xff1a; 以上述图片为例&#xff0c;比如从G港到Y城&#xff0c;可以是G港->R城->Y城&#xff0c;也可以是G港->P城->Y城等&#xff0c;有很多条路径都可以实现从G港到Y城&#xff0c;但要从中找出G港到Y城距离最短的那一条路径&am…...

react js 查看字体效果

起因&#xff0c; 目的: 想查看某个字体&#xff0c;对中英文的支持情况。 效果图: 完整项目见这里&#xff0c; 需要积分下载&#xff0c;不然的话&#xff0c;显得太水了。 过程: AI 对话&#xff0c; 生成代码。我检查运行&#xff0c; 来回修改。写个博客&#xff0c;…...

GZIPInputStream 类详解

GZIPInputStream 类详解 GZIPInputStream 是 Java 中用于解压缩 GZIP 格式数据的流类,属于 java.util.zip 包。它是 InflaterInputStream 的子类,专门处理 GZIP 压缩格式(.gz 文件)。 1. 核心功能 解压 GZIP 格式数据(RFC 1952 标准)自动处理 GZIP 头尾信息(校验和、时…...

数字智慧方案6206丨智慧园区大数据整体解决方案(45页PPT)(文末有下载方式)

资料解读&#xff1a;智慧园区大数据整体解决方案 详细资料请看本解读文章的最后内容。 在数字化快速发展的当下&#xff0c;智慧园区成为推动产业升级和城市发展的关键力量。这份智慧园区大数据整体解决方案&#xff0c;融合前沿技术与创新理念&#xff0c;为园区的高效管理、…...

Linux系统常用命令、标准C库函数和系统调用

目录 一、常用命令 env echo $name 键值 export name unset name gcc -c xxx.c ar 命令 ar -r libxxx.a xxx1.o xxx2.o gcc -c -fpic xxx.c gcc -shared -fpic xxx1.c xxx2.c -o libxxx.so kill [-信号] PID kill -l 软链接&#xff1a;ln -s xxx yyy 硬链接&…...

【Linux】基础指令(2)

man linux中有很多指令&#xff0c;我们不可能全部记住&#xff0c;man是linux/unix系统中的手册页指令&#xff0c;当我们遇到不熟悉的命令可以用man来查看命令&#xff0c;函数&#xff0c;配置文件的详细使用说明。 man手册分为多个章节&#xff0c;详情如下&#xff1a; …...

“会话技术”——Cookie_(2/2)原理与使用细节

经过Cookie的快速入门与代码使用。如果想深入理解Cookie的技术实现&#xff0c;就得去理解它的原理。 且有些时候使用Cookie&#xff0c;还要根据需求设置存活期限以及确定Cookie获取范围等其他细节。最后&#xff0c;我们会总结Cookie这门客户端会话技术的作用。 一、原理 注…...

Linux操作系统--进程间通信(中)(命名管道)

目录 1.命名管道&#xff1a; 1.1创建一个命名管道 1.2匿名管道与命名管道的区别 1.3命名管道的打开规则 1.4例子1-用命名管道实现文件拷贝 1.5例子2-用命名管道实现server&client通信 1.命名管道&#xff1a; 毫不相关的进程进行进程间通信管道应用的一个限制就是只能…...

数据结构6 · BinaryTree二叉树模板

代码函数功能顺序如下&#xff1a; 1&#xff1a;destroy&#xff1a;递归删除树 2&#xff1a;copy&#xff1a;复制二叉树 3&#xff1a;preOrder&#xff1a;递归前序遍历 4&#xff1a;inOrder&#xff1a;递归中序遍历 5&#xff1a;postOrder&#xff1a;递归后续遍…...

ubuntu的libc 库被我 sudo apt-get --reinstall install libc6搞没了

我系统的libc 没了 今天为了运行一个开源的yuv 播放器&#xff0c;在运行的时候提醒 Inconsistency detected by ld.so: dl-call-libc-early-init.c: 37: _dl_call_libc_early_init: Assertion sym ! NULL failed!然后听从AI 的建议 当我去执行ls 时&#xff0c;系统提示 就这…...

cat file.tar.gz | tar -xzf - -C /target/dir两个减号之间为什么有个空格?是写错了吗?(管道命令后续)

在 tar 命令的参数 -xzf - -C 中&#xff0c;两个减号&#xff08;-&#xff09;之间的空格是故意保留的语法&#xff0c;没有写错。具体原因如下&#xff1a; 1. -xzf - 的语法解析 -xzf 是 tar 命令的组合参数&#xff1a; x&#xff1a;表示解压&#xff08;extract&#x…...

手机的数据楚门世界是如何推送的

手机推送&#xff0c;也叫茧影算法&#xff0c;手机的数据“楚门世界”&#xff1a;信息推送机制的深度剖析与社会影响 在数字化时代&#xff0c;手机已然成为人们生活中不可或缺的伴侣。当我们沉醉于手机带来的便捷与娱乐时&#xff0c;或许未曾察觉&#xff0c;自己正置身于…...

体系结构论文(八十二):A Comprehensive Analysis of Transient Errors on Systolic Arrays

研究背景与动机 TPU架构&#xff08;Tensor Processing Unit&#xff09;广泛应用于DNN推理&#xff0c;其核心是脉动阵列&#xff0c;由大量的乘加单元&#xff08;MAC&#xff09;组成。 由于使用了纳米级CMOS技术&#xff0c;TPU对辐射引发的瞬态错误&#xff08;SET&#…...

综合案例:使用vuex对购物车的商品数量和价格等公共数据进行状态管理

文章目录 0.实现需求1.新建购物车模块cart2.使用json-server模拟向后端请求数据3.在vuex请求获取并存入数据,并映射到组件中,在组件中渲染【重点】3.1.安装axios3.2.准备actions和mutations,获取和存入数据到vuex中3.3.动态渲染:用mapState映射 其他1.为什么在axios在项目中要局…...

二叉搜索树的判断(双指针解决)

98. 验证二叉搜索树 - 力扣&#xff08;LeetCode&#xff09; class Solution { public:TreeNode*preNULL;bool isValidBST(TreeNode* root) {if(rootNULL){return true;}bool leftisValidBST(root->left);if(pre!NULL&&pre->val>root->val){return fals…...

关于CSDN创作的常用模板内容

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 好文评论新文推送 &#x1f4c3;文章前言 &…...

不小心误删了文件,找Windows数据恢复工具来帮忙

相信很多人都遇到过这样的情况&#xff1a;不小心在电脑上删除了一些重要的文件&#xff0c;等到想要找回来时&#xff0c;却感觉特别棘手。 今天我要给大家推荐一款超棒的Windows数据恢复工具&#xff0c;它能轻松帮你找回那些被误删的文件。 &#xff08;文末附下载链接&…...

[Verilog]跨时钟域数据传输解决方案

跨时钟域数据传输解决方案 摘要:跨时钟域数据传输 (Clock Domain Crossing, CDC) 是 SoC 设计中常见且关键的问题,因为现代 SoC 通常包含多个时钟域,不同模块可能运行在不同频率或相位的时钟下。跨时钟域传输数据时,如果处理不当,可能会导致亚稳态 (Metastability)…...

Linux——进程终止/等待/替换

前言 本章主要对进程终止&#xff0c;进程等待&#xff0c;进程替换的详细认识&#xff0c;根据实验去理解其中的原理&#xff0c;干货满满&#xff01; 1.进程终止 概念&#xff1a;进程终止就是释放进程申请的内核数据结构和对应的代码和数据 进程退出的三种状态 代码运行…...

数据结构与算法:图论——最短路径

最短路径 先给出一些leetcode算法题&#xff0c;以后遇见了相关题目再往上增加 最短路径的4个常用算法是Floyd、Bellman-Ford、SPFA、Dijkstra。不同应用场景下&#xff0c;应有选择地使用它们&#xff1a; 图的规模小&#xff0c;用Floyd。若边的权值有负数&#xff0c;需要…...

双指针(5)——有效三角形个数

题目&#xff1a; 这道题我们首先可能会想到暴力解法&#xff0c;三个for循环然后进行check&#xff08;&#xff09;。时间复杂度肯定是不允许的。 同时&#xff0c;验证可以组成三角形的条件是任意两边之和大于第三边&#xff0c;这就意味着我们每组要进行三次比较。但也有捷…...

Qt QGraphicsScene 的用法

背景&#xff0c;为什么要写这篇博客 今天学习 model - view 模式的时候还看到有 scene - view 模式。不知道还有这个模式&#xff0c;所以学习了下。 学习后总体的感觉是&#xff1a;其实没有也是可以的&#xff0c;但有了方便许多。 从两种画图的方法开始说 以前有个项目也…...

使用 Tesseract 实现藏文OCR

要识别藏文&#xff0c;最常用且有效的方法是使用Tesseract OCR&#xff08;谷歌开源的OCR工具&#xff09;&#xff0c;因为它拥有针对藏文的预训练模型支持。 &#x1f680; 一、安装 Tesseract OCR 软件&#xff1a; 下载链接&#xff1a;Tesseract OCR 下载页面 Windows用…...

数字智慧方案5873丨智慧交通设计方案(57页PPT)(文末有下载方式)

资料解读&#xff1a;智慧交通设计方案 详细资料请看本解读文章的最后内容。 智慧交通设计方案是一份详尽的交通规划文件&#xff0c;旨在通过科学的交通设计方法&#xff0c;优化交通系统&#xff0c;提升交通效率&#xff0c;确保交通安全&#xff0c;并促进可持续发展。该…...

【quantity】6 温度单位实现(temperature.rs)

一源码 以下代码实现了一个温度单位系统&#xff0c;支持开尔文(Kelvin)和摄氏度(Celsius)之间的转换和运算。 /// Temperature (kelvin) / 温度 (开尔文) use super::{Quantity, prefix::*}; use crate::unit::Kelvin; use derive_more::{Add, Sub, AddAssign, SubAssign};/…...

ARConv的复现流程

使用环境 Python 3.10.16 torch 2.1.1cu118 torchvision 0.16.1cu118 其它按照官方提供代码的requirements.txt安装 GitHub - WangXueyang-uestc/ARConv: Official repo for Adaptive Rectangular Convolution 数据准备 从官方主页下载pancollection数据集PanCollection…...

安卓游戏APK文件解密与编辑的完整攻略

在移动游戏开发中,保护游戏数据不被篡改是开发者的重要任务。然而,随着逆向工程技术的发展,破解游戏数据也变得可能。本文将详细介绍如何分析、解密和编辑APK安装包中的加密JSON文件,特别关注assets/task目录下的文件,并提供一种绕过checkfile.json中MD5校验的有效方法。通…...

JVM——JVM 是如何执行方法调用的?

JVM 是如何执行方法调用的&#xff1f; 在 Java 世界的底层运作中&#xff0c;方法调用机制是理解 Java 虚拟机&#xff08;JVM&#xff09;行为的关键之一。JVM 作为 Java 程序运行的核心&#xff0c;承担着执行字节码、管理内存、调度线程等多项职责。而方法调用作为程序逻辑…...

一天学完JDBC!!(万字总结)

文章目录 JDBC是什么 1、环境搭建 && 入门案例2、核心API理解①、注册驱动(Driver类)②、Connection③、statement(sql注入)④、PreparedStatement⑤、ResultSet 3、jdbc扩展(ORM、批量操作)①、实体类和ORM②、批量操作 4. 连接池①、常用连接池②、Durid连接池③、Hi…...

【愚公系列】《Manus极简入门》011-习惯养成教练:“习惯塑造师”

&#x1f31f;【技术大咖愚公搬代码&#xff1a;全栈专家的成长之路&#xff0c;你关注的宝藏博主在这里&#xff01;】&#x1f31f; &#x1f4e3;开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主&#xff01; &#x1f…...

精益数据分析(38/126):SaaS模式的流失率计算优化与定价策略案例

精益数据分析&#xff08;38/126&#xff09;&#xff1a;SaaS模式的流失率计算优化与定价策略案例 在创业和数据分析的领域中&#xff0c;我们不断探索如何更精准地把握业务发展的关键要素。今天&#xff0c;带着与大家共同进步的想法&#xff0c;深入研读《精益数据分析》&a…...

50.【必备】二分答案法与相关题目

本文的网课内容学习自B站左程云老师的算法详解课程&#xff0c;旨在对其中的知识进行整理和分享~ 网课链接&#xff1a;算法讲解051【必备】二分答案法与相关题目_哔哩哔哩_bilibili 一.爱吃香蕉的珂珂 题目&#xff1a;爱吃香蕉的珂珂 算法原理 整体思路 这是一个二分查找算法…...

C# 方法(局部变量和局部常量)

本章内容: 方法的结构 方法体内部的代码执行 局部变量 局部常量 控制流 方法调用 返回值 返回语句和void方法 局部函数 参数 值参数 引用参数 引用类型作为值参数和引用参数 输出参数 参数数组 参数类型总结 方法重载 命名参数 可选参数 栈帧 递归 局部变量 和第5章介绍的字段…...

MQTT 协议与 HTTP 协议的区别

在现代的网络通信中&#xff0c;MQTT 协议和 HTTP 协议都扮演着重要的角色&#xff0c;但它们有着不同的特点和适用场景。下面我们就从多个方面来详细探讨它们之间的区别。 一.协议设计理念 1. MQTT 协议 MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;即…...

博弈论思维——AI与思维模型【90】

一、定义 博弈论思维模型是一种研究在相互影响的决策情境中&#xff0c;参与者如何通过策略选择来实现自身利益最大化的理论框架。它分析参与者之间的相互作用、策略组合以及由此产生的结果&#xff0c;帮助人们理解在竞争或合作环境下的决策逻辑和行为模式。 二、由来 博弈…...

【Bootstrap V4系列】学习入门教程之 表格(Tables)和画像(Figure)

Bootstrap V4系列 学习入门教程之 表格&#xff08;Tables&#xff09;和画像&#xff08;Figure&#xff09; 表格&#xff08;Tables&#xff09;一、Examples二、Table head options 表格头选项三、Striped rows 条纹行四、Bordered table 带边框的表格五、Borderless table…...

第 3 篇:有序的世界:有序表 (TreeMap/TreeSet) 的概念与优势

上一篇我们探讨了哈希表如何以牺牲顺序为代价换取极致的平均速度。然而&#xff0c;在现实世界的许多应用中&#xff0c;数据的有序性不仅是锦上添花&#xff0c;甚至是核心需求。想象一下&#xff1a; 你需要显示一个按价格排序的商品列表。你需要找到某个时间点之前或之后的…...

VulnHub-DC-2靶机

主机发现 sudo arp-scan -l 以sudo管理员权限扫描本地活动ip地址 Interface: eth0, type: EN10MB, MAC: 08:00:27:22:46:4f, IPv4: 192.168.252.230 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.252.6 4c:5f:70:74:3c:3b …...

论文笔记(八十三)STACKGEN: Generating Stable Structures from Silhouettes via Diffusion

STACKGEN: Generating Stable Structures from Silhouettes via Diffusion 文章概括摘要I. INTRODUCTIONII. 相关工作A. 从直觉物理学学习稳定性B. 用于姿态生成的扩散模型C. 自动化顺序装配 III. 方法A. 用于 S E ( 3 ) SE(3) SE(3)积木姿态生成的扩散模型B. 模型架构C. 数据生…...

论文阅读笔记——TesserAct: Learning 4D Embodied World Models

TesserAct 论文 采用RGB-DN&#xff08;RGB深度法线&#xff09; 作为 4D 场景中间表示&#xff0c;由此建模 4D 场景&#xff0c;比纯 2D 视频更准确地建模 3D 几何结构。相比现有的 4D 视频生成&#xff0c;优化速度快&#xff0c;收敛好&#xff0c;且首次从当前帧和文本描述…...

变转速振动信号分析处理与故障诊断算法模块

变转速振动信号分析处理与故障诊断算法模块&#xff0c;作为信号处理算法工具箱的主要功能模块&#xff0c;形成了以变转速振动信号分析处理与故障诊断算法模块的经典算法模型&#xff0c;可应用于各类关键机械部件&#xff08;轴承、齿轮、转子等&#xff09;的信号分析、故障…...

每日算法-250502

每日算法 - 2025.05.02 记录一下今天刷的几道 LeetCode 算法题。 3191. 使二进制数组全部等于 1 的最少操作次数 I 题目 思路 贪心 解题过程 遍历数组 nums。当我们遇到 nums[i] 时&#xff1a; 如果 nums[i] 是 1&#xff0c;我们不需要进行操作&#xff0c;因为目标是全 …...

如何在纯C中实现类、继承和多态(小白友好版)

基本实现原理 /* 通过结构体函数指针模拟类 */ typedef struct {// 成员变量int x; // 成员方法&#xff08;函数指针&#xff09; void (*print)(void* self); } MyClass;/* 成员函数实现 */ void my_print(void* self) {MyClass* obj (MyClass*)self;p…...

AE/PR插件 转场创建大师专业版 Transition Master Pro v2.0.2 Win+使用教程

Transition Master Pro v2.0.2是一款原生转场插件&#xff0c;专为Adobe Premiere Pro和After Effects设计。它提供了创建、导出和销售自己的转场效果&#xff0c;或从一个庞大的转场预设库中选择。使用Transition Master Pro v2.0.2&#xff0c;您可以快速轻松地创建令人惊叹的…...

[Linux]从零开始的STM32MP157 Buildroot根文件系统构建

一、前言 在前面的教程中&#xff0c;教了大家如何移植一个LInux的内核并且正确启动&#xff0c;我们发现Linux内核在启动后会出现一个错误&#xff0c;提示我们没有找到根文件系统。那么什么是根文件系统呢&#xff1f;之前我们使用Ubuntu编译了STM32MP157的TF-A,UBOOT,LINUX内…...

阿里云服务器 篇五(加更):短链服务网站:添加反垃圾邮件功能

文章目录 系列文章(可选)更新YOURLS版本安装 Compliance 插件安装 Phishtank-2.0 插件(可选)安装 httpBL 插件样例网站(不推荐)使用谷歌解决方案更多系列文章 阿里云服务器 篇一:申请和初始化 阿里云服务器 篇二:搭建静态网站 阿里云服务器 篇三:提交搜索引擎收录 阿…...

状压 DP 详解

文章目录 简介做法洛谷 P1171 简介 状压 DP 其实约等于一个 DP 的小技巧&#xff0c;一般应用在处理一个或多个集合的问题中&#xff08;因为状压 DP 的下标就是一个集合&#xff09;&#xff0c;而且在 n n n 太大的时候建议不要使用这种方法。&#xff08;如果你不懂&#…...

多模态大模型轻量化探索-视觉大模型SAM(Segment Anything Model)

往期&#xff0c;笔者基于LLava的数据对齐训练&#xff0c;搞了一个Reyes多模态大模型&#xff0c;并且看了些多模态大模型&#xff0c;相关开源的多模态大模型如&#xff1a;KimiVL、Internvl、QwenVL等&#xff0c;其视觉编码器的尺寸都比较大&#xff0c;如&#xff1a;Moon…...

数据分析_问题/优化

1 报表开发 1.1 数据问题 (1) 数据易错 问题描述 ①数据整合困难:数据来源多样、格式差异大,整合时处理不当易丢错数据. ②计算逻辑复杂:开发人员对复杂计算逻辑的理解产生偏差,会导致计算结果不准. 解决方案 ①建立数据标准,统一修正字段命名、数据类型、日期格式等 ②加强…...