tidied up code based on error reports by clang-tidy

This commit is contained in:
Krishna Vedala 2020-07-12 17:00:27 -04:00
parent ddf148b613
commit f970ce361c
No known key found for this signature in database
GPG Key ID: BA19ACF8FC8792F7

View File

@ -1,124 +1,116 @@
/** /**
* @file skip_list.cpp * @file skip_list.cpp
* @brief Data structure for fast searching and insertion in \f$O(\log n)\f$ time * @brief Data structure for fast searching and insertion in \f$O(\log n)\f$
* time
* @details * @details
* A skip list is a data structure that is used for storing a sorted list of items with a * A skip list is a data structure that is used for storing a sorted list of
* help of hierarchy of linked lists that connect increasingly sparse subsequences of the items * items with a help of hierarchy of linked lists that connect increasingly
* sparse subsequences of the items
* *
* References used: [GeeksForGeek](https://www.geeksforgeeks.org/skip-list/), [OpenGenus](https://iq.opengenus.org/skip-list) for PseudoCode and Code * References used: [GeeksForGeek](https://www.geeksforgeeks.org/skip-list/),
* [OpenGenus](https://iq.opengenus.org/skip-list) for PseudoCode and Code
* @author [enqidu](https://github.com/enqidu) * @author [enqidu](https://github.com/enqidu)
* . * @author [Krishna Vedala](https://github.com/kvedala)
*/ */
#include <iostream> #include <array>
#include <vector>
#include <cstring> #include <cstring>
#include <ctime> #include <ctime>
#include <iostream>
#include <memory>
#include <vector>
using std::vector; /** \namespace data_structure
using std::endl; * \brief Data-structure algorithms
*/
#define MAX_LEVEL 2 ///< Maximum level of skip list namespace data_structure {
#define PROBABILITY 0.5 ///< Current probability for "coin toss" constexpr int MAX_LEVEL = 2; ///< Maximum level of skip list
constexpr float PROBABILITY = 0.5; ///< Current probability for "coin toss"
/** /**
* Node structure [Key][Node*, Node*...] * Node structure [Key][Node*, Node*...]
*/ */
struct Node { struct Node {
int key; ///< key integer int key; ///< key integer
void* value; ///< pointer of value void* value; ///< pointer of value
vector<Node*> forward; ///< nodes of the given one in all levels std::vector<std::shared_ptr<Node>>
// Constructor of the node forward; ///< nodes of the given one in all levels
Node(int key, int level, void* value);
};
/** /**
* Creates node with provided key, level and value * Creates node with provided key, level and value
* @param key is number that is used for comparision * @param key is number that is used for comparision
* @param level is the maximum level node's going to added * @param level is the maximum level node's going to added
*/ */
Node::Node(int key, int level, void* value) { Node(int key, int level, void* value = nullptr) : key(key) {
this->key = key; // Initialization of forward vector
for (int i = 0; i < (level + 1); i++) {
//Initialization of forward vector
for (int i = 0; i < (level+1); i++){
forward.push_back(nullptr); forward.push_back(nullptr);
} }
} }
};
/** /**
* SkipList class implementation with basic methods * SkipList class implementation with basic methods
*/ */
class SkipList { class SkipList {
int level; ///< Maximum level of the skiplist int level; ///< Maximum level of the skiplist
Node *header; ///< Pointer to the header node std::shared_ptr<Node> header; ///< Pointer to the header node
public:
SkipList();
int randomLevel();
void insertElement(int, void*);
void deleteElement(int);
void* searchElement(int);
void displayList();
~SkipList();
};
public:
/** /**
* Skeep List constructor. Initializes header, start * Skip List constructor. Initializes header, start
* Node for searching in the list * Node for searching in the list
*/ */
SkipList::SkipList() { SkipList() {
level = 0; level = 0;
// Header initialization // Header initialization
header = new Node(-1, MAX_LEVEL, nullptr); header = std::shared_ptr<Node>(new Node(-1, MAX_LEVEL));
} }
/** /**
* Destructor for skiplist class * Destructor for skiplist class
*/ */
SkipList::~SkipList(){ ~SkipList() {
for(int i=0; i <= level; i++) { for (int i = 0; i <= level; i++) {
Node *node = header->forward[i]; std::shared_ptr<Node> node = header->forward[i];
Node* temp; std::shared_ptr<Node> temp;
while(node != nullptr) { while (node != nullptr) {
temp = node; temp = node;
node = node->forward[i]; node = node->forward[i];
delete temp; temp.reset();
} }
} }
delete header; header.reset();
} }
/**
/**
* Returns random level of the skip list. * Returns random level of the skip list.
* Every higher level is 2 times less likely. * Every higher level is 2 times less likely.
* @return lvl: random level for skip list; * @return random level for skip list
*/ */
int SkipList::randomLevel() { int randomLevel() {
int lvl = 0; int lvl = 0;
while(static_cast<float>(std::rand())/RAND_MAX < PROBABILITY && lvl < MAX_LEVEL) lvl++; while (static_cast<float>(std::rand() / RAND_MAX) < PROBABILITY &&
lvl < MAX_LEVEL)
lvl++;
return lvl; return lvl;
} }
/**
/**
* Inserts elements with given key and value; * Inserts elements with given key and value;
* It's level is computed by randomLevel() function. * It's level is computed by randomLevel() function.
* @param key is number that is used for comparision * @param key is number that is used for comparision
* @param value pointer to a value, that can be any type * @param value pointer to a value, that can be any type
*/ */
void SkipList::insertElement(int key, void* value) { void insertElement(int key, void* value) {
std::cout << "Inserting" << key << "..."; std::cout << "Inserting" << key << "...";
Node *x = header; std::shared_ptr<Node> x = header;
Node *update[MAX_LEVEL+1]; std::array<std::shared_ptr<Node>, MAX_LEVEL + 1> update;
memset(update, 0, sizeof(Node*)*(MAX_LEVEL+1)); update.fill(nullptr);
for (int i = level; i >= 0; i--) {
for(int i = level; i >= 0; i--) { while (x->forward[i] != nullptr && x->forward[i]->key < key)
while(x->forward[i] != nullptr && x->forward[i]->key < key) x = x->forward[i]; x = x->forward[i];
update[i] = x; update[i] = x;
} }
@ -128,37 +120,39 @@ void SkipList::insertElement(int key, void* value) {
if (doesnt_exist) { if (doesnt_exist) {
int rlevel = randomLevel(); int rlevel = randomLevel();
if(rlevel > level) { if (rlevel > level) {
for(int i=level+1;i<rlevel+1;i++) update[i] = header; for (int i = level + 1; i < rlevel + 1; i++) update[i] = header;
// Update current level // Update current level
level = rlevel; level = rlevel;
} }
Node* n = new Node(key, rlevel, value); std::shared_ptr<Node> n =
for(int i=0;i<=rlevel;i++) { std::shared_ptr<Node>(new Node(key, rlevel, value));
for (int i = 0; i <= rlevel; i++) {
n->forward[i] = update[i]->forward[i]; n->forward[i] = update[i]->forward[i];
update[i]->forward[i] = n; update[i]->forward[i] = n;
} }
std::cout << "Inserted" << endl; std::cout << "Inserted" << std::endl;
} else { } else {
std::cout << "Exists" << endl; std::cout << "Exists" << std::endl;
}
} }
}
/** /**
* Deletes an element by key and prints if has been removed successfully * Deletes an element by key and prints if has been removed successfully
* @param key is number that is used for comparision. * @param key is number that is used for comparision.
*/ */
void SkipList::deleteElement(int key) { void deleteElement(int key) {
Node *x = header; std::shared_ptr<Node> x = header;
Node *update[MAX_LEVEL+1]; std::array<std::shared_ptr<Node>, MAX_LEVEL + 1> update;
memset(update, 0, sizeof(Node*)*(MAX_LEVEL+1)); update.fill(nullptr);
for(int i = level; i >= 0; i--) { for (int i = level; i >= 0; i--) {
while(x->forward[i] != nullptr && x->forward[i]->key < key) x = x->forward[i]; while (x->forward[i] != nullptr && x->forward[i]->key < key)
x = x->forward[i];
update[i] = x; update[i] = x;
} }
@ -166,76 +160,76 @@ void SkipList::deleteElement(int key) {
bool doesnt_exist = (x == nullptr || x->key != key); bool doesnt_exist = (x == nullptr || x->key != key);
if(!doesnt_exist) { if (!doesnt_exist) {
for(int i=0;i<=level;i++) { for (int i = 0; i <= level; i++) {
if(update[i]->forward[i] != x) break; if (update[i]->forward[i] != x)
break;
update[i]->forward[i] = x->forward[i]; update[i]->forward[i] = x->forward[i];
} }
/* Remove empty levels*/ /* Remove empty levels*/
while(level>0 && header->forward[level] == 0) level--; while (level > 0 && header->forward[level] == nullptr) level--;
std::cout << "Deleted" << endl; std::cout << "Deleted" << std::endl;
} else { } else {
std::cout << "Doesn't exist" << endl; std::cout << "Doesn't exist" << std::endl;
}
} }
}
/**
/**
* Searching element in skip list structure * Searching element in skip list structure
* @param key is number that is used for comparision * @param key is number that is used for comparision
* @return pointer to the value of the node * @return pointer to the value of the node
*/ */
void* SkipList::searchElement(int key) { void* searchElement(int key) {
Node *x = header; std::shared_ptr<Node> x = header;
std::cout << "Searching for " + key << endl; std::cout << "Searching for " << key << std::endl;
for(int i = level; i >= 0; i--) { for (int i = level; i >= 0; i--) {
while(x->forward[i] && x->forward[i]->key < key) x = x->forward[i]; while (x->forward[i] && x->forward[i]->key < key) x = x->forward[i];
} }
x = x->forward[0]; x = x->forward[0];
if(x && x->key == key){ if (x && x->key == key) {
std::cout << "Found" << endl; std::cout << "Found" << std::endl;
return x->value; return x->value;
} else { } else {
std::cout << "Not Found" << endl; std::cout << "Not Found" << std::endl;
return nullptr; return nullptr;
} }
} }
/* /*
* Display skip list level * Display skip list level
*/ */
void SkipList::displayList() { void displayList() {
std::cout << "Displaying list:\n" << endl; std::cout << "Displaying list:\n" << std::endl;
for(int i=0; i <= level; i++) { for (int i = 0; i <= level; i++) {
Node *node = header->forward[i]; std::shared_ptr<Node> node = header->forward[i];
std::cout << "Level " << (i) << ": "; std::cout << "Level " << (i) << ": ";
while(node != nullptr) { while (node != nullptr) {
std::cout << node->key << " "; std::cout << node->key << " ";
node = node->forward[i]; node = node->forward[i];
} }
std::cout << endl; std::cout << std::endl;
} }
} }
};
} // namespace data_structure
/** /**
* Main function: * Main function:
* Creates and inserts random 2^[number of levels] * Creates and inserts random 2^[number of levels]
* elements into the skip lists and than displays it * elements into the skip lists and than displays it
*/ */
int main() int main() {
{
std::srand(std::time(nullptr)); std::srand(std::time(nullptr));
SkipList lst; data_structure::SkipList lst;
for (int j = 0; j < (1 << (MAX_LEVEL+1)); j++){ for (int j = 0; j < (1 << (data_structure::MAX_LEVEL + 1)); j++) {
int k = (std::rand()%( 1 << (MAX_LEVEL+2)) + 1); int k = (std::rand() % (1 << (data_structure::MAX_LEVEL + 2)) + 1);
lst.insertElement(k, &j); lst.insertElement(k, &j);
} }
lst.displayList(); lst.displayList();
} }