diff --git a/main.cpp b/main.cpp index e1dc982..7e39466 100644 --- a/main.cpp +++ b/main.cpp @@ -4,6 +4,8 @@ #include #include +#include "treap.hpp" + using std::string; using std::vector; @@ -12,16 +14,16 @@ enum mode_type { insert, normal }; // Global variables -vector 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; } diff --git a/treap.hpp b/treap.hpp new file mode 100644 index 0000000..2f14e46 --- /dev/null +++ b/treap.hpp @@ -0,0 +1,115 @@ +#include +#include +#include + +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 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); + } +};