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

set和map的封装

目录

介绍

红黑树代码 

set

insert的迭代器转换问题

为什么会有这样的问题?

如何解决

代码 

map

注意点

代码


介绍

set和map的底层都是红黑树,所以我们可以在自己实现的红黑树(简易版)的基础上,进行封装,成为简易的set和map

红黑树代码 

#pragma once#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <cassert>
#include <cstdlib>
#include <utility>// 有迭代器的红黑树
namespace my_RB_Tree
{enum colour{black,red};template <class T>struct RBTreeNode // 结点{RBTreeNode(const T& data): _left(nullptr),_right(nullptr),_parent(nullptr),_col(red),_data(data){}RBTreeNode* _left;RBTreeNode* _right;RBTreeNode* _parent;colour _col;T _data;};template <class T, class Ptr, class Ref> // T是元素类型,ptr是指针类型,ref是引用类型(后两种会有const类型)struct RBTreeIterator                    // 迭代器{typedef RBTreeNode<T> Node;typedef RBTreeIterator<T, Ptr, Ref> Self;//为了可以能让普通迭代器初始化const迭代器,需要来一个普通迭代器对象typedef RBTreeIterator<T, T*, T&> iterator;Node* _pNode;RBTreeIterator(Node* pNode): _pNode(pNode){}RBTreeIterator(const iterator& it) // const迭代器时,它是一个初始化;普通迭代器时,它是一个拷贝: _pNode(it._pNode){}// 让迭代器具有类似指针的行为Ref operator*(){return _pNode->_data;}Ptr operator->(){return &(_pNode->_data);}// 让迭代器可以移动:前置/后置++Self& operator++(){Increament();return *this;}Self operator++(int){Self tmp(*this);Increament();return tmp;}// 让迭代器可以移动:前置/后置--Self& operator--(){DeIncreament();return *this;}Self operator--(int){Self tmp(*this);DeIncreament();return tmp;}// 让迭代器可以比较bool operator!=(const Self& s) const{return _pNode != s._pNode;}bool operator==(const Self& s) const{return _pNode == s._pNode;}private:void Increament();void DeIncreament();};// 为了后序封装map和set,本代码的红黑树会有一个作为哨兵位的头结点template <class K, class T, class KeyOfT> // K是关键字的类型,T是元素类型(区分这两个的原因:会用该红黑树封装成set和map,而map是key_value的)// keyofT是返回关键字类型的值(否则map无法返回)class RBTree                              // 红黑树{public:typedef RBTreeNode<T> Node;typedef RBTreeIterator<T, T*, T&> iterator;typedef RBTreeIterator<T, const T*, const T&> const_iterator;public:RBTree(){_pHead = new Node(T());_pHead->_left = _pHead;_pHead->_parent = nullptr;_pHead->_right = _pHead;}// 在红黑树中插入值为data的节点,插入成功返回true,否则返回falsestd::pair<iterator, bool> Insert(const T& data);// 检测红黑树中是否存在值为data的节点,存在返回该节点的地址,否则返回nullptrNode* Find(const K& data);// 获取红黑树最左侧节点Node* LeftMost() const;// 获取红黑树最右侧节点Node* RightMost() const;iterator begin(){return iterator(LeftMost());}iterator end(){return iterator(_pHead);}const_iterator begin() const{return const_iterator(LeftMost());}const_iterator end() const{return const_iterator(_pHead);}// 检测红黑树是否为有效的红黑树,注意:其内部主要依靠_IsValidRBTRee函数检测bool IsValidRBTRee(){Node* root = _pHead->_parent;if (root->_col == red){return false;}int count = 0;find_blacknode(count, _pHead->_parent);return _IsValidRBTRee(_pHead->_parent, count, 0);}private:bool _IsValidRBTRee(Node* pRoot, size_t blackCount, size_t pathBlack);// 左单旋void RotateL(Node* pParent);// 右单旋void RotateR(Node* pParent);// 为了操作树简单起见:获取根节点Node*& GetRoot(){return _pHead->_parent;}void find_blacknode(int& count, Node* root){if (root == nullptr){return;}if (root->_col == black){++count;}find_blacknode(count, root->_left);find_blacknode(count, root->_right);}private:Node* _pHead = nullptr;};template <class K, class T, class KeyOfT>void RBTree<K, T, KeyOfT>::RotateL(Node* pParent){Node* cur = pParent->_right, * curleft = cur->_left;// 连接p和cur左树,因为该位置被p占据pParent->_right = curleft;if (curleft){curleft->_parent = pParent;}// 连接父结点if (pParent->_parent != _pHead){Node* ppnode = pParent->_parent;if (ppnode->_left == pParent){ppnode->_left = cur;}else{ppnode->_right = cur;}cur->_parent = ppnode;}else{_pHead->_parent = cur;cur->_parent = _pHead;}// 连接p和curpParent->_parent = cur;cur->_left = pParent;}template <class K, class T, class KeyOfT>void RBTree<K, T, KeyOfT>::RotateR(Node* pParent){Node* cur = pParent->_left, * curright = cur->_right;// 连接p和cur右树,因为该位置被p占据pParent->_left = curright;if (curright){curright->_parent = pParent;}// 连接父结点if (pParent->_parent != _pHead){Node* ppnode = pParent->_parent;if (ppnode->_left == pParent){ppnode->_left = cur;}else{ppnode->_right = cur;}cur->_parent = ppnode;}else{_pHead->_parent = cur;cur->_parent = _pHead;}// 连接p和curpParent->_parent = cur;cur->_right = pParent;}template <class K, class T, class KeyOfT>typename RBTree<K, T, KeyOfT>::Node* RBTree<K, T, KeyOfT>::LeftMost() const{Node* cur = _pHead->_parent;while (cur->_left){cur = cur->_left;}return cur;}template <class K, class T, class KeyOfT>typename RBTree<K, T, KeyOfT>::Node* RBTree<K, T, KeyOfT>::RightMost() const{Node* cur = _pHead->_parent;while (cur->_right){cur = cur->_right;}return cur;}template <class K, class T, class KeyOfT>typename RBTree<K, T, KeyOfT>::Node* RBTree<K, T, KeyOfT>::Find(const K& data) // 注意这里,{Node* cur = _pHead->_parent;KeyOfT kot;while (cur){if (data > kot(cur->_data)){cur = cur->_right;}else if (data < kot(cur->_data)){cur = cur->_left;}else{return cur;}}return nullptr;}template <class K, class T, class KeyOfT>std::pair<typename RBTree<K, T, KeyOfT>::iterator, bool> RBTree<K, T, KeyOfT>::Insert(const T& data) // 为了和map适配,要返回pair类型//(first是插入元素所在的迭代器,second是bool值,判断是否成功插入){KeyOfT kot;Node* newnode = nullptr;if (_pHead->_parent == nullptr){newnode = new Node(data);newnode->_col = black;_pHead->_parent = newnode;newnode->_parent = _pHead;return std::make_pair(iterator(newnode), true);}else{Node* cur = _pHead->_parent, * parent = cur;while (cur){if (kot(data) > kot(cur->_data)){parent = cur;cur = cur->_right;}else if (kot(data) < kot(cur->_data)){parent = cur;cur = cur->_left;}else{return std::make_pair((iterator)cur, false);}}newnode = new Node(data);cur = newnode;cur->_parent = parent;if (kot(parent->_data) > kot(cur->_data)){parent->_left = cur;}else{parent->_right = cur;}Node* grandfather = nullptr;while (parent != _pHead && parent->_col == red){grandfather = parent->_parent; // 因为父结点是红色,所以肯定有爷爷结点(注意红黑树规则:根结点必须是黑色)if (grandfather->_left == parent) // 确定父亲位置{Node* uncle = grandfather->_right; // 也就能确定叔叔位置if (uncle && uncle->_col == red){parent->_col = uncle->_col = black;grandfather->_col = red;}else // 如果uncle不存在/为黑,就需要旋转+变色了{// 需要先判断旋转类型(也就是判断 -- parent和cur的相对位置)if (parent->_left == cur){// 一条偏右的直线,需要右旋RotateR(grandfather);// 旋转完后parent成为根结点// 更改完结点指向后,就可以改颜色了(都是根结点为黑,另外两个为红)parent->_col = black;cur->_col = grandfather->_col = red; // 和cur一层}else{// 拐角在左边,也就是先左旋,再右旋RotateL(parent);RotateR(grandfather);// cur成为根结点// 改颜色cur->_col = black;parent->_col = grandfather->_col = red;}break;}}else // parent在grandfather的右树{Node* uncle = grandfather->_left;if (uncle && uncle->_col == red){parent->_col = uncle->_col = black;grandfather->_col = red;}else // 如果uncle不存在/为黑,就需要旋转+变色了{// 需要先判断旋转类型(也就是判断 -- parent和cur的相对位置)if (parent->_right == cur){// 一条偏左的直线,需要左旋RotateL(grandfather);parent->_col = black;cur->_col = grandfather->_col = red; // 和cur一层}else{// 拐角在右边,也就是先右旋,再左旋RotateR(parent);RotateL(grandfather);// 改颜色cur->_col = black;parent->_col = grandfather->_col = red;}break;}}cur = grandfather; // 注意,这里会改cur的指向,但返回值需要返回插入位置的迭代器,所以需要另外保存parent = cur->_parent;}(_pHead->_parent)->_col = black; // 根结点必须为黑(防止它在上面的循环中被修改)}_pHead->_left = LeftMost();_pHead->_right = RightMost();//std::cout << (_pHead->_left)->_data << " " << (_pHead->_right)->_data << std::endl;return std::make_pair(iterator(newnode), true);}template <class K, class T, class KeyOfT>bool RBTree<K, T, KeyOfT>::_IsValidRBTRee(Node* cur, size_t blackCount, size_t pathBlack){if (cur == nullptr){// 到空结点后,就说明一条路径已经走通了,可以用得到的黑色结点数与基准数对比,不一样就说明红黑树错误if (pathBlack != blackCount){return false;}else{return true;}}if (cur->_parent){Node* ppnode = cur->_parent;if (cur->_col == red && ppnode->_col == red){return false;}}if (cur->_col == black){++pathBlack;}return _IsValidRBTRee(cur->_left, blackCount, pathBlack) && _IsValidRBTRee(cur->_right, blackCount, pathBlack);}template <class T, class Ptr, class Ref>void RBTreeIterator<T, Ptr, Ref>::Increament(){Node* cur = _pNode, * parent = _pNode->_parent;if (cur->_right){// 找到右子树的最小结点Node* curright = cur->_right;while (curright->_left){curright = curright->_left;}_pNode = curright;}else{while (parent->_parent != cur && parent->_right == cur) // 找到cur是parent的左结点的位置,这样parent的位置就是下一个位置{cur = parent;parent = parent->_parent;}_pNode = parent;}}template <class T, class Ptr, class Ref>void RBTreeIterator<T, Ptr, Ref>::DeIncreament(){Node* cur = _pNode, * parent = _pNode->_parent;if (cur->_left){// 找到左子树的最大结点Node* curleft = cur->_left;while (curleft->_right){curleft = curleft->_right;}_pNode = curleft;}else{while (parent->_parent != cur && parent->_left == cur) // 找到cur是parent的左结点的位置,这样parent的位置就是下一个位置{cur = parent;parent = parent->_parent;}_pNode = parent;}}
}

set

set我们只实现它的插入和迭代器部分,大概可以看到效果就行

insert的迭代器转换问题

不考虑别的,因为insert返回的都是pair类型的,都是迭代器+布尔值,所以set直接调用红黑树的插入即可

但是,编译过不去!

大概就是说,普通迭代器无法转换为const迭代器

为什么会有这样的问题?

注意,set中,无论是普通迭代器还是const迭代器,其实都封装的是红黑树的const迭代器

stl源码中就是这么定义的:

  • 但是,tree的insert返回的是普通迭代器,而set的insert要返回的是const迭代器
  • 这就存在一个普通迭代器向const迭代器转换的过程

如何解决

所以我们需要在红黑树的迭代器类中增加这一功能

typedef RBTreeNode<T> Node;
typedef RBTreeIterator<T, Ptr, Ref> Self;
//为了可以能让普通迭代器初始化const迭代器,需要来一个普通迭代器对象
typedef RBTreeIterator<T, T*, T&> iterator;
Node* _pNode;RBTreeIterator(Node* pNode): _pNode(pNode)
{}
RBTreeIterator(const iterator& it) // const迭代器时,它是一个初始化;普通迭代器时,它是一个拷贝: _pNode(it._pNode)
{}

代码 

#include "RB_Tree.hpp"namespace my_set
{template <class K>class set{struct SetKeyOfT{const K& operator()(const K& key){return key;}};public:typedef typename my_RB_Tree::RBTree<K, K, SetKeyOfT>::const_iterator iterator;typedef typename my_RB_Tree::RBTree<K, K, SetKeyOfT>::const_iterator const_iterator;const_iterator begin() const{return _t.begin();}const_iterator end() const{return _t.end();}std::pair<iterator, bool> insert(const K& data) {//return _t.Insert(data);//这里在构建时,set的insert调用tree的insert//而tree中insert的返回值,返回的pair中,第一个成员是tree的普通迭代器//然后回到该函数,该函数返回的pair的第一个成员是set中的普通迭代器(实质上是tree中的const迭代器)//所以我们本质上是用不同类型的pair在赋值//所以要先转换std::pair<typename my_RB_Tree::RBTree<K, K, SetKeyOfT>::iterator, bool> ret = _t.Insert(data); //这里是tree的普通迭代器iterator it(ret.first);return std::pair<iterator, bool>(it,ret.second); //这里是要用普通迭代器初始化一个const迭代器,所以需要在tree迭代器中增加这个功能}private:my_RB_Tree::RBTree<K, K, SetKeyOfT> _t;};
}

map

注意点

map的重点就在insert和[ ]的重载上

也没啥别的了,就需要自己先构建一个pair类型,其他的就注意返回值和接收值到底是谁

K:key值类型    V:value类型     T:map的元素类型

代码

#include "RB_Tree.hpp"namespace my_map
{template <class K, class V>class map{public:typedef std::pair<const K, V> T; // map中key不能变,value可以变struct MapKeyOfT{const V &operator()(const T &data){return data.second;}};typedef typename my_RB_Tree::RBTree<K, T, MapKeyOfT>::iterator iterator;typedef typename my_RB_Tree::RBTree<K, T, MapKeyOfT>::const_iterator const_iterator;iterator begin(){return _t.begin();}iterator end(){return _t.end();}const_iterator begin() const{return _t.begin();}const_iterator end() const{return _t.end();}std::pair<iterator, bool> insert(const T &data){return _t.Insert(data);}V &operator[](const K &data){auto ret = insert(std::make_pair(data,V()));return (ret.first)->second;}private:my_RB_Tree::RBTree<K, T, MapKeyOfT> _t;};
}

相关文章:

set和map的封装

目录 介绍 红黑树代码 set insert的迭代器转换问题 为什么会有这样的问题? 如何解决 代码 map 注意点 代码 介绍 set和map的底层都是红黑树,所以我们可以在自己实现的红黑树(简易版)的基础上,进行封装,成为简易的set和map 红黑树代码 #pragma once#include <…...

java基础练习--基础语法

预备知识:Java基本语法、分支、循环、数组和字符串 7-1 累加器 请你实现一个累加器。输入n个非负整数&#xff0c;输出他们的和。 1<n<1000&#xff0c;而每个数则<10000。 输入格式: 输入包括两行。 第一行:包括一个整数n&#xff0c;表示总共有n个数。 第二行:包…...

Android12 OTA编译差分包报错问题

前言 在Ubuntu 20.04.4 LTS系统中编译Android12 OTA差分包的时候提示如下报错log: Warning: releasetools script should be invoked as hermetic Python executable -- build and run ota_from_target_files directly. Traceback (most recent call last):File "./bu…...

现代c++手撸2309神经网络最简化版230901

用c++输入数据:vector<vector<float>> inputs = { {1, 1}, {1, 0} };数据targets={0,1}; 测试:vector<vector<float>> inputs22 = { {1, 0}, {1,1} }; 构建神经网络,例如:NeuralNetwork nn({ 2, 4, 1 }); 则网络有四层、输入层2个节点、输出层1个节…...

Qt之显示PDF文件

之前使用过mupdf库&#xff0c;能够成功显示pdf&#xff0c;但是我用着有BUG&#xff0c;不太理解它的代码&#xff0c;搞了好久都不行。后面又试了其他库&#xff0c;如pdfium、popler、下载了很多例程&#xff0c;都跑不起来&#xff01;后面偶然得知xpdf库&#xff0c;看起来…...

[极客大挑战 2019]FinalSQL - 异或盲注

1、这题的关键是找注入点&#xff0c;如果选择用户名、密码作为输入点就麻烦了 2、注入点&#xff1a;按钮&#xff0c;点击就传id&#xff1b;当id1时&#xff0c;提示Click others   可以利用id的特性&#xff0c;构造异或匹配   payload: f"1^(ord(substr((select…...

【Go语言实战】(25) 分布式算法 MapReduce

MapReduce 写在前面 身为大数据专业的学生&#xff0c;其实大学我也多多少少接触过mapreduce&#xff0c;但是当时觉得这玩意太老了&#xff0c;觉得这和php一样会被时代淘汰。只能说当时确实太年轻了&#xff0c;没有好好珍惜那时候的学习资源… 现在回过头来看mapreduce&a…...

【网络安全-信息收集】网络安全之信息收集和信息收集工具讲解(提供工具)

工具下载百度网盘链接(包含所有用到的工具&#xff09;&#xff1a; 百度网盘 请输入提取码百度网盘为您提供文件的网络备份、同步和分享服务。空间大、速度快、安全稳固&#xff0c;支持教育网加速&#xff0c;支持手机端。注册使用百度网盘即可享受免费存储空间https://pan.…...

战火使命ssr排名,战火使命角色强度排行

在战火使命中&#xff0c;很多玩家都在关注SSR角色的强度排行&#xff0c;那么&#xff0c;下面就为大家分享一下小编整理的最新战火使命ssr排名&#xff0c;一起来看看吧。 关注【娱乐天梯】&#xff0c;获取内部福利号 一、SSR角色排名榜&#xff1a; 1. 克拉拉、艾蕾娜、杰西…...

CSS之linear-gradient( ) 函数—背景颜色渐变设计

目录 linear-gradient( ) 函数 简介&#xff1a; 语法&#xff1a; 详解&#xff1a; 例如&#xff1a; linear-gradient( ) 函数 简介&#xff1a; linear-gradient 函数是 CSS 中用于创建线性渐变的函数。它接受一个或多个参数&#xff0c;并使用这些参数创建一个渐变。…...

[Unity]未能加载一个或多个断点问题

【背景】 大家2023国庆快乐&#xff0c;虽然是假期&#xff0c;我还是继续码些文章。 今天写项目时遇到个环境问题&#xff0c;新建脚本时双击调起VS编辑器&#xff0c;忽然提示无法加载一个或多个断点&#xff08;当时忘记截图了&#xff0c;现在已解决&#xff0c;就不上图了…...

Qt中的基础数据类型

1.基础类型 因为Qt是一个C++ 框架, 因此C++中所有的语法和数据类型在Qt中都是被支持的, 但是Qt中也定义了一些属于自己的数据类型, 下边给大家介绍一下这些基础的数类型 QT基本数据类型定义在#include <QtGlobal> 中,QT基本数据类型有: 类型名称注释备注qint8signed ch…...

2023阿里云域名优惠口令大全

2023年阿里云域名优惠口令&#xff0c;com域名续费优惠口令“com批量注册更享优惠”&#xff0c;cn域名续费优惠口令“cn注册多个价格更优”&#xff0c;cn域名注册优惠口令“互联网上的中国标识”&#xff0c;阿里云优惠口令是域名专属的优惠码&#xff0c;可用于域名注册、续…...

湖南软件测评公司简析:软件功能测试和非功能测试的联系和区别

一、软件功能测试   软件功能测试旨在验证软件是否按照需求规格说明书的要求正常工作。具体而言&#xff0c;功能测试会对软件的所有功能进行测试&#xff0c;以确保其满足用户的需求和预期。在进行功能测试时&#xff0c;根据需求规格说明书编写测试用例&#xff0c;并在测试…...

HuggingFace Transformers教程(1)--使用AutoClass加载预训练实例

知识的搬运工又来啦 ☆*: .&#xff61;. o(≧▽≦)o .&#xff61;.:*☆ 【传送门>原文链接:】https://huggingface.co/docs/transformers/autoclass_tutorial &#x1f697;&#x1f693;&#x1f695;&#x1f6fa;&#x1f699;&#x1f6fb;&#x1f68c;&#x1f6…...

Qt获取当前所用的Qt版本、编译器、位数等信息

//详细的Qt版本编译器位数 QString compilerString "<unknown>"; { #if defined(Q_CC_CLANG)QString isAppleString; #if defined(__apple_build_version__)isAppleString QLatin1String(" (Apple)"); #endifcompilerString QLatin1String("…...

《C和指针》笔记31:多维数组的数组名、指向多维数组的指针、作为函数参数的多维数组

文章目录 1. 指向多维数组的数组名2. 指向多维数组的指针3. 作为函数参数的多维数组 1. 指向多维数组的数组名 我们知道一维数组名的值是一个指针常量&#xff0c;它的类型是“指向元素类型的指针”&#xff0c;它指向数组的第1个元素。那么多维数组的数组名代表什么呢&#x…...

【伪彩色图像处理】将灰度图像转换为彩色图像研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

Go Gin Gorm Casbin权限管理实现 - 2. 使用Gorm存储Casbin权限配置以及`增删改查`

文章目录 0. 背景1. 准备工作2. 权限配置以及增删改查2.1 策略和组使用规范2.2 用户以及组关系的增删改查2.2.1 获取所有用户以及关联的角色2.2.2 角色组中添加用户2.2.3 角色组中删除用户 2.3 角色组权限的增删改查2.3.1 获取所有角色组权限2.3.2 创建角色组权限2.3.3 修改角色…...

DNDC模型的温室气体排放分析

DNDC&#xff08;Denitrification-Decomposition&#xff0c;反硝化-分解模型&#xff09;是目前国际上最为成功的模拟生物地球化学循环的模型之一&#xff0c;自开发以来&#xff0c;经过不断完善和改进&#xff0c;从模拟简单的农田生态系统发展成为可以模拟几乎所有陆地生态…...

vue、全局前置守卫

需求&#xff1a;在使用商城app的时候&#xff0c;游客&#xff08;没有登录的用户&#xff09;可以看到商品信息&#xff0c;当游客点击添加购物车的时候&#xff0c;我们需要把游客“拦”到登录页面&#xff0c;登陆后&#xff0c;才可以添加商品。 游客只可以看得到部分页面…...

OpenWRT、Yocto 、Buildroot和Ubuntu有什么区别

OpenWRT&#xff1a; 用途&#xff1a;OpenWRT 是一个专注于路由器和嵌入式网络设备的Linux发行版。它提供了一个优化的Linux环境&#xff0c;旨在将网络设备变成功能丰富、高度可定制的路由器。 包管理器&#xff1a;OpenWRT 使用 opkg 包管理器&#xff0c;它是一个轻量级的…...

数据挖掘(3)特征化

从数据分析角度&#xff0c;DM分为两类&#xff0c;描述式数据挖掘&#xff0c;预测式数据挖掘。描述式数据挖掘是以简介概要的方式描述数据&#xff0c;并提供数据的一般性质。预测式数据挖掘分析数据建立模型并试图预测新数据集的行为。 DM的分类&#xff1a; 描述式DM&#…...

【RabbitMQ 实战】08 集群原理剖析

上一节&#xff0c;我们用docker-compose搭建了一个RabbitMQ集群&#xff0c;这一节我们来分析一下集群的原理 一、基础概念 1.1 元数据 前面我们有介绍到 RabbitMQ 内部有各种基础构件&#xff0c;包括队列、交换器、绑定、虚拟主机等&#xff0c;他们组成了 AMQP 协议消息…...

2023年 2月3月 工作经历

2月 #pragma make_public(type) 托管C导出传统C类&#xff0c;另一个托管C项目使用不了。传统C类make_public后&#xff0c;就可以使用了。对模板类无效&#xff0c;比如&#xff1a;std::string。 C#线程绑定CPU 我的方案&#xff1a; 假定我们想把 CPU0 设置成专有CPU。 定…...

selenium京东商城爬取

该项目主要参考与:http://c.biancheng.net/python_spider/selenium-case.html 你看完上述项目内容之后&#xff0c;会发现京东登录是一个比较坑的点&#xff0c;selenium控制浏览器没有登录京东,导致我们自动爬取网页被重定向到京东登录注册页面。 因此&#xff0c;我们要单独…...

用pandas处理数据时,使变量能够在不同的Notebook会话页面进行传递,魔法命令%store

【需求来源】 在使用pandas时&#xff0c;有的时候我想将.ipynb文件分开写 其中一个写清洗数据代码另外一个写数据可视化代码 【解决方案】 但是会涉及到变量转移问题&#xff0c;这个时候我通常使用的方法是&#xff1a; 1、在清洗完数据后导出到本地 2、在文件后面增加当…...

选择适合户外篷房企业的企业云盘解决方案

“户外篷房企业用什么企业云盘好&#xff1f;Zoho WorkDrive企业网盘可以帮助户外篷房企业实现文档统一管理、提高工作效率、加强团队协作&#xff0c;并且支持各种文件类型的预览和编辑。” S公司是一家注重管理规范的大型户外篷房企业&#xff0c;已经有10余年的经验。作为设…...

松鼠搜索算法(SSA)(含MATLAB代码)

先做一个声明&#xff1a;文章是由我的个人公众号中的推送直接复制粘贴而来&#xff0c;因此对智能优化算法感兴趣的朋友&#xff0c;可关注我的个人公众号&#xff1a;启发式算法讨论。我会不定期在公众号里分享不同的智能优化算法&#xff0c;经典的&#xff0c;或者是近几年…...

折半+dp之限制转状态+状压:CF1767E

https://vjudge.net/problem/CodeForces-1767E/origin 首先40&#xff0c;必然折半。然后怎么做&#xff1f; 分析性质。每次可以走1步or2步&#xff0c;等价什么&#xff1f;等价任意相邻2个必选一个&#xff01;然后就可以建图 这个图是个限制图&#xff0c;我们折半后可以…...

让搜索引擎收录网站/友情链接交换源码

当我们面对vue-cli 复杂的代码&#xff0c;当我们看到各种配置文件的时候&#xff0c;你是否会为此感到头疼&#xff0c;是否会觉得心累&#xff1f;今天&#xff0c;大家可以跟着我一起&#xff0c;自己来是用webpack 构建一个基于vue单页面的应用&#xff0c;废话不多&#x…...

专做影视评论的网站/黄页大全

前言 只有光头才能变强今天继续来学习Redis&#xff0c;上一篇从零单排学Redis【青铜】已经将Redis常用的数据结构过了一遍了。如果还没看的同学可以先去看一遍再回来~ 这篇主要讲的内容有&#xff1a; Redis服务器的数据库Redis对过期键的处理Redis持久化策略(RDB和AOF)本文力…...

网站建设到运营赚钱/信息流优化师简历

这里主要是在文本框中添加新的投票标题的名称然后点击“添加新项”时&#xff0c;在投票标题栏显示新增加的标题&#xff0c;并在数据库中添加新数据。通过操作数据库SQL语言INSERT INTO来添加新的项目到数据库表中。<?php if(isset($_POST["Submit2"])){$newite…...

海南省住房和城乡建设局网站/中国第一营销网

两个字符串可以经过修改&#xff0c;增加&#xff0c; 删除一个字符作为一个操作&#xff0c;经过n步操作&#xff0c;两个字符串变为一样的&#xff0c; 相似度就为n&#xff0c;求n。 1 #include <iostream>2 #include <cstring>3 4 using namespace std;5 6 cha…...

大气精美网站设计工作室织梦模板(附赠精美织梦后台模板)/重庆关键词搜索排名

2019独角兽企业重金招聘Python工程师标准>>> SQL> --等值连接 SQL> --查询员工信息&#xff1a;员工号 姓名 月薪 部门名称 SQL> set linesize 80 SQL> desc dept 名称 是否为空? 类型 ---------------------…...

请别人做网站注意事项/百度有几种推广方式

ECMAScript 6.0是JavaScript语言的2015年6月的发布版。 一.let和const命令 let:用来声明变量&#xff0c;用法类似于var&#xff0c;但是只在let命令所在的代码块内有效。 var a []; for (let i 0; i < 10; i) {a[i] function () {console.log(i);}; } a[6](); // 6 cons…...