性能测试完毕

This commit is contained in:
huangsimin 2019-08-02 18:32:55 +08:00
parent d0ff4d309b
commit 64e0c379a5
4 changed files with 937 additions and 97 deletions

View File

@ -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
View 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
View 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 */
};

View File

@ -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 */
};