【C++之容器篇】二叉搜索树的理论与使用
目录
- 前言
- 一、二叉搜索树的概念
- 二、二叉搜素树的模拟实现(增删查非递归实现)
- 1. 二叉搜素树的结点
- 2. 二叉搜索树的实现
- (1). 二叉搜索树的基本结构
- (2)构造函数
- (3)查找函数
- (4)插入函数
- (5) 删除函数
- (6)中序遍历
- (7)析构函数
- (8)拷贝构造函数
- (9)赋值运算符重载(现代写法)
- 三、二叉搜索树的模拟实现(增删查递归实现)
- 1. 查找函数
- 2. 插入函数
- 3. 删除函数
前言
在数据结构初阶我们学习了二叉树的相关知识,普通的二叉树的作用只是用来存储数据,并没有任何的性质,所以在任何方面都没有什么优势,今天学习的二叉搜索树是在普通的二叉树的基础上加上了一些性质,使整体的搜索效率大大提升。
一、二叉搜索树的概念
二叉搜索树可能是一棵空树,也可能是一棵具有以下性质的二叉树:
- 如果左子树存在,则左子树所有结点的值都比根节点的值小
- 如果右子树存在,则右子树所有结点的值都比根节点的值大
- 树是递归创建的,所以二叉搜索树中的每一棵子树都要满足以上性质
二、二叉搜素树的模拟实现(增删查非递归实现)
1. 二叉搜素树的结点
// 二叉搜索树的结点
template <class K>
struct BSTreeNode
{// 成员函数//成员变量BSTreeNode<K>* _left;// 指向左孩子的指针(指针域)BSTreeNode<K>* _right;// 指向右孩子的指针(指针域)K _key;// 存储数据的地方(数据域)
};
二叉搜索树的结点中需要包含三个内容:
- _left:指向左孩子的结点的指针,通过这个指针找到左孩子,如果这个指针为空指针,说明当前这棵树不存在左子树
- _right:指向右孩子的结点的指针,通过这个指针找到右孩子,如果这个指针为空指针,说明当前这棵树不存在右子树
- _key:数据域,存放结点的数据的,一般也称为是二叉搜索树的关键字,二叉搜索树的性质就是以这个关键字为准的
2. 二叉搜索树的实现
(1). 二叉搜索树的基本结构
// 二叉搜素树的基本结构
template <class K>
class BSTree
{// 需要使用结点类型typedef BSTreeNode<T> Node;public:// 成员函数private:// 成员变量Node* _root = nullptr;
};
二叉搜索树的底层本质上就是一个根节点,然后通过这个根节点无限去创建其左右子树,在树中需要使用树的结点类型,所以为了方便表示,可以在树中对树的结点类型进行重定义(这个技巧在list的实现中也用到过)。刚开始_root的值默认为nullptr。
(2)构造函数
树不需要实现构造函数,只需要给_root一个缺省值即可。
(3)查找函数
// 查找函数bool find(const K& key){Node* cur = _root;while (cur){if (key < cur->_key){cur = cur->_key;}else if(key>cur->_key){cur = cur->_right;}else{// 找到了return true;}}// 找不到return false;}
上面这个代码中是不需要单独判断树为空树的情况的,因为当树为空树的时候,那么_root = nullptr,此时cur = nullptr,所以循环压根不会进去,直接返回false。
(4)插入函数
// 插入函数bool insert(const K& key){if (_root == nullptr){// 空树_root = new Node(key);return true;}// 非空树// 找到插入的地方Node* cur = _root;// 找插入的位置Node* parent = nullptr;// 记录cur的父亲while (cur){if (key < cur->_key){// 左子树找parent = cur;cur = cur->_left;}else if (key > cur->_key){// 右子树找parent = cur;cur = cur->_right;}else{// 找到相等的值,不允许插入return false;}}// 当cur为空的时候,跳出循环,找到插入的位置cur = new Node(key);if (key < parent->_key){// 插在左子树parent->_left = cur;}else{parent->_right = cur;}return true;}
思路:
主题判断空树的情况,如果是空树,将结点直接插入在根,其他情况:先找到插入的位置,使用一个cur结点指针去标识找插入的位置,parent结点指针去记录cur的父亲结点,所以在cur找到了插入的位置之后,那么parent就是插入位置的父亲,查找的过程中,如果key的值比cur的值小,那么就是插入在左子树,如果key的值比cur的值大,那么就是插入在右子树,如果出现key的值和cur的值是相等的,则说明树中存在该值,不允许插入。最终当cur走到空的时候,则找到插入的位置,此时需要判断cur应该插入在parent的左边还是右边,可以通过插入的值和parent的值进行对比,如果插入的值比parent的值小,则插入在左子树,否则插入在右边。
- 测试查找和插入函数
代码:
void test_BSTree1()
{BSTree<int> t;t.insert(1);t.insert(3);t.insert(2);t.insert(6);t.insert(5);t.insert(9);// 查找cout << "1:" << t.find(1) << endl;cout << "2:" << t.find(2) << endl;cout << "3:" << t.find(3) << endl;cout << "4:" << t.find(4) << endl;cout << "5:" << t.find(5) << endl;cout << "6:" << t.find(6) << endl;}
运行结果:
(5) 删除函数
// 删除函数bool erase(const K& key){Node* cur = _root;Node* parent = nullptr;while (cur){// 找删除的值if (key < cur->_key){// 左子树找parent = cur;cur = cur->_left;}else if (key > cur->_key){// 右子树找parent = cur;cur = cur->_right;}else{// 找到了// 分类讨论// 1. 左孩子空:包含叶子节点// 2. 右孩子为空:不包含叶子节点// 3. 左右孩子都不为空if (cur->_left == nullptr){// 左子树为空,右子树不一定为空if (cur == _root){// cur就是根结点_root = cur->_right;}else{// cur不是根,cur的父亲结点是parentif (cur == parent->_left){parent->_left = cur->_right;}else{parent->_right = cur->_right;}}delete cur;}else if (cur->_right == nullptr){// 右子树为空,左子树一定不为空if (cur == _root){// cur是根节点_root = cur->_left;}else{// cur不是根节点,cur的父亲就是parentif (cur == parent->_left){parent->_left = cur->_left;}else{parent->_right = cur->_left;}}delete cur;}else{// 左子树和右子树都不为空// 找到删除结点所在树的右子树中的最小值Node* minRight = cur->_right;Node* minparent = cur;while (minRight->_left){minparent = minRight;minRight = minRight->_left;}swap(cur->_key, minRight->_key);if (minparent->_left == minRight){minparent->_left = minRight->_right;}else{minparent->_right = minRight->_right;}delete minRight;}return true;}}// cur走到空,说明树中不存在这个值,所以删除是被==失败return false;}
思路: 找到删除的值的结点,如果找不到,则删除失败,空树也是属于找不到的一种情况,如果找到了,需要对删除的结点进行分类讨论:
- 左孩子为空:不存在左子树,右子树是否存在不一定,可能存在也可能不存在,当右子树不存在的时候,此时该结点的左右子树均不存在,属于叶子结点
- 右孩子为空:此时左孩子一定不为空,因为左孩子为空的情况属于上面的请情况,所以这种情况的结点只存在右子树
- 左右孩子均不为空:同时存在左右子树的结点,需要采取替换法,然后转化为第一或者第二种情况进行删除。
细节:
- 在第一种情况和第二种情况中,删除的可能是根节点,当根节点没有左子树的时候,就属于第一种情况,当根节点没有右子树的时候,就属于第二种情况,如果删除的是根节点,该结点左子树为空时,则需要更新根节点到删除结点的右子树,该结点的右子树为空的时候,需要更新根节点到该节点的左子树。
- 第三种情况采取替换法,先找到删除的结点的左子树的最大值结点或者右子树的最小值结点,找这两种结点的原因是这个结点和删除的结点交换后可以保证该值比左子树的所有结点值都大,比右子树所有结点值都小。迭代的过程中一定要记录minRight的父亲,最终才能让该父亲去托管minRight的右子树,这个minparent一定是从删除的结点开始,因为minRight可能就是删除结点的右子树的根节点,这种情况就是删除结点的右子树的根节点没有左孩子的,此时循环是不会进去的,这种情况的minRight就是删除结点的右子树的根节点,那么其父亲就是删除的结点,所以在交换删除结点的值和minRight的值之后,问题就转化为删除minRight,此时minRight的左子树一定是空的,所以就算删除情况的第一种情况。
(6)中序遍历
// 中序遍历void InOrder(){// 因为在类外的对象不方便使用根节点,所以需要套一层进行递归_InOrder(_root);cout << endl;}// 中序遍历的子函数void _InOrder(Node* root){if (root == nullptr){return;}// 先遍历左子树_InOrder(root->_left);// 再访问根节点cout << root->_key << " ";// 最后遍历右子树_InOrder(root->_right);}
思路:在我们之前学习的二叉树的中序遍历中是直接进行递归的,因为C语言实现的二叉树并不是封装的,也就是对象可以直接访问树中的任何成员,但是C++不同,C++采用类对象进行封装的结构,类外的对象是不能访问类中的私有成员的,所以在类外不能访问到树的根节点,所以我们采取的方法就算套一层进行递归。递归的思路和之前一样:中序遍历就算先递归左子树,再访问根节点的值,再递归右子树。
(7)析构函数
二叉树中的结点都需要析构函数进行释放,所以析构函数需要我们自己实现,编译器形成析构函数无法完成这项工作。析构函数的实现思想同样采用递归的思路,而且采用的是后序递归,就是先将树的左子树递归,再递归右子树,最后将根节点释放。还有代码中的析构函数是public的,DestroyTree函数是私有的,析构函数是要给类外的对象进行使用的
public:
// 析构函数~BSTree(){DestroyTree(_root);}private:
void DestroyTree(Node* root){if (root == nullptr){// 空树return;}// 通过后序递归的方法将树中的每一个结点释放DestroyTree(root->_left);DestroyTree(root->_right);delete root;}
(8)拷贝构造函数
编译器默认生成的拷贝构造函数完成浅拷贝,如果采用拷贝,会导致两棵树中的根节点指针指向同一个根节点,也就是最终的两棵树是同一棵树,但是有两个对象,所以最终两个对象在生命周期到的时候都会调用析构函数清理资源,所以会出现同一棵树被清理两次,从而使程序崩溃。
void test_BSTree4()
{int a[] = { 2,3,7,1,5,9 };BSTree<int> t;for (auto& e : a){t.insert(e);}t.InOrder();cout << endl;BSTree<int> t1 = t;t1.InOrder();
}
运行结果:
- 深拷贝
代码:
// 拷贝构造函数
public:BSTree(const BSTree<K>& t){_root = copyTree(t._root);}private:
// copy函数Node* copyTree(const Node* root){if (root == nullptr){return nullptr;}Node* newnode = new Node(root->_key);newnode->_left = copyTree(root->_left);newnode->_right = copyTree(root->_right);return newnode;}
// 测试代码:
void test_BSTree4()
{int a[] = { 2,3,7,1,5,9 };BSTree<int> t;for (auto& e : a){t.insert(e);}t.InOrder();cout << endl;BSTree<int> t1 = t;// 调用拷贝构造函数t1.InOrder();
}
运行结果:
(9)赋值运算符重载(现代写法)
// 赋值运算符重载BSTree<K>& operator=(BSTree<K> t){swap(_root, t._root);return *this;}void test_BSTree5()
{int a[] = { 2,3,7,1,5,9 };BSTree<int> t;for (auto& e : a){t.insert(e);}t.InOrder();cout << endl;BSTree<int> t1;t1 = t;// 调用赋值运算符重载t1.InOrder();
}
运行结果:
三、二叉搜索树的模拟实现(增删查递归实现)
1. 查找函数
public:// 递归版本bool FindR(const K& key){return _FindR(_root,key);}
private:// 查找函数的子函数(递归版本)bool _FindR(Node* root,const K& key){if (root == nullptr){// 空树return false;}// 非空树if (key < root->_key){// 左子树找return _FindR(root->_left, key);}else if (key > root->_key){// 右子树找return _FindR(root->_right, key);}else{// 找到了return true;}}
//测试代码:
void test_BSTree6()
{// 测试树的非递归查找函数int a[] = { 2,3,7,1,5,9 };BSTree<int> t;for (auto& e : a){t.insert(e);}t.InOrder();for (auto& e : a){cout << t.FindR(e) << " ";}
}
运行结果:
2. 插入函数
public:
// 插入函数(递归版本)bool InsertR(const K& key){return _InsertR(_root, key);}
private:// 插入函数递归版本的子函数bool _InsertR(Node*& root, const K& key){if (root == nullptr){root = new Node(key);return true;}// 查找插入的位置if (key < root->_key){// 插入在当前树的左子树return _InsertR(root->_left, key);}else if (key > root->_key){// 插入在当前树的右子树return _InsertR(root->_right, key);}else{// 该值在树中已经存在,插入失败return false;}}
// 测试代码
void test_BSTree7()
{// 测试插入函数的递归版本int a[] = { 2,3,7,1,5,9 };BSTree<int> t;for (auto& e : a){t.InsertR(e);}t.InOrder();}
运行结果:
3. 删除函数
public:
// 删除函数的递归版本bool EraseR(const K& key){return _EraseR(_root, key);}
private:// 删除函数递归版本的子函数bool _EraseR(Node*& root, const K& key){if (root == nullptr){// 空树return false;}// 非空树,找删除的结点if (key < root->_key){// 到左子树找return _EraseR(root->_left, key);}else if (key > root->_key){// 到右子树找return _EraseR(root->_right, key);}else{// 找到了// 分类讨论Node* del = root;if (root->_left == nullptr){// 左子树为空root = root->_right;}else if (root->_right == nullptr){// 右子树为空root = root->_left;}else{// 左右子树均不为空// 替换法Node* minRight = root->_right;while (minRight->_left){minRight = minRight->_left;}swap(minRight->_key, root->_key);// 转化为第一种情况return _EraseR(root->_right, key);}delete del;return true;}}
// 测试代码:void test_BSTree8()
{// 测试插入函数的递归版本int a[] = { 2,3,7,1,5,9 };BSTree<int> t;for (auto& e : a){t.InsertR(e);}t.InOrder();t.EraseR(7);t.InOrder();t.EraseR(1);t.InOrder();for (auto& e : a){t.EraseR(e);}t.InOrder();
}
运行结果:
相关文章:
【C++之容器篇】二叉搜索树的理论与使用
目录前言一、二叉搜索树的概念二、二叉搜素树的模拟实现(增删查非递归实现)1. 二叉搜素树的结点2. 二叉搜索树的实现(1). 二叉搜索树的基本结构(2)构造函数(3)查找函数(4…...
爬虫神级解析工具之XPath:用法详解及实战
一、XPATH是什么 Xpath最初被设计用来搜寻XML文档,但它同样适用于HTML文档的搜索。通过简洁明了的路径选择表达式,它提供了强大的选择功能;同时得益于其内置的丰富的函数,它可以匹配和处理字符串、数值、时间等数据格式,几乎所有节点我们都可以通过Xpath来定位。 在Pyth…...
Markdown编辑器
这里写自定义目录标题欢迎使用Markdown编辑器新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注…...
数据结构<堆>
🎇🎇🎇作者: 小鱼不会骑车 🎆🎆🎆专栏: 《数据结构》 🎓🎓🎓个人简介: 一名专科大一在读的小比特,努力学习编程是我唯一…...
Linux下Socket编程利用多进程实现一台服务器与多台客户端并发通信
文章目录前言一、服务器 server二、客户端 client三、并发通信演示四、程序源码前言 前些日子同“ Linux应用编程 ”专栏中发布过的TCP及UDP在Linux或Windows下的通信都为单进程下的Socket编程,若还存在一些套接字相关函数模糊不清,读者可移步“Socket编…...
【MySQL】数据库基础
目录 1、什么是数据库 2、 数据库基本操作 2.1 查看当前数据库 2.2 创建一个数据库 2.3 选中数据库 2.4 删除数据库 3、常见的数据类型 3.1 数值类型 3.2 字符串类型 3.3 日期类型 4、表的操作 4.1 创建表 4.2 查看指定数据库下的所有表 4.3 查看表的结构 4.…...
Microsoft Office 2021 / 2019 Direct Download Links
前言 微软Office在很长一段时间内都是最常用和最受欢迎的软件。从小型创业公司到大公司,它的使用比例相当。它可以很容易地从微软的官方网站下载。但是,微软只提供安装程序,而不提供完整的软件供下载。这些安装文件通常比较小。下载并运行后,安装的文件将从后端服务器安装M…...
XX 系统oracle RAC+ADG 数据库高可用容灾演练记录
停止备库监听,避免强制关机时切换到备库 su - grid lsnrctl stop 主库高可用重启测试 /u01/app/19c/grid/bin/crsctl stop crs sync;sync;reboot --/u01/app/19c/grid/bin/crsctl start crs 机器重启后自动起的 /u01/app/19c/grid/bin/crsctl stat res -t 主库容…...
JSP与Servlet
一、什么是JSP? JSP(java Service Pages)是由Sun Microsystems公司倡导、许多公司参与一起建立的动态技术标准。 在传统的HTML文件(*.htm 、 *.html)中加入Java程序片段(Scriptlet)和JSP标签,构成了JSP网页。 1.1 JSP页面的运行原理 客户…...
C++之迭代器
迭代器C中,迭代器就是类似于指针的对象,但比指针的功能更丰富,它提供了对对象的间接访问,每个迭代器对象代表容器中一个确定的地址。举个例子:void test() {vector<int> vv{1,2,3,4,5};for(vector<int>::i…...
2023-02-16:干活小计
数学公式表示学习: 大约耗时:2 hours 在做了一些工作后重读论文:MathBERT: A Pre-Trained Model for Mathematical Formula Understanding 这是本篇论文最重要的idea:Current pre-trained models neglect the structural featu…...
Linux上安装LaTeX
Linux上安装LaTeX1. 安装1.1 下载安装texlive1.2 配置中文1.3 安装XeLatex1.4 安装编辑器1.5 设置默认支持中文编译1.6 配置环境路径2. latex配置2.1 latex自动安装宏包2.2 latex手动安装宏包2.2.1. 查找包2.2.2. 生成.sty文件2.2.3. 复制到配置文件夹3. 更新包3. 卸载参考链接…...
webpack -- 无法将“webpack”项识别为 cmdlet
webpack : 无法将“webpack”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。 1.检测是否是版本太高而只能使用脚手架进行打包 webpack4.x的打包已经不能用webpack 文件a …...
对齐与非对齐访问
对齐与非对齐访问 什么是非对齐访问 在机器指令层面,当尝试从不能被 N 整除 (addr % N ! 0) 的起始地址读取 N 字节的数据时即发生了非对齐内存访问。举例而言,从地址 0x10004 读取 4 字节是可以的,然而从地址 0x10005 读取 4 字节数据将会…...
基于感知动作循环的层次推理用于视觉问答
title:Hierarchical Reasoning Based on Perception Action Cycle for Visual Question Answering 基于感知动作循环的层次推理用于视觉问答 文章目录title:[Hierarchical Reasoning Based on Perception Action Cycle for Visual Question Answering](…...
python中的.nc文件处理 | 05 NetCDF数据的进一步分析
NetCDF数据的进一步分析 比较不同数据集、不同季节的气候数据 import os import numpy as np import pandas as pd import matplotlib.pyplot as plt import cartopy.crs as ccrs import cartopy.feature as cfeature import seaborn as sns import geopandas as gpd import…...
GGX发布全新路线图,揭示具备 Layer0 特性且可编程的跨链基建生态
据彭博社报道,具备跨链通信且可编程的 Layer0 基础设施协议 Golden Gate (GGX) 已进行了 两年的线下开发,于近日公开发布了最新的路线图,该路线图不仅显示了该生态在过去两年的发展历程,也披露了 2023 年即将实现的重要里程碑。 G…...
taro+vue3 搭建一套框架,适用于微信小程序和H5
这里写tarovue3 搭建一套框架,适用于微信小程序和H5TaroVue3 搭建适用于微信小程序和 H5 的框架的大致步骤:TaroVue3 搭建适用于微信小程序和 H5 的框架的大致步骤: 安装 Taro。可以在终端输入以下命令进行安装: npm install -g…...
C++:模板初阶(泛型编程、函数模板、类模板)
文章目录1 泛型编程2 函数模板2.1 函数模板概念2.2 函数模板格式2.3 函数模板的原理2.4 函数模板的实例化2.5 模板参数的匹配原则3 类模板3.1 类模板的定义格式3.2 类模板的实例化1 泛型编程 所谓泛型,也就是通用型的意思。 在以往编写代码时,我们常常…...
把数组排成最小的数 AcWing(JAVA)
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。 例如输入数组 [3,32,321][3,32,321],则打印出这 33 个数字能排成的最小数字 321323321323。 数据范围 数组长度 [0,500][0,500]。 样例&#x…...
4.3 PBR
1. 实验目的 熟悉PBR的应用场景掌握PBR的配置方法2. 实验拓扑 PBR实验拓扑如图4-8所示: 图4-8:PBR 3. 实验步骤 (1) IP地址的配置 R1的配置 <Huawei>system-view...
hmac — 加密消息签名和验证
hmac — 加密消息签名和验证 1.概述 它的全称叫做Hash-based Message Authentication Code: 哈希消息认证码,从名字中就可以看出来这个hmac基于哈希函数的,并且还得提供一个秘钥key,它的作用就是用来保证消息的完整性,不可篡改。…...
AWS攻略——使用ACL限制访问
文章目录确定出口IP修改ACL修改主网络ACL修改入站规则修改子网ACL创建子网ACL新增入站规则新增出站规则关联子网假如我们希望限制只有公司内部的IP可以SSH登录到EC2,则可以考虑使用ACL来实现。 我们延续使用《AWS攻略——创建VPC》的案例,在它的基础上做…...
【已解决】关于 luckysheet 设置纯文本,解决日期格式回显错误的办法
目录 一、现象 二、分析 三、思考过程 五、解决 六、参考链接 一、现象 在excel里面输入内容,如 2023-2-17 12:00 保存后,传回后端的数据被转化成了 数值类型,这显然是一种困扰。 如图所示 二、分析 查阅了文档和一些博客发现 Lucky…...
Jackson
first you need to add dependence: gradle: implementation com.fasterxml.jackson.core:jackson-databind:2.13.1 implementation com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.13.1原生Jackson的使用示例: /*** 原生Jackson的使用示例*/ public class Jacks…...
字节软件测试岗:惨不忍睹的三面,幸好做足了准备,月薪19k,已拿offer
我今年25岁,专业是电子信息工程本科,19年年末的时候去面试,统一投了测试的岗位,软件硬件都有,那时候面试的两家公司都是做培训的,当初没啥钱,他们以面试为谎言再推荐去培训这点让我特别难受。后…...
vue使用axios发送post请求携带json body参数,后端使用@RequestBody进行接收
前言 最近在做自己项目中,做一个非常简单的新增用户场景,但是使用原生axios发送post请求的时候,还是踩了不少坑的。 唉,说多了都是泪,小小一个新增业务,在自己前后端一起开发的时候,硬是搞了好…...
【python百炼成魔】python之列表详解
文章目录一. 列表的概念1.1 列表是什么?1.2 为什么要使用列表?1.3 列表的定义二. 列表的增删改查操作2.1 列表的读取2.2 列表的切片2.3 列表的查询操作2.3.1 not in ,in 表达式2.3.2 列表元素遍历2.4 列表元素的增加操作2.4.1 append()的相关用法2.4.2 e…...
如何学习 Web3
在本文中,我将总结您可以采取的步骤来学习 Web3。从哪儿开始?当我们想要开始新事物时,我们需要一些指导,以免在一开始就卡住。但我们都是不同的,我们有不同的学习方式。这篇文章基于我学习 Web3 的非常个人的经验。路线…...
大数据框架之Hadoop:MapReduce(一)MapReduce概述
1.1MapReduce定义 MapReduce是一个分布式计算框架,用于编写批处理应用程序,是用户开发“基于Hadoop的数据分析应用”的核心框架。 MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序,并发运行在一…...
网站的设计特点有哪些/怎么推广游戏代理赚钱
1.Redis 面试题1、什么是 Redis?.2、Redis 的数据类型?3、使用 Redis 有哪些好处?4、Redis 相比 Memcached 有哪些优势?5、Memcache 与 Redis 的区别都有哪些?6、Redis 是单进程单线程的?7、一个字符串类型的值能存储…...
网站建设名片/成功的网络营销案例
2020/04/14 每日十句英语口语 1.It’s a deal. 2.One more thing I forgot. 3.Does the rent cover the utilities? 4.What’s your rule about pets? 5.I’m still deciding. 6.The stove (refrigerator, air conditioning, etc.) doesn’t work. 1.成交。 2.还有件事儿我忘…...
设计师门户网站程序/网站推广软件
2019独角兽企业重金招聘Python工程师标准>>> 用eosjs连接主网节点很简单,只需要在创建JsonRpc对象时,指定要连接主网节点的地址 就可以了。 如果要深入系统地学习EOS开发,推荐这个课程:EOS智能合约与DApp开发入门 例如…...
专业手机移动网站建设/关键词上首页的有效方法
由OpenDigg 出品的安卓开源项目周报第十五期来啦。我们的安卓开源周报集合了OpenDigg一周来新收录的优质的安卓开源项目,方便安卓开发人员便捷的找到自己需要的项目工具。 spruce-android 在屏幕上设计动画 AdaptiveTableLayout 读取和写入CSV文件 ShadowImageView …...
地旺建设官方网站/宁波seo网站排名优化公司
探究网吧被***的根源及解决之道 最近各地网吧经常发生掉线的现象,经技术人员发现有人恶意***网吧,发送大量UDP包堵塞网吧的网络,包小量大,每秒几万条,高时能有150MB的流量,很多路由器是直接接在光纤收发器上…...
海安建设局网站/百度搜索排名
线程本地存储又叫线程局部存储,英文名称为Thread Local Storage,简称TLS,实质上是线程私有的全局变量而已。 普通全局变量在多线程中是共享的,一个线程对其进行了修改,其它所有线程都可以看到,而线程私有…...