Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,13 @@
include_dirs = ['../src/streamingcc_include/'],
extra_compile_args=['-std=c++11'],
language='c++'
),
Extension(
'streamingcc._treap',
sources=['streamingcc/_treap.pyx'] + all_cc_files,
include_dirs = ['../src/streamingcc_include/'],
extra_compile_args=['-std=c++11'],
language='c++'
)
]

Expand Down
19 changes: 19 additions & 0 deletions python/streamingcc/_treap.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# distutils: language = c++
# distutils: sources = ../src/treap.cc
from libcpp cimport bool

cdef extern from "../../src/streamingcc_include/treap.h" namespace "streamingcc":
cdef cppclass Treap:
Treap() except +
void insert(int val)
bool contains(int val)

cdef class PyTreap:
cdef Treap treap
def __cint__(self):
self.treap = Treap()
def insert(self, val):
self.treap.insert(val)
def contains(self, val):
self.treap.contains(val)

13 changes: 13 additions & 0 deletions python/streamingcc/treap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import streamingcc._treap as _treap

Treap = _treap.PyTreap

class TP:
def __init__(self):
self._tp = Treap()

def insert(self, val):
self._tp.insert(val)

def contains(self, val):
self._tp.contains(val)
1 change: 1 addition & 0 deletions src/streamingcc
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@
#include "streamingcc_include/sampling.h"
#include "streamingcc_include/bloom_filter.h"
#include "streamingcc_include/hyper_loglog.h"
#include "streamingcc_include/treap.h"

#endif // SRC_STREAMINGCC
71 changes: 71 additions & 0 deletions src/streamingcc_include/treap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright 2019 Yan Song

#ifndef SRC_STREAMINGCC_INCLUDE_TREAP_H_
#define SRC_STREAMINGCC_INCLUDE_TREAP_H_

#include "../streamingcc_include/util.h"

namespace streamingcc {

template <typename T>
// struct for tree node to store single data of
// any comparable type
struct treeNode {
public:
treeNode* parent;
treeNode* lc;
treeNode* rc;
T value;
int height;
double priority;

// Constructor
treeNode() {
parent = nullptr;
lc = nullptr;
rc = nullptr;
height = 0;
}
};

template <typename T>
class Treap {
// Private data in treap
treeNode<T>* root;
int _size;

// Private operations
// Rotation
void rotate(treeNode<T>* tn);
void rotate_left(treeNode<T>* tn);
void rotate_right(treeNode<T>* tn);

// Underlying insertion and searching
treeNode<T>* insert(treeNode<T>* tn, T val);
bool contains(treeNode<T>* tn, T val);

// Helper functions
void assignPriority(treeNode<T>* tn);
void updateHeight(treeNode<T>* tn);
void adjustPriority(treeNode<T>* tn);

// Clear treap
void destroyRecursive(treeNode<T>* tn);

public:
// Constructor
Treap() {
root = new treeNode<T>();
_size = 0;
}
// Destructor
~Treap() { destroyRecursive(this->root); }

void insert(T val) { insert(this->root, val); }
bool contains(T val) { return contains(this->root, val); }
};


} // namespace streamingcc
#endif // SRC_STREAMINGCC_INCLUDE_TREAP_H_

185 changes: 185 additions & 0 deletions src/treap.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
// Copyright 2019 Yan Song

#include "streamingcc_include/treap.h"

using streamingcc::util::rand_double;

namespace streamingcc {

// Underlying insertion and searching
template <typename T>
bool Treap<T>::contains(treeNode<T>* tn, T val) {
// base case
if (tn == nullptr) return false;
// hit
if (tn->value == val) return true;
// Go to left subtree
if (tn->value > val) return contains(tn->lc, val);
// Go to right subtree
return contains(tn->rc, val);
}

template <typename T>
treeNode<T>* Treap<T>::insert(treeNode<T>* tn, T val) {
// Empty tree
if (_size == 0) {
root->value = val;
assignPriority(root);
_size++;
return root;
}

// Insert to the left
if (tn->value >= val) {
if (tn->lc == nullptr) {
// Create a new left child
treeNode<T>* nlc = new treeNode<T>();
_size++;
assignPriority(nlc);
nlc->value = val;
// Connect nlc to tree
nlc->parent = tn;
tn->lc = nlc;
// Adjust height and priority
nlc->height = 0;
updateHeight(tn);
adjustPriority(nlc);
return nlc;
}
return insert(tn->lc, val);
}

// Insert to the right
if (tn->rc == nullptr) {
// Create a new right child
treeNode<T>* nrc = new treeNode<T>();
_size++;
assignPriority(nrc);
nrc->value = val;
// Connect nrc to tree
nrc->parent = tn;
tn->rc = nrc;
// Adjust height
nrc->height = 0;
updateHeight(tn);
adjustPriority(nrc);
return nrc;
}
return insert(tn->rc, val);
}

// Rotation
template <typename T>
void Treap<T>::rotate(treeNode<T> *tn) {
if (tn->parent == nullptr) return;
if (tn->parent->lc == tn) return rotate_right(tn);
return rotate_left(tn);
}

template <typename T>
void Treap<T>::rotate_left(treeNode<T> *y) {
treeNode<T>* x = y->parent;
treeNode<T>* z = y->lc;

// Take care of x's parent
if (x->parent == nullptr) {
this->root = y;
} else if (x->parent->lc == x) {
x->parent->lc = y;
} else {
x->parent->rc = y;
}

// work on y
y->parent = x->parent;
y->lc = x;

// work on x
x->parent = y;
x->rc = z;

// work on z
if (z != nullptr) z->parent = x;

updateHeight(y);
updateHeight(x);
}

template <typename T>
void Treap<T>::rotate_right(treeNode<T> *x) {
treeNode<T>* y = x->parent;
treeNode<T>* z = x->rc;

// Take care of y's parent
if (y->parent == nullptr) {
this->root = x;
} else if (y->parent->lc == y) {
y->parent->lc = x;
} else {
y->parent->rc = x;
}

// work on x
x->parent = y->parent;
x->rc = y;

// work on y
y->parent = x;
y->lc = z;

// work on z
if (z != nullptr) z->parent = y;

updateHeight(x);
updateHeight(y);
}

// Helper functions
template <typename T>
void Treap<T>::updateHeight(treeNode<T> *tn) {
if (tn == nullptr) return;

int oldHeight = tn->height;
int newHeight = 0;
if (tn->lc == nullptr && tn->rc == nullptr) newHeight = 0;
else if (tn->lc == nullptr) newHeight = tn->rc->height + 1;
else if (tn->rc == nullptr) newHeight = tn->lc->height + 1;
else if (tn->lc->height > tn->rc->height)
newHeight = tn->lc->height + 1;
else
newHeight = tn->rc->height + 1;

if (newHeight == oldHeight) {
return;
} else {
tn->height = newHeight;
updateHeight(tn->parent);
}
}

template <typename T>
void Treap<T>::adjustPriority(treeNode<T> *x) {
while (x->parent != nullptr && x->priority > x->parent->priority) {
rotate(x);
}
}

template <typename T>
void Treap<T>::assignPriority(treeNode<T>* tn) {
double randomPriority = rand_double(1.0);
if (static_cast<int>(randomPriority) == 1) assignPriority(tn);
else
tn->priority = randomPriority;
}

template <typename T>
void Treap<T>::destroyRecursive(treeNode<T>* tn) {
if (tn == nullptr)
return;

destroyRecursive(tn->lc);
destroyRecursive(tn->rc);
delete tn;
}

} // namespace streamingcc
45 changes: 45 additions & 0 deletions tests/treap_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright 2019 Yan Song

#include "../src/streamingcc_include/treap.h"
#include "../src/treap.cc"
#define BOOST_TEST_MODULE ClassTest
#define BOOST_TEST_DYN_LINK

#include <boost/test/unit_test.hpp>

using streamingcc::Treap;
using streamingcc::util::rand_int;

BOOST_AUTO_TEST_CASE(Treap_Test) {
int n = 100000;
Treap<int> treap;
// Insert 1e6 elements into treap
for (int i = 0; i < n; i++) {
treap.insert(i);
}

// Random select 5 elements to check
// if these elements are in treap
for (int i = 0; i < 5; i++) {
int j = rand_int(n);
BOOST_CHECK(treap.contains(j));
}
BOOST_CHECK(!treap.contains(n));
}

BOOST_AUTO_TEST_CASE(Treap_Test_Reverse) {
int n = 1000000;
Treap<int> treap;
// Insert 1e6 elements into treap
for (int i = n-1; i >= 0; i--) {
treap.insert(i);
}

// Random select 5 elements to check
// if these elements are in treap
for (int i = 0; i < 5; i++) {
int j = rand_int(n);
BOOST_CHECK(treap.contains(j));
}
BOOST_CHECK(!treap.contains(n));
}