性能测试完毕
This commit is contained in:
parent
d0ff4d309b
commit
64e0c379a5
147
src/main.cpp
147
src/main.cpp
|
@ -2,35 +2,148 @@
|
|||
#include <map>
|
||||
#include <chrono>
|
||||
#include <random>
|
||||
#include "vbtree.h"
|
||||
#include "sbt.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
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()
|
||||
{
|
||||
std::map<int, int> m;
|
||||
|
||||
std::map<int, int> m;
|
||||
|
||||
default_random_engine e;
|
||||
std::uniform_int_distribution<> dist{0, 1000000000};
|
||||
double N = 1000000;
|
||||
default_random_engine e;
|
||||
std::uniform_int_distribution<> dist{0, 1000000000};
|
||||
|
||||
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++)
|
||||
{
|
||||
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;
|
||||
std::cout << (t2 - t1).count() / N << std::endl;
|
||||
std::cout << "end RBTree Case Benchmark" << std::endl;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
Case1();
|
||||
void Case1_1()
|
||||
{
|
||||
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