高级搜索树-AVL树
AVL树是平衡二叉搜索树中的一种,在渐进意义下,AVL树可以将高度始终控制在O(log n) 以内,以保证每次查找、插入和删除操作均可以在O(log n)的时间内完成。
平衡因子
定义任一结点v的平衡因子(balance factor)为其左右子树的高度差
balfac(v) = height(v->lc) - height(v->rc)
AVL树即平衡因子受限的二叉搜索树—————各结点平衡因子的绝对值不超过1
template<typename T>
inline bool AVLTree<T>::balanced(AVLNodePos(T) &cur) {
int lh = 0, rh = 0;
if (HasLChild(cur))
lh = cur->lc->height;
if (HasRChild(cur))
rh = cur->rc->height;
if ((lh - rh)*(lh - rh) > 1)
return false;
return true;
}
AVL树节点和AVL树的定义
- AVL节点AVLNode的定义
template<typename T>
struct AVLNode {
public:
T key;
int height;
AVLNodePos(T) pa;//pa -- parent
AVLNodePos(T) lc;//lc -- left child
AVLNodePos(T) rc;//rc -- right child
//构造函数
AVLNode(): height(0), pa(NULL), lc(NULL), rc(NULL) {}
AVLNode(T elem, int height = 0, AVLNodePos(T) pa = NULL, AVLNodePos(T) lc = NULL, AVLNodePos(T) rc = NULL) :
key(elem), height(height), pa(pa), lc(lc), rc(rc) { }
};
- AVL树AVLTree的定义如下
template<typename T>
class AVLTree {
private:
AVLNodePos(T) root; //树根
public:
//构造函数和析构函数
AVLTree():root(NULL){}
~AVLTree() {}
//只读函数
int height() { return Height(root); }
//遍历函数
void preOrder(); //前序遍历
void inOrder(); //中序遍历
void postOrder(); //后序遍历
//操作函数
AVLNodePos(T) search(const T &key); //查找函数,若存在值为key的节点返回相应节点,若不存在则返回NULL
AVLNodePos(T) insert(const T &key); //插入值为key的节点
bool remove(const T &key); //移除值为key的节点
private:
bool balanced(AVLNodePos(T) &cur); //判断cur节点是否平衡
void upDataHeight(AVLNodePos(T) &cur); //更新节点cur的高度
void preOrder(AVLNodePos(T) &cur); //以cur节点为root进行前序遍历
void inOrder(AVLNodePos(T) &cur); //以cur节点为root进行中序遍历
void postOrder(AVLNodePos(T) &cur); //以cur节点为root进行后序遍历
AVLNodePos(T) searchIn(const T & key, AVLNodePos(T) cur, AVLNodePos(T)& hot); //以cur节点为root查找值为key的节点,hot为返回节点的父节点
AVLNodePos(T) tallerChild(AVLNodePos(T) &g); //返回g高度更高的孩子
AVLNodePos(T) connect34(AVLNodePos(T) a, AVLNodePos(T) b, AVLNodePos(T) c, //根据 "3"+"4"法则对子树进行调整
AVLNodePos(T) T0, AVLNodePos(T) T1, AVLNodePos(T) T2, AVLNodePos(T) T3);
AVLNodePos(T) adjustNode(AVLNodePos(T)& cur); //调整失衡节点cur,返回调整后得到局部子树的root,并将调整后子树接入原树
};
失衡调整
AVL树和常规二叉搜索树一样也支持插入、删除等动态修改操作,但是经过这类操作之后节点的高度可能发生变化,以至于不再满足AVL树的条件。为此要定义相关使得搜索树平衡的调整算法。只需在每次动态操作后利用balanced()函数判断当前节点是否平衡,在找到第一个失衡节点g后,找到g高度更高的孩子p和p高度更高的孩子s这三个节点,根据相应g,p,s的关系能找到四棵子树T0,T1,T2,T3,利用 3 + 4 重构法则就能统一调整算法
//根据 "3"+"4"法则对子树进行调整
template<typename T>
AVLNodePos(T) AVLTree<T>::connect34(
AVLNodePos(T) a, AVLNodePos(T) b, AVLNodePos(T) c,
AVLNodePos(T) T0, AVLNodePos(T) T1, AVLNodePos(T) T2, AVLNodePos(T) T3)
{ //最终实现效果如下:
a->lc = T0; if (T0) T0->pa = a; // b
a->rc = T1; if (T1) T1->pa = a; // / \
c->lc = T2; if (T2) T2->pa = c; // a c
c->rc = T3; if (T3) T3->pa = c; // / \ / \
b->lc = a; b->rc = c; // T0 T1 T2 T3
a->pa = b; c->pa = b;
b->pa = NULL;
upDataHeight(a);
upDataHeight(c);
upDataHeight(b); //更新高度
return b; //返回b
}
//调整失衡节点cur,返回调整后得到局部子树的root,并将调整后子树接入原树
template<typename T>
AVLNodePos(T) AVLTree<T>::adjustNode(AVLNodePos(T) &g) {
//一旦发现失衡 找到g,p,s 三个节点 //g --grandfa
AVLNodePos(T) p = tallerChild(g); //p --parent
AVLNodePos(T) s = tallerChild(p); //s --son
AVLNodePos(T) gg = g->pa; //gg -- g's parent
if (IsLChild(s) && IsLChild(p)) //left -- left
g = connect34(s, p, g, s->lc, s->rc, p->rc, g->rc);
else if (IsRChild(s) && IsLChild(p)) //right -- left
g = connect34(p, s, g, p->lc, s->lc, s->rc, g->rc);
else if (IsRChild(s) && IsRChild(p)) //right -- right
g = connect34(g, p, s, g->lc, p->lc, s->lc, s->rc);
else if (IsLChild(s) && IsRChild(p)) //left -- left
g = connect34(g, s, p, g->lc, s->lc, s->rc, p->rc);
//将调整后子树接回原树
if (!gg) root = g;// gg为NULL说明g为root,更新root
else { //连接gg和 g
if (gg->key > g->key) {//作为左子树接入
gg->lc = g;
g->pa = gg;
}
else {//作为右子树接入
gg->rc = g;
g->pa = gg;
}
}
upDataHeight(gg);//g的高度已经在connect34时更新,故更新连接g后的gg高度
return g;
}
插入和删除操作
插入和删除操作同搜索二叉树一样,只是每一次都要节点检查是否平衡,如果失衡则进行调整
//AVLNodePos(T) searchIn(const T & key, AVLNodePos(T) cur, AVLNodePos(T)& hot);以cur节点为root查找值为key的节点,hot为返回节点的父节点
//插入值为key的节点
template<typename T>
AVLNodePos(T) AVLTree<T>::insert(const T & key)
{
AVLNodePos(T) cur_pa=NULL;
AVLNodePos(T) x = searchIn(key, root, cur_pa);
if (x) return x; //已经存在值为key的节点
//否则确认key不存在
if (!root)
x = root = new AVLNode<T>(key);
else {
//连接节点
x = new AVLNode<T>(key,0,cur_pa);
if (x->key > cur_pa->key)
cur_pa->rc = x;
else
cur_pa->lc = x;
upDataHeight(x); //更新高度
}
for (AVLNodePos(T) g = cur_pa; g; g = g->pa) { //从 插入节点的父节点开始向上检查
if (!balanced(g)) {//若g失衡
adjustNode(g);//调整以g为root的局部子树
break; //g复平衡后,局部子树高度必然复原,其祖先亦如此,故调整可到此结束
}else {//否则g平衡
upDataHeight(g); //更新高度
}
}
return x; //返回新插入节点位置
}
//移除值为key的节点
template<typename T>
inline bool AVLTree<T>::remove(const T & key)
{
AVLNodePos(T) x = search(key);
if (!x)
return false;//不存在值为key的节点
AVLNodePos(T) w = x; //w是实际被摘除节点
if (!HasLChild(x)) {// 如果x没有左子树,用右子树代替x
if (IsRoot(x))
root = x->rc;
else {
if (IsLChild(x)) x->pa->lc = x->rc;
else x->pa->rc = x->rc;
}
}
else if (!HasRChild(x)) {//如果x没有右子树, 用左子树替代
if (IsRoot(x))
root = x->lc;
else {
if (IsLChild(x)) x->pa->lc = x->lc;
else x->pa->rc = x->lc;
}
}else { //否则有左右子树
//取w为x的直接后继
w = x->rc;
while (HasLChild(w))
w = w->lc;
//交换数据
T tmp = x->key;
x->key = w->key;
w->key = tmp;
if (HasRChild(w))
w->rc->pa = w->pa;
if (w->pa == x) // 注意 w为x的右子这种情况
x->rc = w->rc;
else
w->pa->lc = w->rc;
}
upDataHeight(w->pa);
for (AVLNodePos(T) g = w->pa; g; g = g->pa) { //从succ的父节点开始向上检查
if (!balanced(g)) {//若g失衡
g=adjustNode(g);//调整以g为root的局部子树
//不同于插入操作,删除操作造成的失衡可能会传播
}
else {//否则g平衡
upDataHeight(g); //更新高度
}
}
delete w;//摘除w
return true;
}
完整源码
代码参考《数据结构(c++语言版)》--清华大学邓俊辉
"AVLTree_Declaration.h"
//#include"pch.h"
#include<iostream>
#ifndef _AVL_TREE_DECLARATION_H
#define _AVL_TREE_DECLARATION_H
#define AVLNodePos(T) AVLNode<T> *
//宏定义
#define IsRoot(x) ( !((x)->pa) )
#define IsLChild(x) ( !(IsRoot(x) ) && (x)==(x)->pa->lc)
#define IsRChild(x) ( !(IsRoot(x) ) && (x)==(x)->pa->rc)
#define HasLChild(x) ((x)->lc )
#define HasRChild(x) ((x)->rc )
#define HasChild(x) (HasLChild(x) || HasRChild(x))
#define HasBothChild(x) (HasRChild(x) && HasLChild(x) )
#define IsLeaf(x) (! HasChild(x) )
#define Height(x) ( (x)==NULL? 0: (x)->height ) //x的高度
//AVLNode 定义
template<typename T>
struct AVLNode {
public:
T key;
int height;
AVLNodePos(T) pa;//pa -- parent
AVLNodePos(T) lc;//lc -- left child
AVLNodePos(T) rc;//rc -- right child
//构造函数
AVLNode(): height(0), pa(NULL), lc(NULL), rc(NULL) {}
AVLNode(T elem, int height = 0, AVLNodePos(T) pa = NULL, AVLNodePos(T) lc = NULL, AVLNodePos(T) rc = NULL) :
key(elem), height(height), pa(pa), lc(lc), rc(rc) { }
};
//AVLTree 定义
template<typename T>
class AVLTree {
private:
AVLNodePos(T) root; //树根
public:
//构造函数和析构函数
AVLTree():root(NULL){}
~AVLTree() {}
//只读函数
int height() { return Height(root); }
//遍历函数
void preOrder(); //前序遍历
void inOrder(); //中序遍历
void postOrder(); //后序遍历
//操作函数
AVLNodePos(T) search(const T &key); //查找函数,若存在值为key的节点返回相应节点,若不存在则返回NULL
AVLNodePos(T) insert(const T &key); //插入值为key的节点
bool remove(const T &key); //移除值为key的节点
private:
bool balanced(AVLNodePos(T) &cur); //判断cur节点是否平衡
void upDataHeight(AVLNodePos(T) &cur); //更新节点cur的高度
void preOrder(AVLNodePos(T) &cur); //以cur节点为root进行前序遍历
void inOrder(AVLNodePos(T) &cur); //以cur节点为root进行中序遍历
void postOrder(AVLNodePos(T) &cur); //以cur节点为root进行后序遍历
AVLNodePos(T) searchIn(const T & key, AVLNodePos(T) cur, AVLNodePos(T)& hot); //以cur节点为root查找值为key的节点,hot为返回节点的父节点
AVLNodePos(T) tallerChild(AVLNodePos(T) &g); //返回g高度更高的孩子
AVLNodePos(T) connect34(AVLNodePos(T) a, AVLNodePos(T) b, AVLNodePos(T) c, //根据 "3"+"4"法则对子树进行调整
AVLNodePos(T) T0, AVLNodePos(T) T1, AVLNodePos(T) T2, AVLNodePos(T) T3);
AVLNodePos(T) adjustNode(AVLNodePos(T)& cur); //调整失衡节点cur,返回调整后得到局部子树的root,并将调整后子树接入原树
};
#endif
"AVLTree_Define.h"
//具体实现
//#include"pch.h"
#include "AVLTree_Declaration.h"
#include<iostream>
#ifndef _AVL_TREE_DEFINE_H
#define _AVL_TREE_DEFINE_H
template<typename T>
inline void AVLTree<T>::preOrder(AVLNodePos(T) & cur)
{
if (!cur) return;
std::cout << cur->key << " ";
preOrder(cur->lc);
preOrder(cur->rc);
}
template<typename T>
inline void AVLTree<T>::inOrder(AVLNodePos(T) & cur)
{
if (!cur) return;
inOrder(cur->lc);
std::cout << cur->key << " ";
inOrder(cur->rc);
}
template<typename T>
inline void AVLTree<T>::postOrder(AVLNodePos(T)& cur)
{
if (!cur) return;
postOrder(cur->lc);
postOrder(cur->rc);
std::cout << cur->key << " ";
}
template<typename T>
inline void AVLTree<T>::preOrder()
{
preOrder(root);
}
template<typename T>
inline void AVLTree<T>::inOrder()
{
inOrder(root);
}
template<typename T>
inline void AVLTree<T>::postOrder()
{
postOrder(root);
}
//判断cur节点是否平衡
template<typename T>
inline bool AVLTree<T>::balanced(AVLNodePos(T) &cur) {
int lh = 0, rh = 0;
if (HasLChild(cur))
lh = cur->lc->height;
if (HasRChild(cur))
rh = cur->rc->height;
if ((lh - rh)*(lh - rh) > 1)
return false;
return true;
}
//返回g高度更高的孩子
template<typename T>
inline AVLNodePos(T) AVLTree<T>::tallerChild(AVLNodePos(T) &g) {
if (HasBothChild(g)) {
return (g->lc->height >= g->rc->height ? g->lc : g->rc);
}
else if (HasLChild(g))
return g->lc;
else if (HasRChild(g))
return g->rc;
return NULL;
}
//更新节点cur的高度
template<typename T>
inline void AVLTree<T>::upDataHeight(AVLNodePos(T) & p)
{
if (!p) return;
int tmp = p->height;
if (IsLeaf(p))
p->height = 1;
else if (HasBothChild(p))
p->height = (p->lc->height > p->rc->height) ? p->lc->height + 1 : p->rc->height + 1;
else if (HasLChild(p))
p->height = p->lc->height + 1;
else if (HasRChild(p))
p->height = p->rc->height + 1;
return;
}
//以cur节点为root查找值为key的节点,hot为返回节点的父节点
template<typename T>
inline AVLNodePos(T) AVLTree<T>::searchIn(const T & key, AVLNodePos(T) cur, AVLNodePos(T)& hot)
{
if (!cur || key == cur->key) return cur;
hot = cur;
return searchIn(key, (key < cur->key ? cur->lc : cur->rc), hot);
}
//查找函数,若存在值为key的节点返回相应节点,若不存在则返回NULL
template<typename T>
inline AVLNodePos(T) AVLTree<T>::search(const T & key)
{
AVLNodePos(T) hot = NULL;
return searchIn(key, root, hot);
}
//根据 "3"+"4"法则对子树进行调整
template<typename T>
AVLNodePos(T) AVLTree<T>::connect34(
AVLNodePos(T) a, AVLNodePos(T) b, AVLNodePos(T) c,
AVLNodePos(T) T0, AVLNodePos(T) T1, AVLNodePos(T) T2, AVLNodePos(T) T3)
{ //最终实现效果如下:
a->lc = T0; if (T0) T0->pa = a; // b
a->rc = T1; if (T1) T1->pa = a; // / \
c->lc = T2; if (T2) T2->pa = c; // a c
c->rc = T3; if (T3) T3->pa = c; // / \ / \
b->lc = a; b->rc = c; // T0 T1 T2 T3
a->pa = b; c->pa = b;
b->pa = NULL;
upDataHeight(a);
upDataHeight(c);
upDataHeight(b); //更新高度
return b; //返回b
}
//调整失衡节点cur,返回调整后得到局部子树的root,并将调整后子树接入原树
template<typename T>
AVLNodePos(T) AVLTree<T>::adjustNode(AVLNodePos(T) &g) {
//一旦发现失衡 找到g,p,s 三个节点 //g --grandfa
AVLNodePos(T) p = tallerChild(g); //p --parent
AVLNodePos(T) s = tallerChild(p); //s --son
AVLNodePos(T) gg = g->pa; //gg -- g's parent
if (IsLChild(s) && IsLChild(p)) //left -- left
g = connect34(s, p, g, s->lc, s->rc, p->rc, g->rc);
else if (IsRChild(s) && IsLChild(p)) //right -- left
g = connect34(p, s, g, p->lc, s->lc, s->rc, g->rc);
else if (IsRChild(s) && IsRChild(p)) //right -- right
g = connect34(g, p, s, g->lc, p->lc, s->lc, s->rc);
else if (IsLChild(s) && IsRChild(p)) //left -- left
g = connect34(g, s, p, g->lc, s->lc, s->rc, p->rc);
//将调整后子树接回原树
if (!gg) root = g;// gg为NULL说明g为root,更新root
else { //连接gg和 g
if (gg->key > g->key) {//作为左子树接入
gg->lc = g;
g->pa = gg;
}
else {//作为右子树接入
gg->rc = g;
g->pa = gg;
}
}
upDataHeight(gg);//g的高度已经在connect34时更新,故更新连接g后的gg高度
return g;
}
//插入值为key的节点
template<typename T>
AVLNodePos(T) AVLTree<T>::insert(const T & key)
{
AVLNodePos(T) cur_pa=NULL;
AVLNodePos(T) x = searchIn(key, root, cur_pa);
if (x) return x; //已经存在值为key的节点
//否则确认key不存在
if (!root)
x = root = new AVLNode<T>(key);
else {
//连接节点
x = new AVLNode<T>(key,0,cur_pa);
if (x->key > cur_pa->key)
cur_pa->rc = x;
else
cur_pa->lc = x;
upDataHeight(x); //更新高度
}
for (AVLNodePos(T) g = cur_pa; g; g = g->pa) { //从 插入节点的父节点开始向上检查
if (!balanced(g)) {//若g失衡
adjustNode(g);//调整以g为root的局部子树
break; //g复平衡后,局部子树高度必然复原,其祖先亦如此,故调整可到此结束
}else {//否则g平衡
upDataHeight(g); //更新高度
}
}
return x; //返回新插入节点位置
}
//删除值为key的节点
template<typename T>
inline bool AVLTree<T>::remove(const T & key)
{
AVLNodePos(T) x = search(key);
if (!x)
return false;//不存在值为key的节点
AVLNodePos(T) w = x; //w是实际被摘除节点
if (!HasLChild(x)) {// 如果x没有左子树,用右子树代替x
if (IsRoot(x))
root = x->rc;
else {
if (IsLChild(x)) x->pa->lc = x->rc;
else x->pa->rc = x->rc;
}
}
else if (!HasRChild(x)) {//如果x没有右子树, 用左子树替代
if (IsRoot(x))
root = x->lc;
else {
if (IsLChild(x)) x->pa->lc = x->lc;
else x->pa->rc = x->lc;
}
}else { //否则有左右子树
//取w为x的直接后继
w = x->rc;
while (HasLChild(w))
w = w->lc;
//交换数据
T tmp = x->key;
x->key = w->key;
w->key = tmp;
if (HasRChild(w))
w->rc->pa = w->pa;
if (w->pa == x) // 注意 w为x的右子这种情况
x->rc = w->rc;
else
w->pa->lc = w->rc;
}
upDataHeight(w->pa);
for (AVLNodePos(T) g = w->pa; g; g = g->pa) { //从succ的父节点开始向上检查
if (!balanced(g)) {//若g失衡
g=adjustNode(g);//调整以g为root的局部子树
//不同于插入操作,删除操作造成的失衡可能会传播
}
else {//否则g平衡
upDataHeight(g); //更新高度
}
}
delete w;//摘除w
return true;
}
#endif
"main.cpp"
// main.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include"AVLTree_Define.h"
#include"AVLTree_Declaration.h"
using namespace std;
int main()
{
AVLTree<int> t;
int n;
cout << "insert number:";
cin >> n;
cout << "insert:" ;
for (int i = 0; i < n; i++) {
int tmp;
cin >> tmp;
t.insert(tmp);
}
cout << "PreOrder:";
t.preOrder();
cout << endl;
cout << "InOrder:";
t.inOrder();
cout << endl;
cout << "PostOrder:";
t.postOrder();
cout << endl;
cout << "remove number:";
cin >>n;
cout << "remove:";
for (int i = 0; i < n; i++) {
int tmp;
cin >> tmp;
t.remove(tmp);
}
cout << "PreOrder:";
t.preOrder();
cout << endl;
cout << "InOrder:";
t.inOrder();
cout << endl;
cout << "PostOrder:";
t.postOrder();
cout << endl;
return 0;
}
高级搜索树-AVL树的更多相关文章
- 树-二叉搜索树-AVL树
树-二叉搜索树-AVL树 树 树的基本概念 节点的度:节点的儿子数 树的度:Max{节点的度} 节点的高度:节点到各叶节点的最大路径长度 树的高度:根节点的高度 节点的深度(层数):根节点到该节点的路 ...
- 高度平衡的二叉搜索树(AVL树)
AVL树的基本概念 AVL树是一种高度平衡的(height balanced)二叉搜索树:对每一个结点x,x的左子树与右子树的高度差(平衡因子)至多为1. 有人也许要问:为什么要有AVL树呢?它有什么 ...
- 高级搜索树-伸展树(Splay Tree)
目录 局部性 双层伸展 查找操作 插入操作 删除操作 性能分析 完整源码 与AVL树一样,伸展树(Splay Tree)也是平衡二叉搜索树的一致,伸展树无需时刻都严格保持整棵树的平衡,也不需要对基本的 ...
- AVL树和平衡二叉树 平衡因子 右旋转LL 左旋转RR LR RL
前言 今天要介绍几种高级数据结构AVL树,介绍之前AVL,会先说明平衡二叉树,并将树的学习路线进行总结,并介绍维持平衡的方法:右旋转.左旋转. 一.树学习路线 1.路线总结 总结了一下树的学习路线,如 ...
- 自已动手作图搞清楚AVL树
@ 目录 一.背景 二.平衡二分搜索树---AVL树 2.1 AVL树的基本概念 结点 高度 平衡因子 2.2 AVL树的验证 三.旋转操作 3.1 L L--需要通过右旋操作 3.2 R R--需要 ...
- PAT树_层序遍历叶节点、中序建树后序输出、AVL树的根、二叉树路径存在性判定、奇妙的完全二叉搜索树、最小堆路径、文件路由
03-树1. List Leaves (25) Given a tree, you are supposed to list all the leaves in the order of top do ...
- 平衡搜索树(一) AVL树
AVL树 AVL树又称为高度平衡的二叉搜索树,是1962年有俄罗斯的数学家G.M.Adel'son-Vel'skii和E.M.Landis提出来的.它能保持二叉树的高度 平衡,尽量降低二叉树的高度,减 ...
- 二叉搜索树的平衡--AVL树和树的旋转(图解)
二叉搜索树只有保持平衡时其查找效率才会高. 要保持二叉搜索树的平衡不是一件易事.不过还是有一些非常经典的办法可以做到,其中最好的方法就是将二叉搜索树实现为AVL树. AVL树得名于它的发明者 G.M. ...
- 算法二叉搜索树之AVL树
最近学习了二叉搜索树中的AVL树,特在此写一篇博客小结. 1.引言 对于二叉搜索树而言,其插入查找删除等性能直接和树的高度有关,因此我们发明了平衡二叉搜索树.在计算机科学中,AVL树是最先发明的自平衡 ...
随机推荐
- 小谢第36问:elemet - table表格修改后表格行高亮显示且定位到当前行当前页
第一次做这个需求得时候很乱,总是在表格页和修改页徘徊,总觉得什么都会,但是就是做不出自己想要得效果 其实如果先把思路搞清楚,这个问题得知识点却是不多,以下是我对表格高亮显示得思路: 首先,我会从已知得 ...
- Burp Suite Scanner Module - 扫描模块
Burp Suite Professional 和Enterprise Version的Scaner功能较丰富. 以Professional版本为例,包含Issue activity, Scan qu ...
- SQL 给某字段添加汉字却显示??
错误展示: 解决方案: 1.在要修改的数据库上单击鼠标右键,并选择“属性”. 2.在弹出的数据库属性窗口中点击“选择页”中的“选项”. 3.将排序规则由默认的SQL_Latin1_Genera ...
- python多线程之Threading
什么是线程? 线程是操作系统内核调度的基本单位,一个进程中包含一个或多个线程,同一个进程内的多个线程资源共享,线程相比进程是“轻”量级的任务,内核进行调度时效率更高. 多线程有什么优势? 多线程可以实 ...
- C++语法小记---经典问题之一(一个空类包含什么)
问题:一个空类包含什么 空的构造函数 拷贝构造函数(浅拷贝) 重载赋值操作符函数(浅拷贝) 析构函数 取址运算符 取址运算符const 注意 所有的这些默认函数,只有在代码中调用了才会生成,否则也不会 ...
- Python 什么时候会被取代?
以下是译文: Python经过了几十年的努力才得到了编程社区的赏识.自2010年以来,Python得到了蓬勃发展,并最终超越了C.C#.Java和JavaScript. 但是,这种趋势将持续到什么 ...
- python 中文乱码 list 乱码处理
list 乱码 data_list = ["中文"] print str(data_list).decode("string_escape") mysql 获取 ...
- 性能测试 -- docker安装influxdb
一.前提 1.项目已经部署好 2.docker已经安装好 二.docker安装influxdb 1.下载influxdb镜像:docker pull tutum/influxdb 1)超时报错: ...
- 旧的成功的AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="htt ...
- 《闲扯Redis八》Redis字典的哈希表执行Rehash过程分析
一.前言 随着操作的不断执行, 哈希表保存的键值对会逐渐地增多或者减少, 为了让哈希表的负载因子(load factor)维持在一个合理的范围之内, 当哈希表保存的键值对数量太多或者太少时, 程序需要 ...