红黑树
//红黑树节点的定义
enunm colour
{
RED,
BLACK,
};
template<class K,class V>
struct RBTreeNode
{
RBTreeNode<K,V>* _left;
RBTreeNode<K,V>* _right;
RBTreeNode<K,V>* _parent; //三叉链
pair<K,V> _kv;
colour _col;
RBTreeeNode(const pair<K,V>& kv)
:_left(nullptr)
,_right(nullptr)
,_parent(nullptr)
,_kv(kv)
,_col(RED)
{}
};
template <class K,class V>
class RBTree
{
typedef RBTreeNode<K,V>Node;
public:
private:
Node* _root = nullptr;
};
//红黑树的插入
bool Inert (const pair<K,V>&kv)
{
if(_root == nullptr)
{
_root= new Node(kv);
return true;
}
Node* parent = nullptr;
Node* cur = _root;
while(cur)
{
if(cur->_kv.first<kv.first) //插入节点比当前节点大往右走,小往左走
{
parent = cur;
cur = cur->right;
}
else if(cur->_kv.first> kv.fitst)
{
parent = cur;
cur = cur->left;
}
else
{
return false;
}
}
//链接
cur = new Node(kv);
if(parent->_kv.first>kv.first)
{
parent->_left = cur;
}
else
{
parent->_right;
}
//new的节点的parent还指向空
cur->_parent = parent;
//插入黑色节点还是红色节点 红色
// 如果新插入节点破坏了红黑树规则
// 则更新节点颜色
while (parent && parent->_col == RED)
{
Node* grandfather = parent->_parent;
if (grandfather->_left == parent)
{
Node* uncle = grandfather->_right;
// 情况1:u存在且为红,变色处理,并继续往上处理
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandfather->_col = RED;
// 继续往上调整
cur = grandfather;
parent = cur->_parent;
}
else // 情况2+3:u不存在或者u存在且为黑,旋转+处理
{
// 如果插入节点在父节点的左,c、p、g呈一条斜线
// g
// p u
// c
if (parent->_left == cur)
{
RotateR(grandfather);
parent->_col = BLACK;
grandfather->_col = RED;
}
else
{
// 插入节点在父节点的右,c、p、g呈一条折线
// g
// p u
// c
RotateL(parent);
RotateR(grandfather);
cur->_col = BLACK;
// parent->_col = RED; // 父亲本就是红,变一下双重保险
grandfather->_col = RED;
}
break;
}
}
else // (grandfather->_right == parent)
{
Node* uncle = grandfather->_left;
// 情况1:u存在且为红,变色处理,并继续往上处理
if (uncle && uncle->_col == RED)
{
parent->_col = BLACK;
uncle->_col = BLACK;
grandfather->_col = RED;
// 继续往上调整
cur = grandfather;
parent = cur->_parent;
}
else // 情况2+3:u不存在或者u存在且为黑,旋转+处理
{
// g
// u p
// c
if (parent->_right == cur)
{
RotateL(grandfather);
grandfather->_col = RED;
parent->_col = BLACK;
}
else
{
// g
// u p
// c
RotateR(parent);
RotateL(grandfather);
cur->_col = BLACK;
grandfather->_col = RED;
}
break;
}
}
}
_root->_col = BLACK; // 做个双保险,无论那种情况把根都变成黑的
return true;
}
}
B和B+树
-
btree:所有节点存储数据
-
b树,每次添加都是添加到叶子节点
-
M阶B树满足条件: 1.每个节点最多拥有M颗子树 2.所有叶子节点在同一层 3.关键字数量满足 (M/2)-1 <= n <= M-1
-
先进行合并或者借位再删除, 分裂在添加时才会出现
-
#define SUB_M 3 typedef struct _btree_ndoe{ int *keys;//5 struct _btree_ndoe **childreds;//6 int num; int leaf; }btree_node; typedef struct _btree{ struct _btree_node * root; }btree;
- b+tree:叶子节点存储数据,内节点索引用
- 因此B+树,更适合做磁盘索引
哈希
- 哈希函数
- murmuhash1,2,3 , siphash(redis中使用 ,主要解决字符串接近的强随机性)
- 负载因子 (
used/size
)- 描述冲突激烈程度
- 冲突处理
- 链表法+开放寻址法(或采用双重哈希)
- STL散列表的实现
- 为了实现迭代器,将后面具体节点串成一个单链表
布隆过滤器
- 内存有限,只想确定某个key存不存在
- 实现
- 位图
将key值传入一系列Hash函数得到对应的一系列数组地址(索引下标),注意这里一般来说有几个Hash函数就会得到几个地址,然后去判断这几个索引下标对应的值是否*均为1*,是的话则说明存在,否则不存在。
应用场景
Redis缓存穿透指访问一个缓存和数据库中都不存在的key,由于这个key在缓存中不存在,则会到数据库中查询,数据库中也不存在该key,无法将数据添加到缓存中,所以每次都会访问数据库导致数据库压力增大。
分布式一致性hash
- 解决分布式缓存扩容的问题
- 避免缓存失败
- 固定算法
- 数据迁移
- 保证数据均衡
- 虚拟节点
设计模式
- 虚基类的早晚绑定
设计原则
- 依赖倒置 (高层模块不依赖底层模块。两者依赖抽象)
- 开发封闭 (对扩展(继承)开放,对修改关闭)
- 面向接口
- 封装变化点
- 单一职责(一个类仅只有一个引起变化的原因)
- 里氏替换(子类型必须能够替换它的父类型