【数据结构】——顺序表与链表
顺序表与链表
- 线性表
- 顺序表
- 链表
- 链表的概念
- 链表的分类
- 不带头单向非循环链表的实现
- 带头双向循环链表的实现
- 顺序表与链表的区别
线性表
线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构。
- 常见的线性结构:顺序表、链表、栈、队列、字符串……
线性表在逻辑上是线性结构,也就是说是连续的一条直线,但是在物理结构上并不一定是连续的,线性表在物理存储时,通常以数组和链式结构的形式存储。
顺序表
顺序表从开始连续存储size个
顺序表时用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组数据存储,在数组上完成数组的增删查改。
顺序表一般分为:
1.静态顺序表
缺点:保存数据的数组较小不够使用,较大浪费
//静态顺序表
typedef int SLDateType;
#define N 10
struct Seqlist
{SLDateType a[N];int size;
};
2.动态顺序表
可以实现按需申请
- 此时,如果free出现问题,原因可能是指针为野指针,指针未从初始地址释放或者指针越界
//动态顺序表
typedef int SLDateType;
struct Seqlist
{SLDateType* a;int size;int capacity;
};
- 使用顺序表完成增删查改
seqlist.h文件
#define _CRT_SECURE_NO_WARNINGS 1
//头文件
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>静态顺序表
//typedef int SLDateType;
//#define N 10
//struct Seqlist
//{
// SLDateType a[N];
// int size;
//};//动态顺序表
//定义类型
typedef int SLDataType;
//设置初始容量
#define INIT_CAPACITY 5typedef struct Seqlist
{SLDataType* a;//有效数据个数int size;//容量int capacity;
}SL;//初始化顺序表
void SLInit(SL* ps);
//销毁顺序表
void SLDestroy(SL* ps);
//打印顺序表
void SLPrint(SL* ps);
//增
//后增
void SLPushBack(SL* ps, SLDataType X);
//前增
void SLPushFront(SL* ps, SLDataType X);
//插入
void SLInsert(SL* ps, int pos, SLDataType X);
//删
//后删
void SLPopBack(SL* ps);
//前删
void SLPopFront(SL* ps);
//中间删除
void SLErase(SL* ps, int pos);
//查
int SLFind(SL* ps, SLDataType X);
//改
int SLChange(SL* ps, SLDataType X,SLDataType Y);
//扩容
void SLCheckCap
seqlist.c文件
#include"seqlist.h"//初始化顺序表
void SLInit(SL* ps)
{assert(ps->a);ps->a = (SLDataType*)malloc(sizeof(SLDataType) * INIT_CAPACITY);if (ps->a == NULL){perror("Malloc fail");}ps->size = 0;ps->capacity = INIT_CAPACITY;
}//销毁顺序表
void SLDestroy(SL* ps)
{assert(ps->a);free(ps->a);ps->a = NULL;ps->size = ps->capacity = 0;
}//打印顺序表
void SLPrint(SL* ps)
{assert(ps->a);int i = 0;for (i = 0; i < ps->size; i++){printf("%d ",ps->a[i]);}printf("\n");
}//后增
void SLPushBack(SL* ps, SLDataType X)
{assert(ps->a);SLCheckCapacity(ps);ps->a[ps->size] = X;ps->size++;
}//后删
void SLPopBack(SL* ps)
{assert(ps->a);assert(ps->size>0);/*if (ps->size == 0){return;}*/ps->size--;
}//前增
void SLPushFront(SL* ps, SLDataType X)
{assert(ps->a);SLCheckCapacity(ps);int end = ps->size - 1;while (end >= 0){ps->a[end+1] = ps->a[end];end--;}ps->a[0] = X;ps->size++;
}//前删
void SLPopFront(SL* ps)
{assert(ps->a);int begin = 0;while (begin >= 0 && begin < ps->size){ps->a[begin] = ps->a[begin + 1];begin++;}ps->size--;
}//中间插入
void SLInsert(SL* ps, int pos, SLDataType X)
{assert(ps);assert(pos >= 0 && pos <= ps->size);SLCheckCapacity(ps);int end = ps->size - 1;while (end >= pos){ps->a[end + 1] = ps->a[end];end--;}ps->a[pos] = X;ps->size++;
}//中间删除
void SLErase(SL* ps, int pos)
{assert(ps->a);assert(pos >= 0 && pos <= ps->size);int begin = pos;while (begin >= pos && begin <= ps->size){ps->a[begin] = ps->a[begin + 1];begin++;}ps->size--;
}//查找
int SLFind(SL* ps, SLDataType X)
{assert(ps->a);int i = 0;for (i = 0; i < ps->size; i++){if (ps->a[i] == X){return i;}}return -1;
}//改
int SLChange(SL* ps, SLDataType X , SLDataType Y)
{assert(ps->a);int i = 0;for (i = 0; i < ps->size; i++){if (ps->a[i] == X){ps->a[i] = Y;return 0;}}return -1;
}//扩容
void SLCheckCapacity(SL* ps)
{if (ps->size == ps->capacity){SLDataType* p = (SLDataType*)realloc((void*)ps->a, ps->capacity * sizeof(SLDataType)*2);if (p == NULL){printf("Realloc fail");return;}ps->a = p;p = NULL;ps->capacity *= 2;}
}
main.c文件
#include"seqlist.h"//测试顺序表
void TestSeqlist1()
{//定义顺序表SL s;//初始化顺序表SLInit(&s);//后增SLPushBack(&s,1);SLPushBack(&s, 2);SLPushBack(&s, 3);SLPushBack(&s, 4);//后删SLPopBack(&s);//打印SLPrint(&s);//前增SLPushFront(&s, 10);SLPushFront(&s, 20);SLPushFront(&s, 40);//打印SLPrint(&s);//前删SLPopFront(&s);//打印SLPrint(&s);//中间插入SLInsert(&s, 1, 6);//打印SLPrint(&s);//中间删除SLErase(&s, 2);//打印SLPrint(&s);//改SLChange(&s, 2, 9);//打印SLPrint(&s);//销毁顺序表SLDestroy(&s);
}int main(void)
{//测试顺序表TestSeqlist1();return 0;
}
链表
了解完顺序表之后,可以明显发现顺序的缺点:
- 中间与头部的插入删除,时间复杂度为O(N)
- 增容需要申请空间,拷贝数据,释放旧空间,会有不小的消耗
- 增容一般是呈2倍增长,会有一定的空间浪费
链表的概念
链表是一种物理存储的结构上非连续,非顺序的存储结构,数据元素的逻辑是通过链表中的指针链接次序实现的
注意:
1.链式结构在逻辑上是连续的,但是在物理上不一定连续。
2.现实中的结点一边拿都是从堆上申请出来的
3.从堆上申请的空间是按照一定的策略来分配的,俩次申请的空间可能连续,也可能不连续
链表的分类
- 链表的分类大致分为:
1.单向或者双向
2.带头或者不带头
3.循环或者非循环
其中最常用的是不带头单向非循环链表与带头双向循环链表
- 不带头单向非循环链表:
结构简单,一般不会单独用来存数据,实际中更多是作为其他数据结构的子结构,如哈希桶,图的邻接表等等
- 带头双向循环链表:
结构最复杂,一般用来单独存储数据,实际中使用的链表数据结构,都是双向循环链表
不带头单向非循环链表的实现
- slist.h文件
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLTDatatype;typedef struct SLinklistNode
{SLTDatatype date;struct SLinklistNode* next;
}SLTNode;//增加结点
SLTNode* SLTNewNode(SLTDatatype X);//打印
void SLTPrintf(SLTNode* phead);
//头插
void SLTPushFront(SLTNode** pphead, SLTDatatype X);
//头删
void SLTPopFront(SLTNode** pphead);
//尾插
void SLTPushBack(SLTNode** pphead, SLTDatatype X);
//尾删
void SLTPopBack(SLTNode** pphead);
//查找
SLTNode* SLTFind(SLTNode* pphead,SLTDatatype X);
//前插
void SLTInsertBefore(SLTNode** pphead, SLTNode* pos ,SLTDatatype X);
//pos位置删
void SLTEraseBefore(SLTNode** pphead, SLTNode* pos);
//后插
void SLTInsertAfter(SLTNode** pphead, SLTNode* pos, SLTDatatype X);
//后删
void SLTEraseAfter(SLTNode** pphead, SLTNode* pos);
//销毁
void SLTDestory(SLTNode** pphead);
- slist.c文件
#include"slist.h"//打印
void SLTPrintf(SLTNode* phead)
{SLTNode* cur = phead;while (cur){printf("%d->", cur->date);cur = cur->next;}printf("NULL\n");
}//新增加一个结点
SLTNode* SLTNewNode( SLTDatatype X)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc fail");return NULL;}newnode->date = X;newnode->next = NULL;return newnode;
}//头插
void SLTPushFront(SLTNode** pphead, SLTDatatype X)
{//动态增加一个结点SLTNode* newnode = SLTNewNode(X);newnode->next = *pphead;*pphead = newnode;
}//头删
void SLTPopFront(SLTNode** pphead)
{//温柔/*if (*pphead == NULL){return;}*///断言assert(*pphead);SLTNode* first = *pphead;*pphead = first->next;free(first);first = NULL;
}//尾删
void SLTPopBack(SLTNode** pphead)
{if (*pphead == NULL){return;}assert(*pphead);if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{SLTNode* tail = *pphead;while (tail->next->next != NULL){tail = tail->next;}free(tail->next);tail->next = NULL;}
}//尾增
void SLTPushBack(SLTNode** pphead, SLTDatatype X)
{//新增一个结点SLTNode* newnode = SLTNewNode(X);SLTNode* tail = *pphead;if (*pphead == NULL){*pphead = newnode;}else{while (tail->next != NULL){tail = tail->next;}tail->next = newnode;}}//查找
SLTNode* SLTFind(SLTNode* pphead,SLTDatatype X)
{SLTNode* cur = pphead;while (cur){if (cur->date == X){return cur;}cur = cur->next;}return NULL;
}//前插
void SLTInsertBefore(SLTNode** pphead, SLTNode* pos, SLTDatatype X)
{assert(pos);assert(pphead);if (*pphead == pos){SLTPushFront(pphead, X);}else{SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}SLTNode* newnode = SLTNewNode(X);prev->next = newnode;newnode->next = pos;}
}//pos位置删
void SLTEraseBefore(SLTNode** pphead, SLTNode* pos)
{assert(pphead);assert(pos);assert(*pphead);if (*pphead == pos){SLTPopFront(pphead);}SLTNode* prev = *pphead;while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);
}//后插
void SLTInsertAfter(SLTNode** pphead, SLTNode* pos, SLTDatatype X)
{assert(pos);SLTNode* newnode = SLTNewNode(X);newnode->next = pos->next;pos->next = newnode;
}//后删
void SLTEraseAfter(SLTNode** pphead, SLTNode* pos)
{assert(pos);assert(pos->next);SLTNode* del = pos->next;pos->next = del->next;free(del);del = NULL;
}
//销毁
void SLTDestory(SLTNode** pphead)
{SLTNode* cur = *pphead;while(cur){SLTNode* tmp = cur->NEXT;free(cur);cur = tmp;}*pphead = NULL;
}
带头双向循环链表的实现
Dlist.h文件
#define _CRT_SECURE_NO_WARNINGS 1
//带头双向循环链表的增删查改
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>//定义类型
typedef int LTDataType;//定义结构体
typedef struct ListNode
{LTDataType data;struct ListNode* prev;struct ListNode* next;
}ListNode;//创建一个返回链表的头结点(哨兵)
ListNode* ListCreate();//双向链表的销毁
void ListDestory(ListNode* phead);//双向链表的打印
void ListPrintf(ListNode* phead);//创造一个newnode
ListNode* ListNewNode(LTDataType x);//双向链表的尾插
void ListPushBack(ListNode* phead, LTDataType x);//双向链表的尾删
void ListPopBack(ListNode* phead);//双向链表的头插
void ListPushFront(ListNode* phead, LTDataType x);//双向链表的头删
void ListPopFront(ListNode* phead);//双向链表的查找
ListNode* ListFind(ListNode* phead, LTDataType x);//双向链表在pos前插入
void ListInsert(ListNode* phead, LTDataType x);//双向链表在pos删除
void ListErase(ListNode* pos);
Dlist.c文件
#include"DList.h"
//创建一个返回链表的头结点(哨兵)
ListNode* ListCreate()
{ListNode* phead = ListNewNode(-1);phead->next = phead;phead->prev = phead;return phead;
}//双向链表的销毁(需自行释放哨兵头)
void ListDestory(ListNode* phead)
{assert(phead);ListNode* cur = phead->next;while (cur != phead){ListNode* tail = cur;cur = cur->next;free(tail);tail = NULL;}
}//双向链表的打印
void ListPrintf(ListNode* phead)
{assert(phead);ListNode* cur = phead->next;printf("->NULL->");while (cur != phead){printf("%d->", cur->data);cur = cur->next;}printf("\n");
}//创造一个newnode
ListNode* ListNewNode(LTDataType x)
{ListNode* newnode = (ListNode*)malloc(sizeof(ListNode));if (newnode == NULL){perror("malloc fail");return NULL;}newnode->data = x;newnode->next = NULL;newnode->prev = NULL;return newnode;
}//双向链表的尾插
void ListPushBack(ListNode* phead, LTDataType x)
{assert(phead);ListNode* newnode = ListNewNode(x);newnode->next = phead;newnode->prev = phead->prev;phead->prev->next = newnode;phead->prev = newnode;
}//双向链表的尾删
void ListPopBack(ListNode* phead)
{assert(phead);assert(phead->next != phead);ListNode* tail = phead->prev;phead->prev = tail->prev;tail->prev->next = phead;free(tail);tail = NULL;
}//双向链表的头插
void ListPushFront(ListNode* phead, LTDataType x)
{assert(phead);ListNode* newnode = ListNewNode(x);newnode->next = phead->next;newnode->prev = phead;phead->next->prev = newnode;phead->next = newnode;
}//双向链表的头删
void ListPopFront(ListNode* phead)
{assert(phead);assert(phead->next != phead);ListNode* first = phead->next;phead->next = first->next;first->next->prev = phead;free(first);first = NULL;
}//双向链表的查找
ListNode* ListFind(ListNode* phead, LTDataType x)
{assert(phead);ListNode* cur = phead->next;while (cur != phead){if (cur->data == x){return cur;}cur = cur->next;}return NULL;
}//双向链表在pos前插入
void ListInsert(ListNode* pos, LTDataType x)
{assert(pos);ListNode* newnode = ListNewNode(x);ListNode* front = pos->prev;newnode->prev = front;newnode->next = pos;front->next = newnode;pos->prev = newnode;
}//双向链表在pos删除(自行释放指针)
void ListErase(ListNode* pos)
{assert(pos);pos->prev->next = pos->next;pos->next->prev = pos->prev;free(pos);
}
顺序表与链表的区别
不同点 | 顺序表 | 链表 |
---|---|---|
存储空间上 | 物理上连续 | 逻辑上连续,物理上不一定连续 |
随机访问 | 支持:O(1) | 不支持:O(N) |
任意位置插入或者删除元素 | 可能需要移动元素,效率低O(N) | 只需要修改指针指向 |
插入 | 动态顺序表,空间不够需要扩容 | 没有容量的概念 |
应用场景 | 元素高效访问,频繁访问 | 任意位置插入和删除频繁 |
缓存利用率 | 高 | 低 |
相关文章:

【数据结构】——顺序表与链表
顺序表与链表 线性表顺序表链表链表的概念链表的分类不带头单向非循环链表的实现带头双向循环链表的实现顺序表与链表的区别 线性表 线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构。 常见的线性结构:顺序表、链表、栈、队…...
C++简洁版全排列代码
《代码随想录》在回溯章节中的全排列代码模板较为复杂,其实还有一种常用写法,思路是交换元素位置后做dfs(),并回溯。对应leetcode46题。 class Solution { public:vector<vector<int>> res;void dfs(vector<int>num, int k){// k代表…...

2024电工杯B题保姆级分析完整思路+代码+数据教学
2024电工杯B题保姆级分析完整思路代码数据教学 B题题目:大学生平衡膳食食谱的优化设计及评价 接下来我们将按照题目总体分析-背景分析-各小问分析的形式来 总体分析: 题目要求对两份一日膳食食谱进行营养分析和调整,然后设计优化的平衡膳…...

基于svm的水果识别
1、程序界面介绍 该程序GUI界面包括待检测水果图片加载、检测结果输出、清空可视化框等。其中包括训练模型、加载图片、重置、识别检测按钮。 程序GUI界面 识别玉米识别西瓜 分类器识别水果基本原理: 由于每种水果的外形存在很大差异,比如西瓜与玉米&…...
【DevOps】深入理解 Nginx Location 块:配置示例与应用场景详解
目录 一、location 块的基本概念 二、location 块的语法 三、location 块的匹配方式 四、location 块的优先级 五、location 块的应用场景 六、location 块的嵌套 七、location 块的指令 八、示例配置 Nginx 是一个高性能的 Web 服务器和反向代理服务器,它广…...

专业渗透测试 Phpsploit-Framework(PSF)框架软件小白入门教程(十一)
本系列课程,将重点讲解Phpsploit-Framework框架软件的基础使用! 本文章仅提供学习,切勿将其用于不法手段! 接上一篇文章内容,讲述如何进行Phpsploit-Framework软件的基础使用和二次开发。 我们,继续讲一…...
未来机器人的发展方向
未来机器人的发展方向是多元化且充满潜力的。以下是一些主要的发展方向: 人工智能与机器学习的集成:随着人工智能(AI)和机器学习(ML)技术的不断进步,机器人将变得更加智能化和自主化。这些技术将…...
美国硅谷高防服务器有哪些优势
美国硅谷高防服务器是位于美国硅谷的,具备高级防护能力的服务器。这种服务器针对网络安全威胁提供了增强的保护措施,以确保数据的安全和业务的连续性。Rak部落小编为您整理发布美国硅谷高防服务器有哪些优势。 具体介绍如下: 1. 安全性&#…...

Django介绍:探索Python最受欢迎的Web框架
文章目录 Django是什么Django的核心特性1. MTV架构2. 自带的Admin后台管理系统3. ORM(对象关系映射)4. 强大的表单处理5. 完善的文档和活跃的社区 快速入门:使用Django创建一个简单的Web应用步骤1:安装Django步骤2:创建…...

【Unity Shader入门精要 第9章】更复杂的光照(四)
1. 透明度测试物体的阴影 对于物体有片元丢弃的情况,比如透明度测试或者后边会讲到的消融效果,使用默认的 ShadowCaster Pass 会产生问题,这是因为该Pass在生成阴影映射纹理时,没有考虑被丢弃的片元,而是使用完整的模…...

【软件工程】【23.10】p2
关键字: 软件复用技术、过程途径、特定需求是文档核心、数据字典条目、高内聚低耦合独立性、数据流图映射模块结构图、UML依赖、用例图关系、RUB迭代、程序规格说明等价类划分、有效性测试的目标、喷泉模型面向对象、软件验证过程、CMMI...
WPF--几种常用定时器Timer汇总
1.WPF中常用4种Timer: System.Windows.Threading.DispatcherTimer(UI操作线程) 这是一个基于WPF Dispatcher的计时器。它可以在指定的时间间隔内触发Tick事件,并在UI线程上执行回调函数,方便进行UI更新操作。 System.Timers.Timer 这是一个基…...

在vue中实现下载文件功能
实际操作为,在表格中 我们可以获取到文件的id,通过插槽就可以实现 <template #default"scope"><el-button type"text" click"handleDown(scope.row)"><span>下载</span></el-button> </…...

文件中海量数据的排序
文件中海量数据的排序 题目: 跟之前堆排序可以解决TopK问题一样,我们来看看归并排序会用来解决什么问题? 思路: 我们说归并排序是外排序。其实就是将数据分成一个个小段,在内存中进行排序,再拿出内存&am…...

java项目之视频网站系统源码(springboot+vue+mysql)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的视频网站系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 视频网站系统的主要使用者管…...

262 基于matlab的一级倒立摆仿真
基于matlab的一级倒立摆仿真,在对一级倒立摆进行数学建模的基础上,对模型进行线性化,得到其状态空间模型,利用二次型最优控制方法得出控制率。输出角度和位置优化曲线。程序已调通,可直接运行。 262 一级倒立摆仿真 状…...

智能无网远控再升级 向日葵Q2Pro升级版发布
无网或者内网设备也想要进行远程控制,是不是听上去有些天方夜谭了?其实这类特种设备的远程控制需求是非常强的,比如医疗/工控设备的远程运维、使用指导教学等等。 实际上,只要这类设备有屏幕,支持可视化的桌面操作&am…...

2024电工杯A题详细思路代码分析数学建模:园区微电网风光储协调优化配置
题目分析:园区微电网风光储协调优化配置 我们会先给出三个问题总体的分析,最后会详细分析问题一的建模和详细内容。 背景: 园区微电网由风光发电和主电网联合为负荷供电,为了尽量提高风光电量的负荷占比,需配置较高比…...

Docker搭建mysql性能测试环境
OpenEuler使用Docker搭建mysql性能测试环境 一、安装Docker二、docker安装mysql三、测试mysql连接 一、安装Docker 建立源文件vim /etc/yum.repos.d/docker-ce.repo增加内容[docker-ce-stable] nameDocker CE Stable - $basearch baseurlhttps://repo.huaweicloud.com/docker…...

关于开启直连v2rayn代理Fiddler Charles bp抓包失败问题
Fiddler 使用插件:proxy switchyomega 配置代理8888端口为fiddler && charles的监听端口 此时fiddler提示代理已更改点击变更捕获,这时不需要进行点击只需要开启上述插件即可抓到包并且国外代理,如果点击的话回自动更新为原来的ip 即…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
RestClient
什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端,它允许HTTP与Elasticsearch 集群通信,而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级ÿ…...

DAY 47
三、通道注意力 3.1 通道注意力的定义 # 新增:通道注意力模块(SE模块) class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...

tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

论文阅读:Matting by Generation
今天介绍一篇关于 matting 抠图的文章,抠图也算是计算机视觉里面非常经典的一个任务了。从早期的经典算法到如今的深度学习算法,已经有很多的工作和这个任务相关。这两年 diffusion 模型很火,大家又开始用 diffusion 模型做各种 CV 任务了&am…...
怎么开发一个网络协议模块(C语言框架)之(六) ——通用对象池总结(核心)
+---------------------------+ | operEntryTbl[] | ← 操作对象池 (对象数组) +---------------------------+ | 0 | 1 | 2 | ... | N-1 | +---------------------------+↓ 初始化时全部加入 +------------------------+ +-------------------------+ | …...

【iOS】 Block再学习
iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...
Python爬虫实战:研究Restkit库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地采集这些数据并将其应用于实际业务中,成为了许多企业和开发者关注的焦点。网络爬虫技术作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 RESTful API …...