性能测试完毕
This commit is contained in:
parent
d0ff4d309b
commit
64e0c379a5
147
src/main.cpp
147
src/main.cpp
|
@ -2,35 +2,148 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
#include "vbtree.h"
|
||||||
|
#include "sbt.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using chrono::high_resolution_clock;
|
using chrono::high_resolution_clock;
|
||||||
|
|
||||||
|
int IntCompare(int v1, int v2)
|
||||||
|
{
|
||||||
|
if (v1 > v2)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (v1 < v2)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ULONG N = 5000000;
|
||||||
|
|
||||||
void Case1()
|
void Case1()
|
||||||
{
|
{
|
||||||
std::map<int, int> m;
|
std::map<int, int> m;
|
||||||
|
|
||||||
|
|
||||||
default_random_engine e;
|
default_random_engine e;
|
||||||
std::uniform_int_distribution<> dist{0, 1000000000};
|
std::uniform_int_distribution<> dist{0, 1000000000};
|
||||||
double N = 1000000;
|
|
||||||
|
|
||||||
|
high_resolution_clock::time_point t1 = high_resolution_clock::now(); //返回时间戳
|
||||||
|
|
||||||
high_resolution_clock::time_point t1 = high_resolution_clock::now(); //返回时间戳
|
for (ULONG i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
auto v = dist(e);
|
||||||
|
m[v] = v;
|
||||||
|
}
|
||||||
|
high_resolution_clock::time_point t2 = high_resolution_clock::now(); //返回时间戳
|
||||||
|
|
||||||
for (int i = 0; i < N; i++)
|
std::cout << (t2 - t1).count() / N << std::endl;
|
||||||
{
|
std::cout << "end RBTree Case Benchmark" << std::endl;
|
||||||
auto v = dist(e);
|
|
||||||
m[v] = v;
|
|
||||||
}
|
|
||||||
high_resolution_clock::time_point t2 = high_resolution_clock::now(); //返回时间戳
|
|
||||||
|
|
||||||
std::cout << (t2 - t1).count() / N << std::endl;
|
|
||||||
std::cout << "end Push Case Benchmark" << std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
void Case1_1()
|
||||||
Case1();
|
{
|
||||||
|
std::map<int, int> m;
|
||||||
|
|
||||||
|
default_random_engine e;
|
||||||
|
std::uniform_int_distribution<> dist{0, 1000000000};
|
||||||
|
|
||||||
|
vector<int> vec;
|
||||||
|
|
||||||
|
for (ULONG i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
auto v = dist(e);
|
||||||
|
m[v] = v;
|
||||||
|
vec.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
high_resolution_clock::time_point t1 = high_resolution_clock::now(); //返回时间戳
|
||||||
|
|
||||||
|
for(auto iter = vec.begin(); iter != vec.end() ; iter++) {
|
||||||
|
m[*iter];
|
||||||
|
}
|
||||||
|
|
||||||
|
high_resolution_clock::time_point t2 = high_resolution_clock::now(); //返回时间戳
|
||||||
|
|
||||||
|
std::cout << (t2 - t1).count() / N << std::endl;
|
||||||
|
std::cout << "end RBTree Case Benchmark" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Case2()
|
||||||
|
{
|
||||||
|
VBTree<int, int> m(IntCompare);
|
||||||
|
|
||||||
|
default_random_engine e;
|
||||||
|
std::uniform_int_distribution<> dist{0, 1000000000};
|
||||||
|
|
||||||
|
high_resolution_clock::time_point t1 = high_resolution_clock::now(); //返回时间戳
|
||||||
|
|
||||||
|
for (ULONG i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
auto v = dist(e);
|
||||||
|
m.put(v, v);
|
||||||
|
}
|
||||||
|
high_resolution_clock::time_point t2 = high_resolution_clock::now(); //返回时间戳
|
||||||
|
|
||||||
|
std::cout << (t2 - t1).count() / N << std::endl;
|
||||||
|
std::cout << "end VBTree Case Benchmark" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Case2_1()
|
||||||
|
{
|
||||||
|
VBTree<int, int> m(IntCompare);
|
||||||
|
|
||||||
|
default_random_engine e;
|
||||||
|
std::uniform_int_distribution<> dist{0, 1000000000};
|
||||||
|
|
||||||
|
vector<int> vec;
|
||||||
|
|
||||||
|
for (ULONG i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
auto v = dist(e);
|
||||||
|
m.put(v, v);
|
||||||
|
vec.push_back(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
high_resolution_clock::time_point t1 = high_resolution_clock::now(); //返回时间戳
|
||||||
|
|
||||||
|
for(auto iter = vec.begin(); iter != vec.end() ; iter++) {
|
||||||
|
m.get(*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
high_resolution_clock::time_point t2 = high_resolution_clock::now(); //返回时间戳
|
||||||
|
|
||||||
|
std::cout << (t2 - t1).count() / N << std::endl;
|
||||||
|
std::cout << "end VBTree Case Benchmark" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Case3() {
|
||||||
|
BinaryTree tree;
|
||||||
|
|
||||||
|
default_random_engine e;
|
||||||
|
std::uniform_int_distribution<> dist{0, 1000000000};
|
||||||
|
|
||||||
|
high_resolution_clock::time_point t1 = high_resolution_clock::now(); //返回时间戳
|
||||||
|
|
||||||
|
for (ULONG i = 0; i < N; i++)
|
||||||
|
{
|
||||||
|
auto v = dist(e);
|
||||||
|
tree.insert(v);
|
||||||
|
}
|
||||||
|
high_resolution_clock::time_point t2 = high_resolution_clock::now(); //返回时间戳
|
||||||
|
|
||||||
|
std::cout << (t2 - t1).count() / N << std::endl;
|
||||||
|
std::cout << "end SBT Case Benchmark" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
Case2_1();
|
||||||
|
// Case1();
|
||||||
}
|
}
|
314
src/sbt.h
Normal file
314
src/sbt.h
Normal file
|
@ -0,0 +1,314 @@
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
class SBTNode {
|
||||||
|
public:
|
||||||
|
//size:子树大小(就是以当前结点为根构成的树有多少结点)
|
||||||
|
//data:权值,就是树上的结点储存的值
|
||||||
|
//value:应该是临时储存权值的
|
||||||
|
int data, size, value;
|
||||||
|
SBTNode * lchild, * rchild, * father;
|
||||||
|
//构造函数,参数分别为 权值,以当前结点为根的树的大小,父亲结点
|
||||||
|
SBTNode(int init_data, int init_size = 0, SBTNode * init_father = NULL);
|
||||||
|
~SBTNode();
|
||||||
|
//下面依次是
|
||||||
|
//二叉排序树的插入,搜索,找前驱,找后继,移除某个度为0或1的结点,移除某个权值的点,找出第k大的元素
|
||||||
|
void insert(int value);
|
||||||
|
SBTNode * search(int value);
|
||||||
|
SBTNode * predecessor();
|
||||||
|
SBTNode * successor();
|
||||||
|
void remove_node(SBTNode * delete_node);
|
||||||
|
bool remove(int value);
|
||||||
|
int select(int k);
|
||||||
|
};
|
||||||
|
|
||||||
|
class BinaryTree {
|
||||||
|
private:
|
||||||
|
SBTNode * root;
|
||||||
|
public:
|
||||||
|
BinaryTree();
|
||||||
|
~BinaryTree();
|
||||||
|
//下面依次是
|
||||||
|
//二叉树的插入 查找 删除结点 找出第k大的树,都是以上面的结点类的函数为基础的
|
||||||
|
void insert(int value);
|
||||||
|
bool find(int value);
|
||||||
|
bool remove(int value);
|
||||||
|
int select(int k);
|
||||||
|
};
|
||||||
|
|
||||||
|
//这里搞了个权值为0的结点,避免在边界情况时对空指针(NULL)进行特判,所以将所有原本指向空指针的情况都改为指向一个 ZPTR,并将其 size 设置为 0,从而降低代码复杂度。
|
||||||
|
SBTNode ZERO(0);
|
||||||
|
SBTNode * ZPTR = &ZERO;
|
||||||
|
|
||||||
|
SBTNode::SBTNode(int init_data, int init_size, SBTNode * init_father) {
|
||||||
|
data = init_data;
|
||||||
|
size = init_size;
|
||||||
|
lchild = ZPTR;
|
||||||
|
rchild = ZPTR;
|
||||||
|
father = init_father;
|
||||||
|
}
|
||||||
|
|
||||||
|
SBTNode::~SBTNode() {
|
||||||
|
if (lchild != ZPTR) {
|
||||||
|
delete lchild;
|
||||||
|
}
|
||||||
|
if (rchild != ZPTR) {
|
||||||
|
delete rchild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//左旋:将右孩子变为“根结点”(当前子树的根结点),右孩子的左孩子就变成原来的根结点的右孩子
|
||||||
|
//下面注释中:node(原来的根结点)的右孩子用“根结点”来说
|
||||||
|
SBTNode * left_rotate(SBTNode * node) {
|
||||||
|
//用temp保存“根结点”
|
||||||
|
SBTNode * temp = node->rchild;
|
||||||
|
//“根结点”的左孩子 变成node(原来的根结点)的右孩子
|
||||||
|
node->rchild = temp->lchild;
|
||||||
|
//更新“根结点”原来的左孩子的父亲为node(原来的根结点)
|
||||||
|
temp->lchild->father = node;
|
||||||
|
//node(原来的根结点) 就变成“根结点”的左孩子
|
||||||
|
temp->lchild = node;
|
||||||
|
//“根结点”的父亲更新为node(原来的根结点)的父亲
|
||||||
|
temp->father = node->father;
|
||||||
|
//node(原来的根结点)的父亲更新为“根结点”
|
||||||
|
node->father = temp;
|
||||||
|
//“根结点”的大小更新为node(原来的根结点)的大小(这里的大小是以该结点为根构成的树的结点的个数)
|
||||||
|
temp->size = node->size;
|
||||||
|
//node(原来的根结点)的大小更新为 它左孩子和右孩子的大小再在上本身1
|
||||||
|
node->size = node->lchild->size + node->rchild->size + 1;
|
||||||
|
//返回左旋后的根结点
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
//右旋:将左孩子变为“根结点”(当前子树的根结点),左孩子的右孩子就变成原来的根结点的左孩子
|
||||||
|
//下面注释中:node(原来的根结点)的左孩子用“根结点”来说
|
||||||
|
//反正这里跟上几乎相反
|
||||||
|
SBTNode * right_rotate(SBTNode * node) {
|
||||||
|
//用temp保存“根结点”
|
||||||
|
SBTNode * temp = node->lchild;
|
||||||
|
//“根结点”的右孩子 变成node(原来的根结点)的左孩子
|
||||||
|
node->lchild = temp->rchild;
|
||||||
|
//更新“根结点”原来的右孩子的父亲为node(原来的根结点)
|
||||||
|
temp->rchild->father = node;
|
||||||
|
//node(原来的根结点) 就变成“根结点”的右孩子
|
||||||
|
temp->rchild = node;
|
||||||
|
//“根结点”的父亲更新为node(原来的根结点)的父亲
|
||||||
|
temp->father = node->father;
|
||||||
|
//node(原来的根结点)的父亲更新为“根结点”
|
||||||
|
node->father = temp;
|
||||||
|
//“根结点”的大小更新为node(原来的根结点)的大小(这里的大小是以该结点为根构成的树的结点的个数)
|
||||||
|
temp->size = node->size;
|
||||||
|
//node(原来的根结点)的大小更新为 它左孩子和右孩子的大小再在上本身1
|
||||||
|
node->size = node->lchild->size + node->rchild->size + 1;
|
||||||
|
//返回右旋后的根结点
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
//利用上面的左右旋进行调整的函数
|
||||||
|
//flag为false:处理左子树更高的情况,否则处理右子树更高的情况
|
||||||
|
//node:要调整的子树的根结点
|
||||||
|
SBTNode * maintain(SBTNode * node, bool flag) {
|
||||||
|
//左子树比右子树高(或者叫深度要深)
|
||||||
|
if (flag == false) {
|
||||||
|
//LL型:左子树的左子树的元素个数大于右子树的元素个数,应进行右旋
|
||||||
|
if (node->lchild->lchild->size > node->rchild->size) {
|
||||||
|
//右旋并更新子树的根结点
|
||||||
|
node = right_rotate(node);
|
||||||
|
}
|
||||||
|
//LR型:左子树的右子树的元素个数大于右子树的元素个数
|
||||||
|
//那么先对左子树进行左旋,就变成LL型,再右旋即可
|
||||||
|
else if (node->lchild->rchild->size > node->rchild->size) {
|
||||||
|
//左旋并更新左子树的根结点
|
||||||
|
node->lchild = left_rotate(node->lchild);
|
||||||
|
//右旋并更新根节点
|
||||||
|
node = right_rotate(node);
|
||||||
|
} else {
|
||||||
|
//说明平衡了,返回根节点
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
//右子树比左子树高(或者叫深度要深)
|
||||||
|
} else {
|
||||||
|
//RR型:右子树的右子树的元素个数大于左子树的元素个数,应进行左旋
|
||||||
|
if (node->rchild->rchild->size > node->lchild->size) {
|
||||||
|
//左旋并更新根节点
|
||||||
|
node = left_rotate(node);
|
||||||
|
}
|
||||||
|
//RL型: 右子树的左子树的元素个数大于左子树的元素个数
|
||||||
|
//那么先对右子树进行右旋,变成RR型,在左旋即可
|
||||||
|
else if (node->rchild->lchild->size > node->lchild->size) {
|
||||||
|
//右旋并更新左子树的根结点
|
||||||
|
node->rchild = right_rotate(node->rchild);
|
||||||
|
//左旋并更新根节点
|
||||||
|
node = left_rotate(node);
|
||||||
|
} else {
|
||||||
|
//说明平衡了,返回根节点
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//下面为递归调用,因为有时上面的调整过后,左子树和右子树的某个结点还是不平衡
|
||||||
|
|
||||||
|
//递归调用,处理可能左子树的左子树高度更高的情况
|
||||||
|
//false表示左子树较高
|
||||||
|
node->lchild = maintain(node->lchild, false);
|
||||||
|
//其右子树的右子树高度更高的情况
|
||||||
|
node->rchild = maintain(node->rchild, true);
|
||||||
|
//最后再对子树根结点的左右子树递归进行调整
|
||||||
|
node = maintain(node, false);
|
||||||
|
node = maintain(node, true);
|
||||||
|
//返回调整后的子树的根结点
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
SBTNode * insert(SBTNode * node, int value) {
|
||||||
|
if (value == node->data) {
|
||||||
|
return node;
|
||||||
|
} else {
|
||||||
|
node->size++;
|
||||||
|
if (value > node->data) {
|
||||||
|
if (node->rchild == ZPTR) {
|
||||||
|
node->rchild = new SBTNode(value, 1, node);
|
||||||
|
} else {
|
||||||
|
node->rchild = insert(node->rchild, value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (node->lchild == ZPTR) {
|
||||||
|
node->lchild = new SBTNode(value, 1, node);
|
||||||
|
} else {
|
||||||
|
node->lchild = insert(node->lchild, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maintain(node, value > node->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
SBTNode * SBTNode::search(int value) {
|
||||||
|
if (data == value) {
|
||||||
|
return this;
|
||||||
|
} else if (value > data) {
|
||||||
|
if (rchild == ZPTR) {
|
||||||
|
return ZPTR;
|
||||||
|
} else {
|
||||||
|
return rchild->search(value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (lchild == ZPTR) {
|
||||||
|
return ZPTR;
|
||||||
|
} else {
|
||||||
|
return lchild->search(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SBTNode * SBTNode::predecessor() {
|
||||||
|
SBTNode * temp = lchild;
|
||||||
|
while (temp != ZPTR && temp->rchild != ZPTR) {
|
||||||
|
temp = temp->rchild;
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
SBTNode * SBTNode::successor() {
|
||||||
|
SBTNode * temp = rchild;
|
||||||
|
while (temp != ZPTR && temp->lchild != ZPTR) {
|
||||||
|
temp = temp->lchild;
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SBTNode::remove_node(SBTNode * delete_node) {
|
||||||
|
SBTNode * temp = ZPTR;
|
||||||
|
if (delete_node->lchild != ZPTR) {
|
||||||
|
temp = delete_node->lchild;
|
||||||
|
temp->father = delete_node->father;
|
||||||
|
delete_node->lchild = ZPTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delete_node->rchild != ZPTR) {
|
||||||
|
temp = delete_node->rchild;
|
||||||
|
temp->father = delete_node->father;
|
||||||
|
delete_node->rchild = ZPTR;
|
||||||
|
}
|
||||||
|
if (delete_node->father->lchild == delete_node) {
|
||||||
|
delete_node->father->lchild = temp;
|
||||||
|
} else {
|
||||||
|
delete_node->father->rchild = temp;
|
||||||
|
}
|
||||||
|
temp = delete_node;
|
||||||
|
while (temp != NULL) {
|
||||||
|
temp->size--;
|
||||||
|
temp = temp->father;
|
||||||
|
}
|
||||||
|
delete delete_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SBTNode::remove(int value) {
|
||||||
|
SBTNode * delete_node, * current_node;
|
||||||
|
current_node = search(value);
|
||||||
|
if (current_node == ZPTR) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
size--;
|
||||||
|
if (current_node->lchild != ZPTR) {
|
||||||
|
delete_node = current_node->predecessor();
|
||||||
|
} else if (current_node->rchild != ZPTR) {
|
||||||
|
delete_node = current_node->successor();
|
||||||
|
} else {
|
||||||
|
delete_node = current_node;
|
||||||
|
}
|
||||||
|
current_node->data = delete_node->data;
|
||||||
|
remove_node(delete_node);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SBTNode::select(int k) {
|
||||||
|
//rank表示当前结点在子树的排位
|
||||||
|
int rank = lchild->size + 1;
|
||||||
|
//若rank等于第k小的k,说明就是要找的值,直接返回权值即可
|
||||||
|
if (rank == k) {
|
||||||
|
return data;
|
||||||
|
}else if (k < rank) {
|
||||||
|
//小于rank,就表明要找比当前结点更小的,就在左边查找
|
||||||
|
return lchild->select(k);
|
||||||
|
}else{
|
||||||
|
//大于就在右边咯
|
||||||
|
//这里为什么看k - rank呢,因为我们已经把前rank排除了,
|
||||||
|
//相当于我们要在右子树(把他当做一颗新的树去查找),所以排位当然要减去rank了
|
||||||
|
return rchild->select(k - rank);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryTree::BinaryTree() {
|
||||||
|
root = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
BinaryTree::~BinaryTree() {
|
||||||
|
if (root != NULL) {
|
||||||
|
delete root;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BinaryTree::insert(int value) {
|
||||||
|
if (root == NULL) {
|
||||||
|
//初始化时只有根结点,所以子树大小为1
|
||||||
|
root = new SBTNode(value, 1);
|
||||||
|
} else {
|
||||||
|
root = ::insert(root, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryTree::find(int value) {
|
||||||
|
if (root->search(value) == NULL) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BinaryTree::remove(int value) {
|
||||||
|
return root->remove(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int BinaryTree::select(int k) {
|
||||||
|
return root->select(k);
|
||||||
|
}
|
493
src/vbtree.h
Normal file
493
src/vbtree.h
Normal file
|
@ -0,0 +1,493 @@
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <tuple>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using std::cout, std::endl;
|
||||||
|
using std::tuple, std::make_tuple;
|
||||||
|
|
||||||
|
typedef unsigned long ULONG;
|
||||||
|
|
||||||
|
template <class TKey, class TValue>
|
||||||
|
class VBTree
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef int (*Compare)(TKey, TKey);
|
||||||
|
struct TreeNode
|
||||||
|
{
|
||||||
|
TreeNode *children[2];
|
||||||
|
TreeNode *parent;
|
||||||
|
unsigned long size;
|
||||||
|
TKey key;
|
||||||
|
TValue value;
|
||||||
|
|
||||||
|
TreeNode()
|
||||||
|
{
|
||||||
|
this->children[0] = NULL;
|
||||||
|
this->children[1] = NULL;
|
||||||
|
this->parent = NULL;
|
||||||
|
this->size = 1;
|
||||||
|
}
|
||||||
|
/* data */
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
TreeNode *root;
|
||||||
|
Compare compare;
|
||||||
|
ULONG getSize(TreeNode *cur)
|
||||||
|
{
|
||||||
|
if (cur == NULL)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return cur->size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ULONG getChildrenSumSize(TreeNode *cur)
|
||||||
|
{
|
||||||
|
return this->getSize(cur->children[0]) + this->getSize(cur->children[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tuple<ULONG, ULONG> getChildrenSize(TreeNode *cur)
|
||||||
|
{
|
||||||
|
return make_tuple(this->getSize(cur->children[0]), this->getSize(cur->children[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap_node_kv(TreeNode *n1, TreeNode *n2)
|
||||||
|
{
|
||||||
|
TKey tempkey = n1->key;
|
||||||
|
TValue tempvalue = n1->value;
|
||||||
|
|
||||||
|
n1->key = n2->key; //交换值达到, 相对位移
|
||||||
|
n1->value = n2->value;
|
||||||
|
|
||||||
|
n2->key = tempkey;
|
||||||
|
n2->value = tempvalue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lrrotate3(TreeNode *cur)
|
||||||
|
{
|
||||||
|
const int l = 1;
|
||||||
|
const int r = 0;
|
||||||
|
|
||||||
|
TreeNode *movparent = cur->children[l];
|
||||||
|
TreeNode *mov = movparent->children[r];
|
||||||
|
|
||||||
|
this->swap_node_kv(mov, cur);
|
||||||
|
|
||||||
|
cur->children[r] = mov;
|
||||||
|
mov->parent = cur;
|
||||||
|
|
||||||
|
cur->children[l] = movparent;
|
||||||
|
movparent->children[r] = NULL;
|
||||||
|
|
||||||
|
cur->children[r] = mov;
|
||||||
|
mov->parent = cur;
|
||||||
|
|
||||||
|
cur->children[l]->size = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lrrotate(TreeNode *cur)
|
||||||
|
{
|
||||||
|
|
||||||
|
const int l = 1;
|
||||||
|
const int r = 0;
|
||||||
|
|
||||||
|
TreeNode *movparent = cur->children[l];
|
||||||
|
TreeNode *mov = movparent->children[r];
|
||||||
|
|
||||||
|
this->swap_node_kv(mov, cur); //交换值达到, 相对位移
|
||||||
|
|
||||||
|
if (mov->children[l] != NULL)
|
||||||
|
{
|
||||||
|
movparent->children[r] = mov->children[l];
|
||||||
|
movparent->children[r]->parent = movparent;
|
||||||
|
//movparent->children[r].child = l
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
movparent->children[r] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mov->children[r] != NULL)
|
||||||
|
{
|
||||||
|
mov->children[l] = mov->children[r];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mov->children[l] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur->children[r] != NULL)
|
||||||
|
{
|
||||||
|
mov->children[r] = cur->children[r];
|
||||||
|
mov->children[r]->parent = mov;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mov->children[r] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur->children[r] = mov;
|
||||||
|
mov->parent = cur;
|
||||||
|
|
||||||
|
movparent->size = getChildrenSumSize(movparent) + 1;
|
||||||
|
mov->size = getChildrenSumSize(mov) + 1;
|
||||||
|
cur->size = getChildrenSumSize(cur) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rlrotate3(TreeNode *cur)
|
||||||
|
{
|
||||||
|
const int l = 0;
|
||||||
|
const int r = 1;
|
||||||
|
|
||||||
|
TreeNode *movparent = cur->children[l];
|
||||||
|
TreeNode *mov = movparent->children[r];
|
||||||
|
|
||||||
|
this->swap_node_kv(mov, cur);
|
||||||
|
|
||||||
|
cur->children[r] = mov;
|
||||||
|
mov->parent = cur;
|
||||||
|
|
||||||
|
cur->children[l] = movparent;
|
||||||
|
movparent->children[r] = NULL;
|
||||||
|
|
||||||
|
cur->children[r] = mov;
|
||||||
|
mov->parent = cur;
|
||||||
|
|
||||||
|
cur->children[l]->size = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rlrotate(TreeNode *cur)
|
||||||
|
{
|
||||||
|
const int l = 0;
|
||||||
|
const int r = 1;
|
||||||
|
|
||||||
|
TreeNode *movparent = cur->children[l];
|
||||||
|
TreeNode *mov = movparent->children[r];
|
||||||
|
|
||||||
|
this->swap_node_kv(mov, cur);
|
||||||
|
|
||||||
|
if (mov->children[l] != NULL)
|
||||||
|
{
|
||||||
|
movparent->children[r] = mov->children[l];
|
||||||
|
movparent->children[r]->parent = movparent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
movparent->children[r] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mov->children[r] != NULL)
|
||||||
|
{
|
||||||
|
mov->children[l] = mov->children[r];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mov->children[l] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur->children[r] != NULL)
|
||||||
|
{
|
||||||
|
mov->children[r] = cur->children[r];
|
||||||
|
mov->children[r]->parent = mov;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mov->children[r] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur->children[r] = mov;
|
||||||
|
mov->parent = cur;
|
||||||
|
|
||||||
|
movparent->size = this->getChildrenSumSize(movparent) + 1;
|
||||||
|
mov->size = this->getChildrenSumSize(mov) + 1;
|
||||||
|
cur->size = this->getChildrenSumSize(cur) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rrotate3(TreeNode *cur)
|
||||||
|
{
|
||||||
|
const int l = 0;
|
||||||
|
const int r = 1;
|
||||||
|
// 1 right 0 left
|
||||||
|
TreeNode *mov = cur->children[l];
|
||||||
|
|
||||||
|
this->swap_node_kv(mov, cur);
|
||||||
|
|
||||||
|
cur->children[r] = mov;
|
||||||
|
|
||||||
|
cur->children[l] = mov->children[l];
|
||||||
|
cur->children[l]->parent = cur;
|
||||||
|
|
||||||
|
mov->children[l] = NULL;
|
||||||
|
|
||||||
|
mov->size = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rrotate(TreeNode *cur)
|
||||||
|
{
|
||||||
|
|
||||||
|
const int l = 0;
|
||||||
|
const int r = 1;
|
||||||
|
// 1 right 0 left
|
||||||
|
TreeNode *mov = cur->children[l];
|
||||||
|
|
||||||
|
this->swap_node_kv(mov, cur);
|
||||||
|
|
||||||
|
// mov->children[l]不可能为nil
|
||||||
|
mov->children[l]->parent = cur;
|
||||||
|
|
||||||
|
cur->children[l] = mov->children[l];
|
||||||
|
|
||||||
|
// 解决mov节点孩子转移的问题
|
||||||
|
if (mov->children[r] != NULL)
|
||||||
|
{
|
||||||
|
mov->children[l] = mov->children[r];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mov->children[l] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur->children[r] != NULL)
|
||||||
|
{
|
||||||
|
mov->children[r] = cur->children[r];
|
||||||
|
mov->children[r]->parent = mov;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mov->children[r] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 连接转移后的节点 由于mov只是与cur交换值,parent不变
|
||||||
|
cur->children[r] = mov;
|
||||||
|
|
||||||
|
mov->size = getChildrenSumSize(mov) + 1;
|
||||||
|
cur->size = getChildrenSumSize(cur) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lrotate3(TreeNode *cur)
|
||||||
|
{
|
||||||
|
const int l = 1;
|
||||||
|
const int r = 0;
|
||||||
|
// 1 right 0 left
|
||||||
|
TreeNode *mov = cur->children[l];
|
||||||
|
|
||||||
|
this->swap_node_kv(cur, mov);
|
||||||
|
|
||||||
|
cur->children[r] = mov;
|
||||||
|
|
||||||
|
cur->children[l] = mov->children[l];
|
||||||
|
cur->children[l]->parent = cur;
|
||||||
|
|
||||||
|
mov->children[l] = NULL;
|
||||||
|
|
||||||
|
mov->size = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void lrotate(TreeNode *cur)
|
||||||
|
{
|
||||||
|
|
||||||
|
const int l = 1;
|
||||||
|
const int r = 0;
|
||||||
|
// 1 right 0 left
|
||||||
|
TreeNode *mov = cur->children[l];
|
||||||
|
|
||||||
|
this->swap_node_kv(cur, mov);
|
||||||
|
|
||||||
|
// mov->children[l]不可能为nil
|
||||||
|
mov->children[l]->parent = cur;
|
||||||
|
|
||||||
|
cur->children[l] = mov->children[l];
|
||||||
|
|
||||||
|
// 解决mov节点孩子转移的问题
|
||||||
|
if (mov->children[r] != NULL)
|
||||||
|
{
|
||||||
|
mov->children[l] = mov->children[r];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mov->children[l] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur->children[r] != NULL)
|
||||||
|
{
|
||||||
|
mov->children[r] = cur->children[r];
|
||||||
|
mov->children[r]->parent = mov;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mov->children[r] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 连接转移后的节点 由于mov只是与cur交换值,parent不变
|
||||||
|
cur->children[r] = mov;
|
||||||
|
|
||||||
|
mov->size = getChildrenSumSize(mov) + 1;
|
||||||
|
cur->size = getChildrenSumSize(cur) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fixSize(TreeNode *cur, ULONG ls, ULONG rs)
|
||||||
|
{
|
||||||
|
if (ls > rs)
|
||||||
|
{
|
||||||
|
tuple<ULONG, ULONG> lllr = this->getChildrenSize(cur->children[0]);
|
||||||
|
ULONG llsize = std::get<0>(lllr);
|
||||||
|
ULONG lrsize = std::get<1>(lllr);
|
||||||
|
if (lrsize > llsize)
|
||||||
|
{
|
||||||
|
this->rlrotate(cur);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->rrotate(cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tuple<ULONG, ULONG> rlrr = this->getChildrenSize(cur->children[1]);
|
||||||
|
ULONG rlsize = std::get<0>(rlrr);
|
||||||
|
ULONG rrsize = std::get<1>(rlrr);
|
||||||
|
if (rlsize > rrsize)
|
||||||
|
{
|
||||||
|
this->lrrotate(cur);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->lrotate(cur);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
VBTree(Compare compare)
|
||||||
|
{
|
||||||
|
this->compare = compare;
|
||||||
|
this->root = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
TValue* get(TKey key)
|
||||||
|
{
|
||||||
|
for (TreeNode *n = this->root; n != NULL;)
|
||||||
|
{
|
||||||
|
int c = this->compare(key, n->key);
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
n = n->children[0];
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
n = n->children[1];
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
return &n->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void put(TKey key, TValue value)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (this->root == NULL)
|
||||||
|
{
|
||||||
|
TreeNode *node = new TreeNode();
|
||||||
|
node->key = key;
|
||||||
|
node->value = value;
|
||||||
|
this->root = node;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<TreeNode*> vsize;
|
||||||
|
|
||||||
|
for (TreeNode *cur = this->root;;)
|
||||||
|
{
|
||||||
|
if (cur->size > 8)
|
||||||
|
{
|
||||||
|
unsigned long factor = cur->size / 10;
|
||||||
|
unsigned long ls = cur->children[0]->size;
|
||||||
|
unsigned long rs = cur->children[1]->size;
|
||||||
|
if (rs >= ls * 2 + factor || ls >= rs * 2 + factor)
|
||||||
|
{
|
||||||
|
this->fixSize(cur, ls, rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// cur->size++;
|
||||||
|
vsize.push_back(cur);
|
||||||
|
|
||||||
|
int c = this->compare(key, cur->key);
|
||||||
|
if (c < 0)
|
||||||
|
{
|
||||||
|
if (cur->children[0] == NULL)
|
||||||
|
{
|
||||||
|
TreeNode *node = new TreeNode();
|
||||||
|
node->key = key;
|
||||||
|
node->value = value;
|
||||||
|
|
||||||
|
for (auto iter = vsize.begin(); iter != vsize.end();iter++) {
|
||||||
|
(*iter)->size ++ ;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur->children[0] = node;
|
||||||
|
node->parent = cur;
|
||||||
|
|
||||||
|
if (cur->parent != NULL && cur->parent->size == 3)
|
||||||
|
{
|
||||||
|
if (cur->parent->children[0] == NULL)
|
||||||
|
{
|
||||||
|
this->lrrotate3(cur->parent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->rrotate3(cur->parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cur = cur->children[0];
|
||||||
|
}
|
||||||
|
else if (c > 0)
|
||||||
|
{
|
||||||
|
if (cur->children[1] == NULL)
|
||||||
|
{
|
||||||
|
TreeNode *node = new TreeNode();
|
||||||
|
node->key = key;
|
||||||
|
node->value = value;
|
||||||
|
|
||||||
|
for (auto iter = vsize.begin(); iter != vsize.end();iter++) {
|
||||||
|
(*iter)->size ++ ;
|
||||||
|
}
|
||||||
|
|
||||||
|
cur->children[1] = node;
|
||||||
|
node->parent = cur;
|
||||||
|
|
||||||
|
if (cur->parent != NULL && cur->parent->size == 3)
|
||||||
|
{
|
||||||
|
if (cur->parent->children[1] == NULL)
|
||||||
|
{
|
||||||
|
this->rlrotate3(cur->parent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->lrotate3(cur->parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cur = cur->children[1];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cur->key = key;
|
||||||
|
cur->value = value;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* data */
|
||||||
|
};
|
|
@ -1,80 +0,0 @@
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
using std::cout, std::endl;
|
|
||||||
|
|
||||||
template <class TKey, class TValue>
|
|
||||||
class VBTree
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
typedef struct Node
|
|
||||||
{
|
|
||||||
Node *children[2];
|
|
||||||
Node *parent;
|
|
||||||
unsigned long size;
|
|
||||||
TKey key;
|
|
||||||
TValue value;
|
|
||||||
/* data */
|
|
||||||
} ;
|
|
||||||
|
|
||||||
public:
|
|
||||||
void put(TKey key, TValue value) {
|
|
||||||
Node *node = new Node();
|
|
||||||
}
|
|
||||||
|
|
||||||
// if tree.root == nil {
|
|
||||||
// tree.root = node
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// for cur := tree.root; ; {
|
|
||||||
|
|
||||||
// if cur.size > 8 {
|
|
||||||
// factor := cur.size / 10 // or factor = 1
|
|
||||||
// ls, rs := cur.children[0].size, cur.children[1].size
|
|
||||||
// if rs >= ls*2+factor || ls >= rs*2+factor {
|
|
||||||
// tree.fixSize(cur, ls, rs)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// cur.size++
|
|
||||||
|
|
||||||
// c := tree.Compare(key, cur.key)
|
|
||||||
// if c < 0 {
|
|
||||||
// if cur.children[0] == nil {
|
|
||||||
// cur.children[0] = node
|
|
||||||
// node.parent = cur
|
|
||||||
|
|
||||||
// if cur.parent != nil && cur.parent.size == 3 {
|
|
||||||
// if cur.parent.children[0] == nil {
|
|
||||||
// tree.lrrotate3(cur.parent)
|
|
||||||
// } else {
|
|
||||||
// tree.rrotate3(cur.parent)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// cur = cur.children[0]
|
|
||||||
// } else {
|
|
||||||
// if cur.children[1] == nil {
|
|
||||||
// cur.children[1] = node
|
|
||||||
// node.parent = cur
|
|
||||||
|
|
||||||
// if cur.parent != nil && cur.parent.size == 3 {
|
|
||||||
// if cur.parent.children[1] == nil {
|
|
||||||
// tree.rlrotate3(cur.parent)
|
|
||||||
// } else {
|
|
||||||
// tree.lrotate3(cur.parent)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// cur = cur.children[1]
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
/* data */
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user