Merge branch 'treap'
This commit is contained in:
commit
6942a0cf01
2 changed files with 130 additions and 12 deletions
27
main.cpp
27
main.cpp
|
@ -4,6 +4,8 @@
|
|||
#include <vector>
|
||||
#include <fstream>
|
||||
|
||||
#include "treap.hpp"
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
|
@ -12,16 +14,16 @@ enum mode_type { insert, normal };
|
|||
|
||||
|
||||
// Global variables
|
||||
vector<string> file(0);
|
||||
treap file;
|
||||
int row = 0, col = 0;
|
||||
|
||||
// Accessing the file
|
||||
char get(int r, int s) { return file[r][s]; }
|
||||
void set(int r, int s, char ch) { file[r][s] = ch; }
|
||||
void insert_char(int r, int s, char ch) { file[r].insert(s, string{ch}); }
|
||||
string get_line(int r) { return file[r]; }
|
||||
void add_line(int r) { file.insert(file.begin() + r, ""); }
|
||||
void remove_line(int r) { file.erase(file.begin() + r); }
|
||||
string get_line(int r) { return file.find(r)->text; }
|
||||
char get(int r, int s) { return get_line(r)[s]; }
|
||||
void set(int r, int s, char ch) { file.find(r)->text[s] = ch; }
|
||||
void add_line(int r, string text = "") { file.insert(r, text); }
|
||||
void remove_line(int r) { file.remove(r); }
|
||||
void insert_char(int r, int s, char ch) { file.find(r)->text.insert(s, string{ch}); }
|
||||
|
||||
// For normal mode not to write to terminal
|
||||
void step_back() {
|
||||
|
@ -37,9 +39,10 @@ bool load(string filename) {
|
|||
std::ifstream infile(filename);
|
||||
if(!infile.good())
|
||||
return 1;
|
||||
|
||||
string line;
|
||||
while (std::getline(infile, line))
|
||||
file.push_back(line);
|
||||
file.insert(file.size(), line);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -48,8 +51,8 @@ bool save(string filename) {
|
|||
std::ofstream outfile(filename);
|
||||
if(!outfile.good())
|
||||
return 1;
|
||||
for(string line : file)
|
||||
outfile << line << std::endl;
|
||||
for(int i = 0; i < file.size(); ++i)
|
||||
outfile << get_line(i) << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -58,7 +61,7 @@ void print_file() {
|
|||
clear();
|
||||
for(int i = 0; i < file.size(); i++) {
|
||||
move(i, 0);
|
||||
adds(file[i]);
|
||||
adds(get_line(i));
|
||||
}
|
||||
move(row, col);
|
||||
}
|
||||
|
@ -110,7 +113,7 @@ void move_cursor(char ch) {
|
|||
break;
|
||||
|
||||
case 'l':
|
||||
if(col < file[row].size())
|
||||
if(col < get_line(row).size())
|
||||
move(row, ++col);
|
||||
break;
|
||||
}
|
||||
|
|
115
treap.hpp
Normal file
115
treap.hpp
Normal file
|
@ -0,0 +1,115 @@
|
|||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <utility>
|
||||
|
||||
using std::string;
|
||||
typedef unsigned long long count_type;
|
||||
|
||||
// Treap node representation of a line
|
||||
struct line {
|
||||
count_type priority, size;
|
||||
string text;
|
||||
line *left, *right;
|
||||
|
||||
line(count_type _p, string _t) : priority(_p), text(_t), size(1), left(nullptr), right(nullptr) {}
|
||||
};
|
||||
typedef std::pair<line*, line*> two_lines;
|
||||
|
||||
// Treap representation of a file
|
||||
class treap {
|
||||
line* root;
|
||||
|
||||
// Get size uf a subtreap
|
||||
int get_size(line* l) {
|
||||
if(l == nullptr) return 0;
|
||||
return l->size;
|
||||
}
|
||||
|
||||
// Split treap by k-th element
|
||||
// Hopefully with sizes
|
||||
two_lines 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
|
||||
// Hopefully with working sizes
|
||||
line* 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;
|
||||
}
|
||||
}
|
||||
line* join(two_lines two) { return join(two.first, two.second); }
|
||||
|
||||
// Find k-th line of file
|
||||
line* 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)) );
|
||||
}
|
||||
|
||||
public:
|
||||
treap() {
|
||||
srand(120);
|
||||
root = nullptr;
|
||||
}
|
||||
// File access
|
||||
line* 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);
|
||||
}
|
||||
|
||||
// Line insert
|
||||
void insert(int 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 remove(count_type k) {
|
||||
auto two = split(root, k+1);
|
||||
two.first = split(two.first, k).first;
|
||||
root = join(two);
|
||||
}
|
||||
count_type size() {
|
||||
return get_size(root);
|
||||
}
|
||||
};
|
Loading…
Reference in a new issue