zeed/treap.cpp

132 lines
2.8 KiB
C++

#include "everything.hpp"
// Treap representation of a file
line* root;
// Get size uf a subtreap
count_type Treap::get_size(line* l) {
if(l == nullptr) return 0;
return l->size;
}
// Split treap by k-th element
two_lines Treap::split(line *l, count_type k) {
if(l == nullptr) return {nullptr, nullptr};
if(get_size(l->left) >= k) {
// In the left subtree
auto two = split(l->left, k);
l->left = two.second;
l->size -= get_size(two.first);
return {two.first, l};
}
else {
// In the right subtree
auto two = split(l->right, k - (1+get_size(l->left)));
l->right = two.first;
l->size -= get_size(two.second);
return {l, two.second};
}
}
// Join two treaps
line* Treap::join(line *a, line *b) {
if(a == nullptr) return b;
if(b == nullptr) return a;
if(a->priority < b->priority) {
a->size += get_size(b);
a->right = join(a->right, b);
return a;
}
else {
b->size += get_size(a);
b->left = join(a, b->left);
return b;
}
}
// Find k-th line of file
line* Treap::find(line* l, count_type k) {
if(l == nullptr) return nullptr;
if(k <= get_size(l->left))
return find(l->left, k);
else if(k == get_size(l->left)+1)
return l;
else
return find(l->right, k - (1+get_size(l->left)) );
}
// File access
line* Treap::find(count_type k) {
if(k >= root->size)
return nullptr;
// Don't find index k, but k-th line -> +1
return find(root, k+1);
}
void Treap::clear() {
while(size() > 0) {
auto two = split(root, 1);
root = two.second;
delete two.first;
}
}
// Line insert
void Treap::insert(count_type k, string s) {
line *l = new line(rand(), s);
if(root == nullptr) {
root = l;
return;
}
auto two = split(root, k);
two.first = join(two.first, l);
root = join(two);
}
// Line removal
void Treap::remove(count_type k) {
auto two = split(root, k+1);
auto first_split = split(two.first, k);
delete first_split.second;
two.first = first_split.first;
root = join(two);
}
// Accessing the file
string Treap::get_line(count_type r, bool substitute_tab) {
string line = get(r);
if(!substitute_tab)
return line;
string ret = "";
for(count_type i = 0; i < line.size(); ++i) {
if(line[i] == '\t')
for(int j = 0; j < TAB_SIZE; j++)
ret += ' ';
else
ret += line[i];
}
return ret;
}
count_type Treap::get_tab_offset(position p) {
count_type tab_offset = 0;
string line = get_line(p.r, false);
for(count_type i = 0; i + tab_offset < p.c; ++i) {
if(line[i] == '\t')
tab_offset += TAB_SIZE - 1;
if(i + tab_offset > p.c)
tab_offset -= i + tab_offset - p.c;
}
return tab_offset;
}
void Treap::set(position p, char ch) {
find(p.r)->text[p.c-get_tab_offset(p)] = ch;
}
void Treap::insert(position p, string t) {
find(p.r)->text.insert(p.c-get_tab_offset(p), t);
}
void Treap::remove(position p, count_type len) {
find(p.r)->text.erase(p.c-get_tab_offset(p),len);
}