list常用接口模拟实现
文章目录
- 一、模拟list类的框架
- 二、函数接口实现
- 1、迭代器接口
- 2、常用删除、插入接口
- 3、常用其他的一些函数接口
- 4、默认成员函数
一、模拟list类的框架
1、使用带哨兵的双向链表实现。
2、链表结点:
// List的结点类
template<class T>
struct ListNode
{ListNode<T>* _pPre; //后继指针ListNode<T>* _pNext; //前驱指针T _val; //数据//构造结点ListNode(const T& val = T()) :_val(val), _pPre(nullptr), _pNext(nullptr){}
};
3、list类的成员变量和构造双向链表的哨兵位结点函数。
//让哨兵位结点指向自己
typedef ListNode<T> Node;
typedef Node* PNode;void CreateHead(){_pHead = new Node;_pHead->_pNext = _pHead;_pHead->_pPre = _pHead;}PNode _pHead; //哨兵位结点
二、函数接口实现
1、迭代器接口
list的迭代器是双向迭代器,支持++、–,但是它们在内存上储存是不连续的,无法简单通过指针去进行++、–操作,所以我们要对list的迭代器进行封装。
(1)list正向迭代器类
成员变量:两个结点指针。
typedef ListNode<T>* PNode;
PNode _pNode; //结点指针
PNode _P;//保存哨兵位结点指针,用于判断解引用是否访问哨兵位结点
构造函数:
//构造函数 ,获取一个结点指针ListIterator(const PNode & pNode = nullptr, const PNode& const P = nullptr) :_pNode(pNode),_P(P){}
拷贝构造、赋值、析构函数:
因为_pNode的指针指向的内存是有list类释放的,所以该类无需进行资源清理,使用浅拷贝即可,所以拷贝、赋值、析构都使用编译器生成的即可。
重载操作符:
//Ref为T& Ptr为T*typedef ListIterator<T, Ref, Ptr> Self;//解引用Ref operator*(){assert(_P != _pNode);return _pNode->_val;}//该运算符重载的意义为T为自定义类型时使用,迭代器可以通过该运算符直接访问自定义类型成员Ptr operator->(){return &(_pNode->_val);}//前置++Self& operator++(){_pNode = _pNode->_pNext;return *this;}//后置++Self operator++(int){Self tmp(_pNode);_pNode = _pNode->_pNext;return tmp;}//前置--Self& operator--(){_pNode = _pNode->_pPre;return *this;}//后置--Self& operator--(int){Self tmp(_pNode);_pNode = _pNode->_pPre;return tmp;}//比较bool operator!=(const Self& l){return l._pNode != _pNode;}bool operator==(const Self& l){return l._pNode == _pNode;}
获取成员变量函数:
//获取该迭代器成员变量PNode get(){return _pNode;}
ListIterator类一览:
//Ref为T& Ptr为T*
template<class T, class Ref, class Ptr>
class ListIterator
{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;
public://构造函数 ,获取一个结点指针ListIterator(const PNode & pNode = nullptr, const PNode& const P = nullptr) :_pNode(pNode),_P(P){}Ref operator*(){assert(_P != _pNode);return _pNode->_val;}Ptr operator->(){return &(operator*());}Self& operator++(){_pNode = _pNode->_pNext;return *this;}Self operator++(int){Self tmp(_pNode);_pNode = _pNode->_pNext;return tmp;}Self& operator--(){_pNode = _pNode->_pPre;return *this;}Self& operator--(int){Self tmp(_pNode);_pNode = _pNode->_pPre;return tmp;}bool operator!=(const Self& l){return l._pNode != _pNode;}bool operator==(const Self& l){return l._pNode == _pNode;}PNode get(){return _pNode;}
private:PNode _pNode;PNode _P;
};
};
(2)反向迭代器类
与正向迭代器不一样的有 *
操作符,_pNode
保存的是有效元素的下一个位置,如:想要的是_pNode->_pPre
指向的元素,但是该迭代器保存的是_pNode
的指针,还有++,–与正向迭代器相反。
其他操作与正向迭代器一致。
template<class T, class Ref, class Ptr>
class Reverse_ListIterator
{typedef ListNode<T>* PNode;typedef Reverse_ListIterator<T, Ref, Ptr> Self;
public:Reverse_ListIterator(const PNode& pNode = nullptr, const PNode& const P = nullptr) :_pNode(pNode), _P(P){}Ref operator*(){assert(_P != _pNode ->_pPre);return _pNode->_pPre->_val;}Ptr operator->(){return &(operator*());}Self& operator++(){_pNode = _pNode->_pPre;return *this;}Self operator++(int){Self tmp(_pNode);_pNode = _pNode->_pPre;return tmp;}Self& operator--(){_pNode = _pNode->_pNext;}Self& operator--(int){Self tmp(_pNode);_pNode = _pNode->_pNext;return tmp;}bool operator!=(const Self& l){return l._pNode != _pNode;}bool operator==(const Self& l){return l._pNode == _pNode;}PNode get(){return _pNode;}
private:PNode _pNode;PNode _P;
};
(3)list迭代器接口
//一些类型的重命名typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;typedef Reverse_ListIterator<T, T&, T*> reverse_iterator;typedef Reverse_ListIterator<T, const T&, const T*> reverse_const_iterator;// List Iterator//第一个有效元素位置的迭代器
iterator begin()
{return iterator(_pHead->_pNext,_pHead);
}
//最后一个有效元素位置的下一个位置的迭代器
iterator end()
{return iterator(_pHead,_pHead);
}
//加了const 修饰
const_iterator begin() const
{return const_iterator(_pHead->_pNext,_pHead);
}
const_iterator end()const
{return const_iterator(_pHead,_pHead);
}//反向迭代器
//哨兵位的位置reverse_iterator rbegin(){return reverse_iterator(_pHead,_pHead);}
//第一个有效元素位置reverse_iterator rend(){return reverse_iterator(_pHead ->_pNext,_pHead);}
//加了const修饰reverse_const_iterator rbegin() const{return reverse_const_iterator(_pHead,_pHead);}reverse_const_iterator rend()const{return reverse_const_iterator(_pHead->_pNext,_pHead);}
2、常用删除、插入接口
(1)insert
在迭代器位置前插入一个结点。
// 在pos位置前插入值为val的节点
iterator insert(iterator pos, const T & val)
{//创造一个结点PNode tmp = new Node(val);//获取迭代器中的指针PNode _pos = pos.get();//进行插入PNode prv = _pos->_pPre;prv->_pNext = tmp;tmp->_pPre = prv;tmp->_pNext = _pos;_pos->_pPre = tmp;//返回新迭代器return iterator(tmp);
}
迭代器是否失效:
因为插入新的结点,不会影响到原来的结点,所以该迭代器不会失效。
(2)erase
删除迭代器位置结点。
// 删除pos位置的节点,返回该节点的下一个位置
iterator erase(iterator pos)
{//判断是否为哨兵位结点iterator it = end();assert(pos != it);//获取迭代器结点指针PNode tmp = pos.get();//进行删除PNode next = tmp->_pNext;PNode prv = tmp->_pPre;prv->_pNext = next;next->_pPre = prv;delete tmp;tmp = nullptr;//返回被删除结点的下一个位置的结点迭代器return iterator(next);
}
迭代器是否失效:
因为将结点删除了,所以原本的迭代器是不能使用的,所以迭代器失效了。
(3)push_back、pop_back、push_front、pop_front
这里的头插、尾插、头删、尾删均复用上面两个函数接口。
void push_back(const T & val) { insert(end(), val); }
void pop_back() { erase(--end()); }
void push_front(const T & val) { insert(begin(), val); }
void pop_front() { erase(begin()); }
3、常用其他的一些函数接口
(1)size
返回大小,通过遍历链表即可找到。
size_t size()const
{//保存哨兵位的下一个位置PNode tmp = _pHead->_pNext;//开始遍历size_t count = 0;while (tmp != _pHead){tmp = tmp->_pNext;++count;}return count;
}
(2)empty
是否为空,判断哨兵位结点是否指向自己即可。
bool empty()const
{return _pHead == _pHead->_pNext;
}
(3)clear
清空链表,遍历链表逐个清空,保留哨兵位结点,再让哨兵位结点自己连接自己。
void clear(){//保存有效结点位置PNode tmp = _pHead->_pNext;//遍历删除while (tmp != _pHead){PNode p = tmp->_pNext;delete tmp;tmp = p;}//重新指向_pHead->_pNext = _pHead;_pHead->_pPre = _pHead;
(4)swap
交换,只需要交换指向哨兵位结点的指针即可。
void swap(list<T>& l)
{std::swap(_pHead, l._pHead);
}
(4)front
获取第一个位置的元素。
T& front()
{assert(!empty());return _pHead->_pNext->_val;
}
const T& front()const
{assert(!empty());return _pHead->_pNext->_val;
}
(5)back
获取最后一个位置元素。
T& back()
{assert(!empty());return _pHead->_pPre->_val;
}
const T& back()const
{assert(!empty());return _pHead->_pPre->_val;
}
4、默认成员函数
(1)构造函数
构造函数都会先进行构造哨兵位结点,再进行下面的操作,除了无参构造,其他都复用了尾插,将元素尾插到链表结尾。
//无参构造
list()
{ //构造一个哨兵位结点CreateHead();
}//利用n个val值进行构造
list(int n, const T& value = T())
{//构造一个哨兵位结点CreateHead();//将元素尾插入while (n != 0){push_back(value);--n;}
}//这里用迭代器区间构造,重写一个模板,使其可以使用其他容器的迭代器
template <class Iterator>
list(Iterator first, Iterator last)
{//构造一个哨兵位结点CreateHead();//将元素尾插入while (first != last){push_back(*first);++first;}
}//拷贝构造
list(const list<T>& l)
{//构造一个哨兵位结点CreateHead();//遍历+将元素尾插入PNode tmp = l._pHead->_pNext;while (tmp != l._pHead){push_back(tmp->_val);tmp = tmp->_pNext;}
}
(2)重载赋值运算符
通过传值传参构造一个临时容器 l ,再将其与原来的容器交换,当出了函数作用域之后临时容器就会调用析构函数,对临时容器的资源进行清理(就是原来容器的资源)。
list<T>& operator=(list<T> l)
{//与临时变量进行交换swap(l);return *this;
}
(3)析构函数
对链表清理。
~list()
{//清空链表clear();//删除哨兵位结点delete _pHead;_pHead = nullptr;
}
三、总代码
#pragma once
#include<iostream>
#include<assert.h>
#include<string>
using namespace std;namespace xu
{// List的结点类template<class T>struct ListNode{ListNode<T>* _pPre; //后继指针ListNode<T>* _pNext; //前驱指针T _val; //数据//构造结点ListNode(const T& val = T()) :_val(val), _pPre(nullptr), _pNext(nullptr){}};//List的正向迭代器类//Ref为T& Ptr为T*template<class T, class Ref, class Ptr>class ListIterator{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;public://构造函数 ,获取一个结点指针ListIterator(PNode pNode = nullptr) :_pNode(pNode){}Ref operator*(){return _pNode->_val;}Ptr operator->(){return &(operator*());}Self& operator++(){_pNode = _pNode->_pNext;return *this;}Self operator++(int){Self tmp(_pNode);_pNode = _pNode->_pNext;return tmp;}Self& operator--(){_pNode = _pNode->_pPre;return *this;}Self& operator--(int){Self tmp(_pNode);_pNode = _pNode->_pPre;return tmp;}bool operator!=(const Self& l){return l._pNode != _pNode;}bool operator==(const Self& l){return l._pNode == _pNode;}PNode get(){return _pNode;}private:PNode _pNode;};//List的反向迭代器类template<class T, class Ref, class Ptr>class Reverse_ListIterator{typedef ListNode<T>* PNode;typedef Reverse_ListIterator<T, Ref, Ptr> Self;public:Reverse_ListIterator(PNode pNode = nullptr) :_pNode(pNode){}Ref operator*(){return _pNode->_pPre->_val;}Ptr operator->(){return &(operator*());}Self& operator++(){_pNode = _pNode->_pPre;return *this;}Self operator++(int){Self tmp(_pNode);_pNode = _pNode->_pPre;return tmp;}Self& operator--(){_pNode = _pNode->_pNext;}Self& operator--(int){Self tmp(_pNode);_pNode = _pNode->_pNext;return tmp;}bool operator!=(const Self& l){return l._pNode != _pNode;}bool operator==(const Self& l){return l._pNode == _pNode;}PNode get(){return _pNode;}private:PNode _pNode;};//list类template<class T>class list{typedef ListNode<T> Node;typedef Node* PNode;public:typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;typedef Reverse_ListIterator<T, T&, T*> reverse_iterator;typedef Reverse_ListIterator<T, const T&, const T*> reverse_const_iterator;public://默认构造list() { //构造一个哨兵位结点CreateHead(); }list(int n, const T& value = T()){//构造一个哨兵位结点CreateHead();//将元素尾插入while (n != 0){push_back(value);--n;}}template <class Iterator>list(Iterator first, Iterator last){//构造一个哨兵位结点CreateHead();//将元素尾插入while (first != last){push_back(*first);++first;}}list(const list<T>& l){//构造一个哨兵位结点CreateHead();//遍历+将元素尾插入PNode tmp = l._pHead->_pNext;while (tmp != l._pHead){push_back(tmp->_val);tmp = tmp->_pNext;}}list<T>& operator=(list<T> l){//与临时变量进行交换swap(l);return *this;}~list(){//清空链表clear();//删除哨兵位结点delete _pHead;_pHead = nullptr;}///// List Iteratoriterator begin(){return iterator(_pHead->_pNext);}iterator end(){return iterator(_pHead);}const_iterator begin() const{return const_iterator(_pHead->_pNext);}const_iterator end()const{return const_iterator(_pHead);}reverse_iterator rbegin(){return reverse_iterator(_pHead);}reverse_iterator rend(){return reverse_iterator(_pHead ->_pNext);}reverse_const_iterator rbegin() const{return reverse_const_iterator(_pHead);}reverse_const_iterator rend()const{return reverse_const_iterator(_pHead->_pNext);}///// List Capacitysize_t size()const{PNode tmp = _pHead->_pNext;size_t count = 0;while (tmp != _pHead){tmp = tmp->_pNext;++count;}return count;}bool empty()const{return _pHead == _pHead->_pNext;}// List AccessT& front(){assert(!empty());return _pHead->_pNext->_val;}const T& front()const{assert(!empty());return _pHead->_pNext->_val;}T& back(){assert(!empty());return _pHead->_pPre->_val;}const T& back()const{assert(!empty());return _pHead->_pPre->_val;}// List Modifyvoid push_back(const T & val) { insert(end(), val); }void pop_back() { erase(--end()); }void push_front(const T & val) { insert(begin(), val); }void pop_front() { erase(begin()); }// 在pos位置前插入值为val的节点iterator insert(iterator pos, const T & val){//创造一个结点PNode tmp = new Node(val);//获取迭代器中的指针PNode _pos = pos.get();//进行插入PNode prv = _pos->_pPre;prv->_pNext = tmp;tmp->_pPre = prv;tmp->_pNext = _pos;_pos->_pPre = tmp;//返回新迭代器return iterator(tmp);}// 删除pos位置的节点,返回该节点的下一个位置iterator erase(iterator pos){//判断是否为哨兵位结点iterator it = end();assert(pos != it);//获取迭代器结点指针PNode tmp = pos.get();//进行删除PNode next = tmp->_pNext;PNode prv = tmp->_pPre;prv->_pNext = next;next->_pPre = prv;delete tmp;tmp = nullptr;//返回被删除结点的下一个位置的结点迭代器return iterator(next);}void clear(){//保存有效结点位置PNode tmp = _pHead->_pNext;//遍历删除while (tmp != _pHead){PNode p = tmp->_pNext;delete tmp;tmp = p;}//重新指向_pHead->_pNext = _pHead;_pHead->_pPre = _pHead;}void swap(list<T>& l){std::swap(_pHead, l._pHead);}private://让哨兵位结点指向自己void CreateHead(){_pHead = new Node;_pHead->_pNext = _pHead;_pHead->_pPre = _pHead;}PNode _pHead; //哨兵位结点};};
相关文章:

list常用接口模拟实现
文章目录 一、模拟list类的框架二、函数接口实现1、迭代器接口2、常用删除、插入接口3、常用其他的一些函数接口4、默认成员函数 一、模拟list类的框架 1、使用带哨兵的双向链表实现。 2、链表结点: // List的结点类 template<class T> struct ListNode {Li…...
前端工程化工具系列(三) —— Stylelint(v16.6.1):CSS/SCSS 代码质量工具
Stylelint 是 CSS/SCSS 代码的静态分析工具,用于检查代码中的错误和样式违规。 1. 环境要求 v16 以上的 Stylelint,支持 Node.js 的版本为 v18.12.0。 在命令行中输入以下内容来查看当前系统中 node 的版本。 node -vNode.js 推荐使用 v18.20.3 或者 …...

crossover mac好用吗 CrossOver Mac怎么下载 Mac用crossover损害电脑吗
CrossOver 是一款可以让Mac用户能够自由运行和游戏windows游戏软件的虚拟机类应用,虽然能够虚拟windows但是却并不是一款虚拟机,也不需要重启系统或者启动虚拟机,类似于一种能够让mac系统直接运行windows软件的插件。它以其出色的跨平台兼容性…...
PHP模块pdo_sqlite.so: undefined symbol: sqlite3_column_table_name
安装 php-sqlite3 之后,执行php -m 命令有警告,如下 PHP Warning: PHP Startup: Unable to load dynamic library pdo_sqlite (tried: /usr/lib64/php/modules/pdo_sqlite (/usr/lib64/php/modules/pdo_sqlite: cannot open shared object file: No su…...

卷积神经网络-奥特曼识别
数据集 四种奥特曼图片_数据集-飞桨AI Studio星河社区 (baidu.com) 中间的隐藏层 已经使用参数的空间 Conv2D卷积层 ReLU激活层 MaxPool2D最大池化层 AdaptiveAvgPool2D自适应的平均池化 Linear全链接层 Dropout放置过拟合,随机丢弃神经元 -----------------…...

VB.net进行CAD二次开发(四)
netload不能弹出对话框,参考文献2 参考文献1说明了自定义菜单的问题,用的是cad的系统命令 只要加载了dll,自定义的命令与cad的命令同等地位。 这时,可以将自定义菜单的系统命令替换为自定义命令。 <CommandMethod("Add…...

3步轻松月入过万,APP广告新模式大揭秘!
万万没想到:用这个APP广告模式,月入过万竟然如此简单! 在移动应用开发的世界里,变现一直是一道难题。 许多APP开发者和产品经理为了提高收益、增强用户黏性,不断尝试各种策略。 然而,很多时候,…...

java项目之智能家居系统源码(springboot+vue+mysql)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的智能家居系统。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 基于Springboot的智能家居系…...
前端 JS 经典:读取文件原始内容
前言:有些时候在工程化开发中,我们需要读取文件里面的原始内容,比如,你有一个文件,后缀名为 .myfile,你需要拿到这个文件里的内容,该怎么处理呢。 在 vue2 中,因为 vue2 使用 vue-c…...

汇编概论和实践
一 汇编第一例 C代码 #include <stdio.h>int main() {printf("Hello, World!\n");return 0; }对应的汇编 .LC0:.string "Hello, World!"main:pushq %rbpmovq %rsp, %rbpleaq .LC0(%rip), %rdicall puts@PLTmovl $0, %eaxpopq %rbpret 二 CPU架构…...

铁塔基站用能监控能效解决方案
截至2023年10月,我国5G基站总数达321.5万个,占全国通信基站总数的28.1%。然而,随着5G基站数量的快速增长,基站的能耗问题也逐渐日益凸显,基站的用电给运营商带来了巨大的电费开支压力,降低5G基站的能耗成为…...

keepalived安装文档
目录 1、安装环境 2、安装keepalived 2.1 上传keepalived安装文件 2.2 解压 2.3 安装keepalived 2.4 加入开机启动: 2.5 配置日志文件 2.6 打开防火墙的通讯地址 1、安装环境 su - root yum -y install kernel-devel* yum -y install openssl-* yum -y …...
Spring Security
Spring Security spring提供的安全框架。主要提供了认证和授权的功能。简单梳理看看。 原理简单说就是Spring Security在基于Servlet应用中,其底层采用了Filter机制实现了对请求的认证,授权和漏洞防御等功能。 DelegatingFilterProxy 我们知道,Filter是Servlet规范里面…...

vue中大屏可视化适配所有屏幕大小
1. 外部盒子 .screenBox {width: 100vw;height: 100vh;background: url("/assets/images/bg.png") no-repeat;background-size: cover; }2.比例盒子 外层盒子css定义 .boxScale {width: 1920px;height: 1080px;background-color: orange;transform-origin: left top;…...

AI大模型探索之路-实战篇12: 构建互动式Agent智能数据分析平台:实现多轮对话控制
系列篇章💥 AI大模型探索之路-实战篇4:深入DB-GPT数据应用开发框架调研 AI大模型探索之路-实战篇5:探索Open Interpreter开放代码解释器调研 AI大模型探索之路-实战篇6:掌握Function Calling的详细流程 AI大模型探索之路-实战篇7…...

深入理解文件系统和日志分析
文件是存储在硬盘上的,硬盘上的最小存储单位是扇区,每个扇区的大小是512字节。 inode:存储元信息(包括文件的属性,权限,创建者,创建日期等等) block:块,连续…...

vue+vant移动端显示table表格加横向滚动条
vant移动端显示table效果,增加复选框,可以进行多选和全选。加横向滚动条,可以看全部内容。 <template><div class"app-container"><div class"nav_text" style"position: relative;"><…...
webserver服务器从零搭建到上线(八)|EpollPoller事件分发器类
文章目录 EpollPoller事件分发器类成员变量和成员函数解释私有的成员函数和成员变量成员函数 具体实现常量的作用构造函数和析构函数⭐️poll函数updateChannel函数removeChannel 函数removeChannel 和updateChannel⭐️fillActiveChannels 函数⭐️update 函数 总结 终于要开始…...
SD-WAN:企业网络转型的必然趋势
随着SD-WAN技术的不断进步和完善,越来越多的企业选择利用SD-WAN进行网络转型。根据IDC的研究,47%的企业已经成功迁移到SD-WAN,另有48%的公司计划在未来两个月内部署这一技术。 据Channel Futures报道,一位合作伙伴透露,…...

构建高效稳定的短视频直播系统架构
随着短视频直播的迅猛发展,构建一个高效稳定的短视频直播系统架构成为了互联网企业的重要挑战。本文将探讨如何构建高效稳定的短视频直播系统架构,以提供优质的用户体验和满足日益增长的用户需求。 ### 1. 短视频直播系统的背景 短视频直播近年来蓬勃发…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
Golang dig框架与GraphQL的完美结合
将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用,可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器,能够帮助开发者更好地管理复杂的依赖关系,而 GraphQL 则是一种用于 API 的查询语言,能够提…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...

C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...