mirror of
https://github.com/usatiuk/ficus.git
synced 2025-10-29 00:27:52 +01:00
Get rid of skip list set
This commit is contained in:
@@ -8,7 +8,6 @@
|
||||
#include "List.hpp"
|
||||
#include "PointersCollection.hpp"
|
||||
#include "SkipList.hpp"
|
||||
#include "SkipListSet.hpp"
|
||||
#include "String.hpp"
|
||||
#include "Vector.hpp"
|
||||
#include "assert.h"
|
||||
@@ -180,36 +179,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class SkipListSetTester {
|
||||
public:
|
||||
bool test() {
|
||||
SkipListSet<int> test1;
|
||||
|
||||
test1.add(5, false);
|
||||
test1.add(999, false);
|
||||
test1.add(5, false);
|
||||
test1.add(1, false);
|
||||
test1.add(999, false);
|
||||
|
||||
assert(test1.find(5)->key == 5);
|
||||
assert(test1.find(1)->key == 1);
|
||||
assert(test1.find(999)->key == 999);
|
||||
|
||||
test1.erase(1);
|
||||
assert(test1.find(1)->key != 1);
|
||||
test1.add(87, false);
|
||||
assert(test1.find(87)->key == 87);
|
||||
|
||||
auto p2 = test1.lower_bound_update(78);
|
||||
assert(p2->key == 87);
|
||||
test1.add(78, true);
|
||||
assert(test1.find(78)->key == 78);
|
||||
|
||||
// GlobalTtyManager.all_tty_putstr("SkipListSet tests ok!\n");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void test_unique_ptr() {
|
||||
UniquePtr<String> ptr("Hello");
|
||||
assert(*ptr == "Hello");
|
||||
@@ -265,11 +234,8 @@ void test_list() {
|
||||
}
|
||||
|
||||
int test_templates() {
|
||||
|
||||
SkipListTester SLTester;
|
||||
SLTester.test();
|
||||
SkipListSetTester SLSTester;
|
||||
SLSTester.test();
|
||||
StringTester stringTester;
|
||||
stringTester.test();
|
||||
VectorTester vectorTester;
|
||||
|
||||
@@ -1,322 +0,0 @@
|
||||
#ifndef SkipListSetSET_H
|
||||
#define SkipListSetSET_H
|
||||
|
||||
template<typename K>
|
||||
class SkipListSet {
|
||||
static constexpr size_t maxL{31};
|
||||
|
||||
public:
|
||||
struct Node {
|
||||
Node *next[maxL + 1] = {nullptr};
|
||||
Node *before = nullptr;
|
||||
bool end = false;
|
||||
K key = K();
|
||||
};
|
||||
|
||||
private:
|
||||
class NodeAllocator {
|
||||
static constexpr int size{64};
|
||||
Node *nodes[size];
|
||||
int top = -1;
|
||||
|
||||
public:
|
||||
NodeAllocator() noexcept = default;
|
||||
|
||||
~NodeAllocator() noexcept {
|
||||
for (int i = top; i >= 0; i--) {
|
||||
delete nodes[i];
|
||||
}
|
||||
}
|
||||
|
||||
void push(Node *&e) {
|
||||
if (top >= size - 1) {
|
||||
delete e;
|
||||
return;
|
||||
}
|
||||
nodes[++top] = e;
|
||||
}
|
||||
|
||||
|
||||
Node *get() {
|
||||
if (top == -1) {
|
||||
return new Node;
|
||||
}
|
||||
|
||||
Node *node = nodes[top--];
|
||||
|
||||
node->end = false;
|
||||
node->before = nullptr;
|
||||
node->next[0] = nullptr;
|
||||
node->key = K();
|
||||
// node->data = V();
|
||||
|
||||
return node;
|
||||
}
|
||||
};
|
||||
|
||||
static int randomL() {
|
||||
int ret = __builtin_ffs(rand());
|
||||
assert(ret >= 0);
|
||||
return ret; // NOLINT
|
||||
}
|
||||
|
||||
NodeAllocator nodeAllocator;
|
||||
|
||||
Node *root;
|
||||
Node *endnode;
|
||||
mutable Node *toUpdate[maxL + 1];
|
||||
size_t curL = 0;
|
||||
|
||||
public:
|
||||
SkipListSet() noexcept {
|
||||
root = (Node *) nodeAllocator.get();
|
||||
root->end = true;
|
||||
endnode = (Node *) nodeAllocator.get();
|
||||
endnode->end = true;
|
||||
endnode->before = root;
|
||||
|
||||
for (size_t i = 0; i <= maxL; i++) {
|
||||
root->next[i] = endnode;
|
||||
}
|
||||
};
|
||||
|
||||
~SkipListSet() noexcept {
|
||||
auto cur = root;
|
||||
while (cur != nullptr) {
|
||||
auto prev = cur;
|
||||
cur = cur->next[0];
|
||||
nodeAllocator.push(prev);
|
||||
}
|
||||
}
|
||||
|
||||
SkipListSet(SkipListSet const &l) noexcept : SkipListSet() {
|
||||
toUpdate[0] = root;
|
||||
|
||||
for (auto n = l.root->next[0]; n != nullptr && !n->end; n = n->next[0]) {
|
||||
size_t newLevel = randomL();
|
||||
|
||||
if (newLevel > curL) {
|
||||
for (size_t i = curL + 1; i <= newLevel; i++)
|
||||
toUpdate[i] = root;
|
||||
curL = newLevel;
|
||||
}
|
||||
|
||||
auto newNode = (Node *) nodeAllocator.get();
|
||||
newNode->key = n->key;
|
||||
newNode->data = n->data;
|
||||
newNode->before = toUpdate[0];
|
||||
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
||||
|
||||
for (size_t i = 0; i <= newLevel; i++) {
|
||||
newNode->next[i] = toUpdate[i]->next[i];
|
||||
toUpdate[i]->next[i] = newNode;
|
||||
toUpdate[i] = newNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SkipListSet(SkipListSet &&l) noexcept {
|
||||
this->root = l.root;
|
||||
l.root = nullptr;
|
||||
this->endnode = l.endnode;
|
||||
l.endnode = nullptr;
|
||||
this->curL = l.curL;
|
||||
l.curL = 0;
|
||||
}
|
||||
|
||||
SkipListSet &operator=(SkipListSet l) noexcept {
|
||||
std::swap(l.root, root);
|
||||
std::swap(l.endnode, endnode);
|
||||
std::swap(l.curL, curL);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool erase(Node *begin, Node *end, bool reuseUpdate = false) {
|
||||
if (begin == end) return false;
|
||||
|
||||
if (!reuseUpdate) {
|
||||
Node *cur = root;
|
||||
for (int i = curL; i >= 0; i--) {
|
||||
while (cur->next[i]->key < begin->key && !cur->next[i]->end)
|
||||
cur = cur->next[i];
|
||||
toUpdate[i] = cur;
|
||||
}
|
||||
}
|
||||
|
||||
Node *prev = nullptr;
|
||||
for (auto cur = begin; cur != end; cur = cur->next[0]) {
|
||||
if (prev)
|
||||
nodeAllocator.push(prev);
|
||||
|
||||
cur->next[0]->before = toUpdate[0];
|
||||
|
||||
for (size_t i = 0; i <= curL; i++) {
|
||||
if (toUpdate[i]->next[i] != cur)
|
||||
break;
|
||||
|
||||
toUpdate[i]->next[i] = cur->next[i];
|
||||
}
|
||||
|
||||
while (curL > 0 &&
|
||||
root->next[curL] == nullptr)
|
||||
curL--;
|
||||
prev = cur;
|
||||
}
|
||||
|
||||
if (prev)
|
||||
nodeAllocator.push(prev);
|
||||
return true;
|
||||
}
|
||||
|
||||
Node *add(K const &k, bool reuseUpdate = false) {
|
||||
if (!reuseUpdate) {
|
||||
Node *cur = root;
|
||||
|
||||
for (int i = curL; i >= 0; i--) {
|
||||
while (cur->next[i]->key < k && !cur->next[i]->end)
|
||||
cur = cur->next[i];
|
||||
toUpdate[i] = cur;
|
||||
}
|
||||
cur = cur->next[0];
|
||||
|
||||
if (cur->key == k) return nullptr;
|
||||
}
|
||||
|
||||
size_t newLevel = randomL();
|
||||
|
||||
if (newLevel > curL) {
|
||||
for (size_t i = curL + 1; i <= newLevel; i++)
|
||||
toUpdate[i] = root;
|
||||
|
||||
curL = newLevel;
|
||||
}
|
||||
|
||||
auto newNode = (Node *) nodeAllocator.get();
|
||||
newNode->key = k;
|
||||
|
||||
newNode->before = toUpdate[0];
|
||||
if (toUpdate[0]->next[0] != nullptr) toUpdate[0]->next[0]->before = newNode;
|
||||
|
||||
for (size_t i = 0; i <= newLevel; i++) {
|
||||
newNode->next[i] = toUpdate[i]->next[i];
|
||||
toUpdate[i]->next[i] = newNode;
|
||||
toUpdate[i] = newNode;
|
||||
}
|
||||
return newNode;
|
||||
}
|
||||
|
||||
bool erase(K const &k) {
|
||||
Node *cur = root;
|
||||
|
||||
for (int i = curL; i >= 0; i--) {
|
||||
while (cur->next[i]->key < k && !cur->next[i]->end)
|
||||
cur = cur->next[i];
|
||||
toUpdate[i] = cur;
|
||||
}
|
||||
cur = cur->next[0];
|
||||
|
||||
if (cur->end || cur->key != k) return false;
|
||||
|
||||
cur->next[0]->before = toUpdate[0];
|
||||
|
||||
for (size_t i = 0; i <= curL; i++) {
|
||||
if (toUpdate[i]->next[i] != cur)
|
||||
break;
|
||||
|
||||
toUpdate[i]->next[i] = cur->next[i];
|
||||
}
|
||||
|
||||
while (curL > 0 &&
|
||||
root->next[curL] == nullptr)
|
||||
curL--;
|
||||
nodeAllocator.push(cur);
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
// Returns the node PRECEDING the node with a key that is GREATER than k
|
||||
Node *find(K const &k) const {
|
||||
Node *cur = root;
|
||||
|
||||
for (int i = curL; i >= 0; i--)
|
||||
while (cur->next[i]->key <= k && !cur->next[i]->end)
|
||||
cur = cur->next[i];
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
Node *upper_bound(K const &k) const {
|
||||
Node *cur = root;
|
||||
|
||||
for (int i = curL; i >= 0; i--) {
|
||||
while (cur->next[i]->key <= k && !cur->next[i]->end)
|
||||
cur = cur->next[i];
|
||||
}
|
||||
|
||||
cur = cur->next[0];
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
Node *lower_bound_update(K const &k) const {
|
||||
Node *cur = root;
|
||||
|
||||
for (int i = curL; i >= 0; i--) {
|
||||
while (cur->next[i]->key < k && !cur->next[i]->end)
|
||||
cur = cur->next[i];
|
||||
toUpdate[i] = cur;
|
||||
}
|
||||
|
||||
cur = cur->next[0];
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
|
||||
Node *lower_bound(K const &k) const {
|
||||
Node *cur = root;
|
||||
|
||||
for (int i = curL; i >= 0; i--) {
|
||||
while (cur->next[i]->key < k && !cur->next[i]->end)
|
||||
cur = cur->next[i];
|
||||
}
|
||||
|
||||
cur = cur->next[0];
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
|
||||
bool operator==(SkipListSet const &r) const {
|
||||
auto n = root->next[0];
|
||||
auto n2 = r.root->next[0];
|
||||
|
||||
while (!n->end && !n2->end) {
|
||||
if (!(n->data == n2->data)) return false;
|
||||
n = n->next[0];
|
||||
n2 = n2->next[0];
|
||||
}
|
||||
|
||||
if ((n->end || n2->end) && n->end != n2->end) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// void print() const {
|
||||
// std::cout << "LIST STATUS" << std::endl;
|
||||
//
|
||||
// for (size_t i = 0; i <= curL; i++) {
|
||||
// Node *n = root->next[i];
|
||||
// std::cout << "L " << i << ": ";
|
||||
// while (n != nullptr && n->next[0]) {
|
||||
// std::cout << "GUARD: " << n->end << " KEY: " << n->key << " RANGE: " << n->data
|
||||
// << " <<<<<";
|
||||
// n = n->next[i];
|
||||
// }
|
||||
// std::cout << std::endl;
|
||||
// }
|
||||
// };
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user