【C++】反向迭代器
文章目录
- 一、什么是反向迭代器
- 二、STL 源码中反向迭代器的实现
- 三、reverse_iterator 的模拟实现
- 四、vector 和 list 反向迭代器的实现
一、什么是反向迭代器
C++ 中一共有四种迭代器 – iterator、const_iterator、reverse_iterator 以及 const_reverse_iterator,其中正向迭代器我们已经很熟悉了,其实反向迭代器的使用和正向迭代器几乎一样,反向迭代器的特点如下:
- rbegin() 相当于 end();
- rend() 相当于 begin();
- 反向迭代器++相当于正向迭代器–;
- 其他操作比如 * != -> 和正向迭代器相同。
反向迭代器的使用:反向迭代器的使用和正向迭代器完全相同
void reverse_iterator_test() {vector<int> v;v.push_back(1);v.push_back(5);v.push_back(6);v.push_back(5);v.push_back(9);vector<int>::reverse_iterator rit = v.rbegin();while (rit != v.rend()) {(*rit) += 1;cout << *rit << " ";++rit;}cout << endl;
}
在以前 string、vector 和 list 中模拟实现中我们只实现了正向迭代器,而并没有去实现反向迭代器,今天我们就来探究如何实现反向迭代器。
二、STL 源码中反向迭代器的实现
我们可以通过参考 STL 源码中反向迭代器的实现方式来学习如何实现反向迭代器,如下:
//list.h部分源码 -- SGI版
template <class T, class Alloc = alloc>
class list {
public:typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T, const T&, const T*> const_iterator;#ifdef __STL_CLASS_PARTIAL_SPECIALIZATIONtypedef reverse_iterator<const_iterator> const_reverse_iterator;typedef reverse_iterator<iterator> reverse_iterator;
//vector.h部分源码 -- SGI版
template <class T, class Alloc = alloc>
class vector {
public:typedef T value_type;typedef value_type* iterator;typedef const value_type* const_iterator;#ifdef __STL_CLASS_PARTIAL_SPECIALIZATIONtypedef reverse_iterator<const_iterator> const_reverse_iterator;typedef reverse_iterator<iterator> reverse_iterator;
可以看到,STL 源码中 vector 和 list 的反向迭代器都是 reverse_iterator 类的 typedef,而 reverse_iterator 类位于源码中的 stl_iterator.h 中,其部分源码如下:
//stl_iterator.h -- SGI版
template <class Iterator>
class reverse_iterator {
protected:Iterator current;public:typedef Iterator iterator_type;typedef reverse_iterator<Iterator> self;public:reverse_iterator() {}explicit reverse_iterator(iterator_type x) : current(x) {}reverse_iterator(const self& x) : current(x.current) {}reference operator*() const {Iterator tmp = current;return *--tmp;}
#ifndef __SGI_STL_NO_ARROW_OPERATORpointer operator->() const { return &(operator*()); }
#endif /* __SGI_STL_NO_ARROW_OPERATOR */self& operator++() {--current;return *this;}self& operator--() {++current;return *this;}//...
}
如上,正向迭代器是 reverse_iterator 的模板参数,而反向迭代器是 reverse_iterator 的对象,所以反向迭代器是一个容器适配器,它的适配容器就是对应的正向迭代器,这样它就能根据传递过来的正向迭代器的不同实例化出对应的反向迭代器。
也就是说,只要实现了 reverse_iterator 类,以后不管是 vector、list、map 还是其他的容器,只要你将其对应的正向迭代器传递给我,我就能适配出对应的反向迭代器,做到泛型编程。
三、reverse_iterator 的模拟实现
模拟实现代码:iterator.h
#pragma oncenamespace thj {template<class Iterator, class Ref, class Ptr>class reverse_iterator {typedef reverse_iterator<Iterator, Ref, Ptr> self;public:reverse_iterator(Iterator it) //构造: _it(it){}self& operator++() { //++--_it;return *this;}self operator++(int) { //后置++ 返回值不加引用,因为tmp是局部变量Iterator tmp = _it;--_it;return tmp;}self& operator--() { //--++_it;return *this;}self operator--(int) { //后置-- 返回值不加引用Iterator tmp = _it;++_it;return tmp;}bool operator!=(const self& s) const { //不等于return _it != s._it;}Ref operator*() { //解引用,返回的是反向迭代器的前一个位置Iterator tmp = _it;return *(--tmp);}Ptr operator->() { //-> 返回节点数据的地址return &(operator*());}private:Iterator _it; //成员变量是正向迭代器};
}
模拟实现细节:
1、由于 rbegin() 等价于 end(),rend() 等价于 begin(),所以 ++reverse_iterator 等价于 --iteraor,–reverse_iterator 等价于 ++iterator;
2、在实现 operator*() 和 operator->() 时我们并不知道 T 的类型 (const 与非 const),所以我们不能确定函数的返回值;STL 源码中使用迭代器萃取的方法来解决这个问题,如下:
//stl_iterator.h部分源码
template <class Iterator>
class reverse_iterator
{// iterator_traits -- 迭代器萃取typedef typename iterator_traits<Iterator>::pointertypedef typename iterator_traits<Iterator>::reference reference;reference operator*() const {Iterator tmp = current;return *--tmp;}
#ifndef __SGI_STL_NO_ARROW_OPERATORpointer operator->() const { return &(operator*()); }
};
但是这种方式十分复杂,并且校招的时候并不会考察萃取相关的知识,所以这里我们参考 list 正向迭代器 的设计思路 – 增加两个模板参数分别作为 operator*() 和 operator->() 函数的返回值,如下:
//typedef reverse_iterator<Iterator, T&, T*> reverse_iterator 反向迭代器
//typedef const_reverse_iterator<Iterator, const T&, const T*> const_reverse_iterator const反向迭代器template<class Iterator, class Ref, class Ptr>
class reverse_iterator {typedef reverse_iterator<Iterator, Ref, Ptr> self;public:Ref operator*() { //解引用,特别注意:返回的是反向迭代器的前一个位置Iterator tmp = _it;return *(--tmp);}Ptr operator->() { //-> 返回节点数据的地址return &(operator*());}private:Iterator _it; //成员变量是正向迭代器
};
3、同时,由于 end 是指向最后一个元素的下一个位置,而 rbegin 由 end 适配得到,所以反向迭代器中 operator*() 不是返回迭代器当前位置的数据,而是返回迭代器前一个位置的数据,不然会发生越界访问。
四、vector 和 list 反向迭代器的实现
现在我们已经实现了 reverse_iterator 类,所以可以直接用 vector 和 list 的正向迭代器作为 reverse_iterator 的适配容器适配出它们的反向迭代器。
vector 反向迭代器
反向迭代器相关代码:
#include "iterator.h"
template<class T>class list{//反向迭代器typedef thj::reverse_iterator<iterator, T&, T*> reverse_iterator;typedef thj::reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;reverse_iterator rbegin() {return reverse_iterator(end());}reverse_iterator rend() {return reverse_iterator(begin());}const_reverse_iterator rbegin() const {return const_reverse_iterator(end());}const_reverse_iterator rend() const {return const_reverse_iterator(begin());}};
}
list.h:
#pragma once#include <assert.h>
#include <algorithm>
#include "iterator.h"namespace thj {template<class T>struct list_node{list_node<T>* _next;//不加<T>也没错,但是写上好一些list_node<T>* _prev;T _data;list_node(const T& x)//构造:_next(nullptr), _prev(nullptr), _data(x){}};//迭代器最终版//const 迭代器 -- 增加模板参数,解决 operator*() 返回值与 operator->() 返回值问题//typedef __list_iterator<T, T&, T*> iterator;//typedef __list_iterator<T, const T&, const T*> const_iterator;//STL源码中大佬的写法,利用多个模板参数来避免副本造成的代码冗余问题template<class T, class Ref, class Ptr>struct __list_iterator //迭代器类{typedef list_node<T> node; //重命名list节点typedef __list_iterator<T, Ref, Ptr> Self; //这里进行重命名是为了后续再添加模板参数时只用修改这一个地方node* _pnode; //节点指针作为类的唯一成员变量__list_iterator(node* p):_pnode(p){}Ref operator*() //解引用{return _pnode->_data;}Ptr operator->() //->{return &_pnode->_data;}Self& operator++() //前置++{_pnode = _pnode->_next;return *this;}Self& operator++(int) //后置++{Self it(*this);_pnode = _pnode->_next;return it;}Self& operator--() //前置--{_pnode = _pnode->_prev;return *this;}Self& operator--(int) //后置--{Self it(*this);_pnode = _pnode->_prev;return it;}bool operator!=(const Self& it) const //!={return _pnode != it._pnode;}bool operator==(const Self& it) const //=={return _pnode == it._pnode;}};//list 类template<class T>class list{typedef list_node<T> node;public:typedef __list_iterator<T, T&, T*> iterator; //迭代器typedef __list_iterator<T, const T&, const T*> const_iterator; //const 迭代器//反向迭代器typedef thj::reverse_iterator<iterator, T&, T*> reverse_iterator;typedef thj::reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;reverse_iterator rbegin() {return reverse_iterator(end());}reverse_iterator rend() {return reverse_iterator(begin());}const_reverse_iterator rbegin() const {return const_reverse_iterator(end());}const_reverse_iterator rend() const {return const_reverse_iterator(begin());}//迭代器iterator begin() {return iterator(_head->_next);}iterator end() {//iterator it(_head);//return it;//直接利用匿名对象更为便捷return iterator(_head);}const_iterator begin() const {return const_iterator(_head->_next);}const_iterator end() const {return const_iterator(_head);}void empty_initialize() { //初始化 -- 哨兵位头结点_head = new node(T());_head->_next = _head;_head->_prev = _head;_size = 0; //空间换时间,用于标记节点个数}list() { //构造,不是list<T>的原因:构造函数函数名和类名相同,而list<T>是类型empty_initialize();}//迭代器区间构造template <class InputIterator>list(InputIterator first, InputIterator last) {empty_initialize();while (first != last){push_back(*first);++first;//first++;}}// 拷贝构造的现代写法//list(const list& lt) 官方库是这样写的,这是由于在类内类名等价于类型,但不建议自己这样写list(const list<T>& lt) {empty_initialize(); //初始化头结点,防止交换后tmp野指针不能正常的调用析构list<T> tmp(lt.begin(), lt.end());swap(tmp);}//赋值重载现代写法//list& operator=(list lt)list<T>& operator=(list<T> lt) { //不能加引用,lt是调用拷贝构造生成的swap(lt);return *this;}~list() { //析构clear();delete _head;_head = nullptr;}void swap(list<T>& lt) { //交换两个链表,本质上是交换两个链表的头结点std::swap(_head, lt._head);std::swap(_size, lt._size);}size_t size() const { //增加一个计数的成员,以空间换时间return _size;}bool empty() { //判空return _size == 0;}void clear() {iterator it = begin();while (it != end()) {it = erase(it);}_size = 0;}void push_back(const T& x) {insert(end(), x); //复用}void push_front(const T& x) {insert(begin(), x); //复用}void pop_front() {erase(begin());}void pop_back() {erase(--end());}iterator insert(iterator pos, const T& x) {node* newnode = new node(x);node* cur = pos._pnode;node* prev = cur->_prev;prev->_next = newnode;newnode->_prev = prev;cur->_prev = newnode;newnode->_next = cur;++_size;return iterator(pos);}iterator erase(iterator pos) {assert(pos != end());node* prev = pos._pnode->_prev;node* next = pos._pnode->_next;prev->_next = next;next->_prev = prev;delete pos._pnode;--_size;return iterator(next);}private:node* _head;size_t _size;};
}
test.cpp:
void list_reverse_iterator_test() {thj::list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(5);thj::list<int>::reverse_iterator rit = lt.rbegin(); //反向迭代器while (rit != lt.rend()) {(*rit)++;cout << *rit << " ";++rit;}cout << endl;const thj::list<int> clt(lt.begin(), lt.end());thj::list<int>::const_reverse_iterator crit = clt.rbegin(); //const反向迭代器while (crit != clt.rend()) {//(*crit)++;cout << *crit << " ";++crit;}cout << endl;
}
vector 反向迭代器
反向迭代器相关代码:
namespace thj {template<class T>class vector {public://正向迭代器typedef T* iterator;typedef const T* const_iterator;//反向迭代器 -- 容器适配器typedef thj::reverse_iterator<iterator, T&, T*> reverse_iterator;typedef thj::reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;reverse_iterator rbegin() {return reverse_iterator(end());}reverse_iterator rend() {return reverse_iterator(begin());}const_reverse_iterator rbegin() const {return const_reverse_iterator(end());}const_reverse_iterator rend() const {return const_reverse_iterator(begin());}};
}
vector.h:
#pragma once
#include <iostream>
#include <assert.h>
#include <string.h>
#include <algorithm>
#include "iterator.h"namespace thj {template<class T>class vector {public://正向迭代器typedef T* iterator;typedef const T* const_iterator;iterator begin() {return _start;}iterator end() {return _finish;}const_iterator begin() const {return _start;}const_iterator end() const {return _finish;}//反向迭代器 -- 容器适配器//反向迭代器 -- 容器适配器typedef thj::reverse_iterator<iterator, T&, T*> reverse_iterator;typedef thj::reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;reverse_iterator rbegin() {return reverse_iterator(end());}reverse_iterator rend() {return reverse_iterator(begin());}const_reverse_iterator rbegin() const {return const_reverse_iterator(end());}const_reverse_iterator rend() const {return const_reverse_iterator(begin());}public://---------------------------constructor------------------------------////无参构造vector():_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){}//迭代器区间构造template<class InputIterator>vector(InputIterator first, InputIterator last):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){while (first != last){push_back(*first);++first;}}//n个val构造vector(size_t n, const T& val = T()):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){reserve(n);for (size_t i = 0; i < n; i++)push_back(val);}//n个val构造 -- 重载vector(int n, const T& val = T()):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){reserve(n);for (int i = 0; i < n; i++)push_back(val);}//拷贝构造 -- 现代写法vector(const vector<T>& v):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){vector<T> tmp(v.begin(), v.end()); //复用构造函数和swap函数swap(tmp);}//析构函数~vector() {delete[] _start;_start = _finish = _end_of_storage = nullptr;}//赋值重载vector<T>& operator=(vector<T> v) //复用拷贝构造,存在自我赋值的问题,但不影响程序正确性{swap(v);return *this;}//---------------------------------capacity------------------------------------//size_t size() const{return _finish - _start;}size_t capacity() const{return _end_of_storage - _start;}bool empty() const{return _start == _finish;}//扩容void reserve(size_t n){if (n > capacity()) //reserve 函数不缩容{T* tmp = new T[n];//memcpy(tmp, _start, sizeof(T) * size()); //error//memcpy有自定义类型的浅拷贝问题,需要对每个元素使用拷贝构造进行深拷贝for (int i = 0; i < size(); i++)tmp[i] = _start[i]; //拷贝构造size_t oldSize = _finish - _start; //记录原来的size,避免扩容不能确定_finishdelete[] _start;_start = tmp;_finish = _start + oldSize;_end_of_storage = _start + n;}}//扩容并初始化void resize(size_t n, T x = T()){if (n > capacity()) //resize 不缩容{reserve(n);}if (n > size()){while (_finish < _start + n){*_finish = x;++_finish;}}if (n < size()){_finish = _start + n;}}//------------------------------element access-------------------//T& operator[](size_t pos){assert(pos < size()); //检查越界return _start[pos];}const T& operator[](size_t pos) const{assert(pos < size());return _start[pos];}//----------------------------------modifys-----------------------------------////尾插void push_back(const T& n){if (size() == capacity()){size_t newCapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newCapacity);}*_finish = n;++_finish;}//尾删void pop_back(){assert(!empty());--_finish;}//任意位置插入iterator insert(iterator pos, const T& x){assert(pos >= _start);assert(pos <= _finish);//扩容导致 pos 迭代器失效if (size() == capacity()){size_t oldPos = pos - _start; //记录pos,避免扩容后pos变为野指针size_t newCapacity = capacity() == 0 ? 4 : capacity() * 2;reserve(newCapacity);pos = _start + oldPos; //扩容之后更新pos}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;return pos;}//任意位置删除 -- erase 之后也认为 pos 迭代器失效iterator erase(iterator pos){assert(pos >= _start);assert(pos < _finish);iterator begin = pos;while (begin < _finish - 1){*begin = *(begin + 1);++begin;}--_finish;return pos;}//交换两个对象void swap(vector<T>& v){std::swap(_start, v._start); //复用算法库的swap函数std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);}void clear(){_finish = _start;}private:T* _start;T* _finish;T* _end_of_storage;};
}
test.cpp:
void vector_reverse_iterator_test() {thj::vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);thj::vector<int>::reverse_iterator rit = v.rbegin();while (rit != v.rend()) {(*rit)++;cout << *rit << " ";++rit;}cout << endl;const thj::vector<int> cv(v.begin(), v.end());thj::vector<int>::const_reverse_iterator crit = cv.rbegin();while (crit != cv.rend()) {//(*crit)++;cout << *crit << " ";++crit;}cout << endl;
}
相关文章:
【C++】反向迭代器
文章目录一、什么是反向迭代器二、STL 源码中反向迭代器的实现三、reverse_iterator 的模拟实现四、vector 和 list 反向迭代器的实现一、什么是反向迭代器 C 中一共有四种迭代器 – iterator、const_iterator、reverse_iterator 以及 const_reverse_iterator,其中…...
(蓝桥真题)扫描游戏(计算几何+线段树二分)
题目链接:P8777 [蓝桥杯 2022 省 A] 扫描游戏 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 样例输入: 5 2 0 1 1 0 3 2 4 3 5 6 8 1 -51 -33 2 样例输出: 1 1 3 4 -1 分析:先考虑如何对物件进行排序,首先&…...
面试官:什么是双亲委派模型?如何打破它?
本文已经收录进 JavaGuide(「Java学习+面试指南」一份涵盖大部分 Java 程序员所需要掌握的核心知识。) 参加过校招面试的同学,应该对这个问题不陌生。一般提问 JVM 知识点的时候,就会顺带问你双亲委派模型(别扭的翻译。。。)。 就算是不准备面试,学习双亲委派模型对于我…...
自建服务器系列- DDNS配置
1、环境说明 光猫桥接路由器拔号的模式 2、DDNS是什么 对于DHCP方式获得的IP,无论对于局域网内来说,还是外网来说,都会有使得IP地址每隔一段时间变化一次,如果想要通过恒定不变的地址访问主机,就需要动态域名解析。…...
vue中使用axios简单封装用法,axios报错the request was rejected because no multipart boundar
在这里插入代码片## 创建实例 //这个写法作为我错误的记录,可以不看暂时 transformRequest: [(data: any) > {if (!data) {data {}}return qs.stringify(data)}]在我的项目里面,初始化配置里面进行handers的修改,例如:例如将…...
Leetcode.1220 统计元音字母序列的数目
题目链接 Leetcode.1220 统计元音字母序列的数目 Rating : 1730 题目描述 给你一个整数 n,请你帮忙统计一下我们可以按下述规则形成多少个长度为 n的字符串: 字符串中的每个字符都应当是小写元音字母(a, e, i, o, u)…...
深入元空间
元空间是干嘛的?元空间存储的是类的相关信息,就是类的运行时表达。包括:Class文件类的结构和方法常量注解代码优化JDK1.8分界在1.8版本之前,类的meta信息、类变量、字符串常量池都存储在永久代。1.8版本以后,类变量、实…...
前端技术和框架
一、各种技术概述 1.HTML 🧨HTML中文称为超文本标记语言,从语义上来说,它只是一种是一种标识性的语言,并不是一种编程语言。 <p>这是一段话</p>通过这个标签可以表示文本的一个段落。而且其中还有还有图片标签、视…...
02从零开始学Java之Java到底是个啥?
博主简介我是壹壹哥(孙玉昌),十年软件开发授课经验,CSDN博客专家、阿里云专家博主、掘金优秀创作者、infoQ专家博主;关注壹壹哥(孙玉昌),带你玩转Java,轻松实现从入门到放弃,哦不,到熟悉&#x…...
KEIL5中头文件路劲包含问题
方式1:1.Keil中添加头文件相对路劲的方法在c/c配置中添加路劲,最终是将添加的绝对路径转化为相对路径;注意:相对路径的当前位置指.uvproj文件所在位置在C/C配置中的include paths”中添加工程所用的所有头文件的路径;2…...
机智云目前我用过最便捷的物联网快速开发方案
GE211 MINI DTU上手来看,是一款尺寸比较小巧的模块,适合放置在几乎所有白色家电中,通过ph2.0端子(注意不要买错)引出了5v、gnd、tx、rx。可以说是非常方便了。下面正式开始我们的接入流程:首先注册一个机智…...
MySQL基础篇1
第1章 数据库介绍 1.1 数据库概述 什么是数据库? 数据库就是存储数据的仓库,其本质是一个文件系统,数据按照特定的格式将数据存储起来,用户可以对数据库中的数据进行增加,修改,删除及查询操作。 数据库分两…...
AQS 源码解读
一、AQS AQS 是 AbstractQueuedSynchronizer 的简称,又称为同步阻塞队列,是 Java 中的一个抽象类。在其内部维护了一个由双向链表实现的 FIFO 线程等待队列,同时又提供和维护了一个共享资源 state ,像我们平常使用的 ReentrantLo…...
使用 DataLoader 加载数据报错‘expected sequence of length 4 at dim 1 (got 0)’
使用 transformer 将字符串转为 id 序列,字符串为中英文混杂形式, 运行中出现报错:expected sequence of length 4 at dim 1 (got 0) 发现是在encoder_plus转换时,将输入的文本根据max_length截断了,导致[MASK]等字段…...
第十四届蓝桥杯第三期模拟赛B组C/C++原题与详解
文章目录 一、填空题 1、1 找最小全字母十六进制数 1、1、1 题目描述 1、1、2 题解关键思路与解答 1、2 给列命名 1、2、1 题目描述 1、2、2 题解关键思路与解答 1、3 日期相等 1、3、1 题目描述 1、3、2 题解关键思路与解答 1、4 乘积方案数 1、4、1 题目描述 1、4、2 题解关…...
致敬三八女神节,致敬IT女生
前言 三八女神节是一个特别的节日,它是为了纪念所有的女性,表达对她们的尊重和关爱。在这个特别的节日里,我们想要致敬所有在IT领域中奋斗的女生,她们用自己的智慧和努力为这个世界带来了无限的可能。 IT女神 从事IT行业的女生…...
【Go语言学习笔记】数据
目录字符串数组数组初始化指针复制切片基本操作resliceappendcopy字典deletemap是引用类型并发操作字符串 字符串是不可变字节(byte)序列,其本身是一个复合结构 type stringStruct struct{str unsafe.Pointerlen int }头部指针指向字节数组…...
puzzle(0919)六宫数局
目录 六宫数局 示例题目 简单模式 普通模式 困难模式 六宫数局 最强大脑同款项目。 找出一条给定起点和终点的路径,每一步的方向任选,在这个方向上移动的步数是当前数的质因数分解中2、3、5的次数。 示例题目 按照六边形坐标系来建立坐标系&#…...
脑机接口科普0016——独立BCI与非独立BCI
本文禁止转载!!!! 所谓的“独立BCI”与“非独立BCI”仅仅是BCI系统中的一个术语。本章主要是介绍一下这两个术语。 这两个术语是由Wolpaw在2002年提出来的。 独立BCI是指不依赖于中枢神经系统的的输出。 非独立BCI是指那种依赖…...
女神节告白代码
今天是女神节,送给所有女神们一句话: 爱自己是终生浪漫的开始,无论何时都要好好爱自己 目录 1. 请求动画帧填充 2.点类 3.粒子类 编辑 4.ParticlePool 池类 5.创建和填充 6.处理循环队列 7.更新活动粒子 8.移除非活性粒子 9.绘制有…...
【数据结构】单链表:头部操作我很行,插入也不用增容!!!
单链表 文章目录单链表1.链表1.1链表的概念和结构1.2链表的分类2.单链表的模拟实现2.1单链表的打印2.2单链表的尾插2.3单链表的头插2.4单链表的尾删2.5单链表的头删2.6单链表的查找2.7单链表的中间插入(在结点前插入)2.8单链表的中间删除(删除该结点)2.9单链表的中间插入(在结点…...
SpringBoot——使用WebSocket功能
springboot自带websocket,通过几个简单的注解就可以实现websocket的功能; 启动类跟普通的springboot一样: /*** 2023年3月2日下午4:16:57*/ package testspringboot.test7websocket;import org.springframework.boot.SpringApplication; im…...
博弈论小课堂:非零和博弈(实现双赢)【纳什均衡点】
文章目录 引言I 非零和博弈1.1 囚徒问题1.2 博弈中双方的收益矩阵II 在现实中找均衡点2.1 博弈通常不是一次性的,而是反复进行的2.2 博弈论讲的都是阳谋的策略2.3 人类还处于文明的初级阶段,人的道德水准不容高估2.4 乌合之众效应2.5 很多时候看似是双赢,其实是在更大范围内…...
数组中的逆序对
解题思路1: 看到这个题目,我们的第一反应是顺序扫描整个数组。每扫描到一个数组的时候,逐个比较该数字和它后面的数字的大小。如果后面的数字比它小,则这两个数字就组成了一个逆序对。假设数组中含有n个数字。由于每个数字都要和…...
C++基础了解-01-基础语法
基础语法 一、基础语法 C 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象,方法、即时变量。 对象 - 对象具有状态和行为。例如:一只狗的状态 - 颜色、名称、品种,行为 -…...
phpmyadmin 文件包含(CVE-2014-8959)
0x01 漏洞介绍 phpMyAdmin是phpMyAdmin团队开发的一套免费的、基于Web的MySQL数据库管理工具。该工具能够创建和删除数据库,创建、删除、修改数据库表,执行SQL脚本命令等。phpMyAdmin的GIS编辑器中libraries/gis/GIS_Factory.class.php脚本存在目录遍历漏洞。远程攻击者可借助…...
SpringBoot集成MyBatis
目录 实现步骤 1. 在项目的 pom.xml 配置文件中引入如下依赖 2. 在项目的 application.properties 配置文件中添加如下依赖 3. 新建 UserMapper.class 接口类,添加如下 3 个方法 4. 在 /resources/mybatis/mapper 路径(需要手动创建文件夹)下创建 UserMapper.xm…...
MySQL-索引
索引介绍索引是对数据库表中一列或者多列的值进行排序的一种结构,使用索引可提高数据库中特定数据的查询速度。索引是一个单独的、存储在磁盘上的数据库结构,它们包含着对数据表里所有记录的引用指针。使用索引用于快速找出在某个或多个列中有一特定值得…...
【STM32存储器映射-寄存器基地址-偏移】
前言 在学习STM32的时候,我们看到很多的寄存器编程, 比方说LED灯: //GPIOB.5端口输出高电平GPIOB->ODR|1<<5; //PB.5 输出高GPIOE->ODR|1<<5; //PE.5输出高 //GPIOB端口全部输出高电平*(unsigned int*)(0x4001 …...
【华为OD机试2023】最多颜色的车辆 C++ Java Python
【华为OD机试2023】最多颜色的车辆 C++ Java Python 前言 如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可以给您一些建议! 本文解法非最优解(即非性能最优),不能保证通过率。 Tips1:机试为ACM 模式 你的代码需要处理输入输出,input/cin接收…...
aso优化平台/google seo怎么做
5.1类 class Counter { private var value0 //你必须初始化字段 def increment() {value1} //方法默认是公有的 def current()value 在scala中,类并不声明为public。Scala源文件包含多个类,都是公有的 如何对…...
phpcms做网站/手机上如何制作自己的网站
Linux:SSH-实验报告 手写扫描300 dpi质量,足够看清文字图片上传超出限制,可直接下载附件!C8-SSH.rar [url]http://rapidshare.com/files/122533076/C8-SSH.rar.html[/url]转载于:https://blog.51cto.com/newbie/82155...
wordpress dom监听/网络广告宣传怎么做
原文链接:http://www.tmtpost.com/46740.html作者前言:本文的主旨是盘点和预测,对于业内人士来说,也就没有太多新的东西。笔者能力有限,无法将每个行业盘点得尽善尽美,尽管如此,还是觉得这篇文章…...
企业备案 网站服务内容/推广普通话的意义论文
在使用Exists时,如果能正确使用,有时会提高查询速度: 1,使用Exists代替inner join 2,使用Exists代替 in 1,使用Exists代替inner join例子: 在一般写sql语句时通常会遇到如下语句: 两个表连接时&…...
最近大事件新闻/抖音seo优化系统招商
使用前先new 一下 所有方法均返回 promise 对象 可使用then() 写后续业务 或 使用 async await 预览一下 体验一下 H5 地址 http://uni_upload.gek6.com/uploader/#/ 服务端返回示例 {"code":0,"msg":"上传成功","data":"http://…...
网站开发流程可规划为哪三个阶段/营销型网站建设论文
当用户将鼠标悬停在浏览器中的标签上时,Chrome浏览器会显示网页标题。虽然有时信息足够,但如果网站使用相似或相同的标题,就派不上任何用场了。在各大主流浏览器Firefox,Opera,甚至已被“放弃”的Edge中,都…...