blob: ca71c7fecc72ddc187a80f6634d68ec6c0d57920 [file] [log] [blame]
Shuo Chen9a43f162014-07-01 13:43:54 +08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
Davide Pesavento49f3a5f2017-09-23 01:36:33 -04002/*
3 * Copyright (c) 2014-2017, Regents of the University of California.
4 *
5 * This file is part of NDN repo-ng (Next generation of NDN repository).
6 * See AUTHORS.md for complete list of repo-ng authors and contributors.
7 *
8 * repo-ng is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * repo-ng is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * repo-ng, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 */
Shuo Chen9a43f162014-07-01 13:43:54 +080019
WeiqiShia79c7782014-12-26 09:42:10 +080020#ifndef REPO_TESTS_OTHER_SKIPLIST_LIST_HPP
21#define REPO_TESTS_OTHER_SKIPLIST_LIST_HPP
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040022
Shuo Chen9a43f162014-07-01 13:43:54 +080023#include "common.hpp"
24
Davide Pesavento49f3a5f2017-09-23 01:36:33 -040025#include <random>
26
WeiqiShia79c7782014-12-26 09:42:10 +080027namespace update1 {
Shuo Chen9a43f162014-07-01 13:43:54 +080028
Shuo Chenbf2248d2014-07-12 13:47:20 +080029class SkipList32Levels25Probabilty
Shuo Chen9a43f162014-07-01 13:43:54 +080030{
31public:
32 static size_t
Shuo Chenbf2248d2014-07-12 13:47:20 +080033 getMaxLevels()
Shuo Chen9a43f162014-07-01 13:43:54 +080034 {
35 return 32;
36 }
37
38 static double
39 getProbability()
40 {
Shuo Chenbf2248d2014-07-12 13:47:20 +080041 return 0.25; // 25%
Shuo Chen9a43f162014-07-01 13:43:54 +080042 }
43};
44
Shuo Chenbf2248d2014-07-12 13:47:20 +080045template<typename T>
46struct SkipListNode
47{
48 typedef SkipListNode<T>* SkipListNodePointer;
49 T data;
WeiqiShia79c7782014-12-26 09:42:10 +080050 std::list<SkipListNodePointer> prevs;
51 std::list<SkipListNodePointer> nexts;
Shuo Chenbf2248d2014-07-12 13:47:20 +080052};
53
54template<typename T, class Ref, class Ptr>
55class SkipListIterator : public std::iterator<std::bidirectional_iterator_tag, T>
56{
57public:
58 typedef SkipListNode<T>* NodePointer;
59 NodePointer node;
60
61 typedef SkipListIterator<T, Ref, Ptr> Self;
62 typedef T value_type;
63 typedef Ptr pointer;
64 typedef Ref reference;
65 typedef ptrdiff_t difference_type;
66 typedef SkipListIterator<T, const T&, const T*> const_iterator;
67 /// alias of const_iterator
68 typedef const_iterator iterator;
69
70public:
71 // constructor
72 SkipListIterator()
73 {
74 }
75
76 explicit
77 SkipListIterator(NodePointer x)
78 : node(x)
79 {
80 }
81
82 SkipListIterator(const SkipListIterator& x)
83 : node(x.node)
84 {
85 }
86
87 bool
88 operator==(const const_iterator& x) const
89 {
90 return node == x.node;
91 }
92
93 bool
94 operator!=(const const_iterator& x) const
95 {
96 return node != x.node;
97 }
98
99 reference
100 operator*() const
101 {
102 return (*node).data;
103 }
104
105 pointer
106 operator->() const
107 {
108 return &(operator*());
109 }
110
111 Self&
112 operator++()
113 {
WeiqiShia79c7782014-12-26 09:42:10 +0800114 node = node->nexts.front();
Shuo Chenbf2248d2014-07-12 13:47:20 +0800115 return *this;
116 }
117
118 Self
119 operator++(int)
120 {
121 Self tmp = *this;
122 ++*this;
123 return tmp;
124 }
125
126 Self&
127 operator--()
128 {
WeiqiShia79c7782014-12-26 09:42:10 +0800129 node = node->prevs.front();
Shuo Chenbf2248d2014-07-12 13:47:20 +0800130 return *this;
131 }
132
133 Self
134 operator--(int)
135 {
136 Self tmp = *this;
137 --*this;
138 return tmp;
139 }
140};
141
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400142/**
Shuo Chenbf2248d2014-07-12 13:47:20 +0800143 * @brief SkipList
144 *
145 * Examples of internal structure:
146 * "A <-i-> B" means A->nexts[i] = B and B->prevs[i] = A
147 *
148 * case 1: an empty skip list
149 * m_head <-0-> m_head
150 *
151 * case 2: a skip list with only one level and only one node
152 * m_head <-0-> A <-0-> m_head
153 *
154 * case 3: a skip list with three nodes, node A and B appear on one level,
155 * node C appears on two levels
156 * m_head <-1-> C <-1-> m_head
157 * m_head <-0-> A <-0-> B <-0-> C <-0-> m_head
158 */
159
Shuo Chen9a43f162014-07-01 13:43:54 +0800160template<typename T, typename Compare = std::less<T>,
Shuo Chenbf2248d2014-07-12 13:47:20 +0800161 typename Traits = SkipList32Levels25Probabilty>
Shuo Chen9a43f162014-07-01 13:43:54 +0800162class SkipList
163{
164public:
Shuo Chenbf2248d2014-07-12 13:47:20 +0800165 typedef T value_type;
166 typedef value_type* pointer;
167 typedef const value_type* const_pointer;
168 typedef value_type& reference;
169 typedef const value_type& const_reference;
170 typedef SkipListNode<T> Node;
171 typedef Node* NodePointer;
172 typedef size_t size_type;
173 typedef ptrdiff_t difference_type;
174 typedef SkipListIterator<T, const T&, const T*> const_iterator;
175 /// alias of const_iterator
176 typedef const_iterator iterator;
WeiqiShia79c7782014-12-26 09:42:10 +0800177 typedef SkipListNode<T>* SkipListNodePointer;
Shuo Chen9a43f162014-07-01 13:43:54 +0800178
179public:
180 explicit
Shuo Chenbf2248d2014-07-12 13:47:20 +0800181 SkipList()
182 {
183 initializeHead();
184 }
Shuo Chen9a43f162014-07-01 13:43:54 +0800185
Shuo Chenbf2248d2014-07-12 13:47:20 +0800186 ~SkipList()
187 {
188 clear();
WeiqiShia79c7782014-12-26 09:42:10 +0800189 delete(m_head);
Shuo Chenbf2248d2014-07-12 13:47:20 +0800190 }
191
192 const_iterator
193 begin() const
194 {
195 return const_iterator(*(*m_head).nexts.begin());
196 }
197
198 const_iterator
199 end() const
200 {
201 return const_iterator(m_head);
202 }
203
204 bool
205 empty() const
206 {
207 return *(m_head->nexts.begin()) == m_head;
208 }
Shuo Chen9a43f162014-07-01 13:43:54 +0800209
210 size_t
Shuo Chenbf2248d2014-07-12 13:47:20 +0800211 size() const
212 {
213 return m_size;
214 }
Shuo Chen9a43f162014-07-01 13:43:54 +0800215
Shuo Chenbf2248d2014-07-12 13:47:20 +0800216 const_iterator
217 lower_bound(const T& x) const;
Shuo Chen9a43f162014-07-01 13:43:54 +0800218
Shuo Chenbf2248d2014-07-12 13:47:20 +0800219 const_iterator
220 find(const T& x) const;
Shuo Chen9a43f162014-07-01 13:43:54 +0800221
Shuo Chenbf2248d2014-07-12 13:47:20 +0800222 std::pair<const_iterator, bool>
223 insert(const T& x);
Shuo Chen9a43f162014-07-01 13:43:54 +0800224
Shuo Chenbf2248d2014-07-12 13:47:20 +0800225 const_iterator
226 erase(const_iterator it);
Shuo Chen9a43f162014-07-01 13:43:54 +0800227
Shuo Chenbf2248d2014-07-12 13:47:20 +0800228protected:
Shuo Chen9a43f162014-07-01 13:43:54 +0800229
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400230 /**
Shuo Chenbf2248d2014-07-12 13:47:20 +0800231 * @brief initialize the node
232 */
233 NodePointer
234 createNode()
235 {
WeiqiShia79c7782014-12-26 09:42:10 +0800236 NodePointer p = new Node;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800237 return p;
238 }
Shuo Chen9a43f162014-07-01 13:43:54 +0800239
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400240 /**
Shuo Chenbf2248d2014-07-12 13:47:20 +0800241 * @brief initialize the node with given value
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400242 * @param x to be set to the value of node
Shuo Chenbf2248d2014-07-12 13:47:20 +0800243 */
244 NodePointer
245 createNode(const T& x)
246 {
WeiqiShia79c7782014-12-26 09:42:10 +0800247 NodePointer p = new Node;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800248 m_dataAllocator.construct(&(p->data), x);
249 return p;
250 }
251
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400252 /**
253 * @brief destructor of the node
254 * @param p pointer to the node to be destructed
Shuo Chenbf2248d2014-07-12 13:47:20 +0800255 */
256 void
257 destroyNode(NodePointer p)
258 {
WeiqiShia79c7782014-12-26 09:42:10 +0800259 delete(p);
Shuo Chenbf2248d2014-07-12 13:47:20 +0800260 }
261
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400262 /**
Shuo Chenbf2248d2014-07-12 13:47:20 +0800263 * @brief initialize the head
264 */
265 void
266 initializeHead()
267 {
268 m_head = createNode();
269 m_head->prevs.push_back(m_head);
270 m_head->nexts.push_back(m_head);
271 m_size = 0;
272 }
273
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400274 /**
Shuo Chenbf2248d2014-07-12 13:47:20 +0800275 * @brief destroy all the nodes of skiplist except the head
276 */
277 void
278 clear()
279 {
WeiqiShia79c7782014-12-26 09:42:10 +0800280 NodePointer cur = m_head->nexts.front();
Shuo Chenbf2248d2014-07-12 13:47:20 +0800281 while (cur != m_head) {
282 NodePointer tmp = cur;
WeiqiShia79c7782014-12-26 09:42:10 +0800283 cur = cur->nexts.front();
Shuo Chenbf2248d2014-07-12 13:47:20 +0800284 destroyNode(tmp);
285 }
WeiqiShia79c7782014-12-26 09:42:10 +0800286 m_head->nexts.front() = m_head;
287 m_head->prevs.front() = m_head;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800288 }
289
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400290 /**
Shuo Chenbf2248d2014-07-12 13:47:20 +0800291 * @brief pick a random height for inserted skiplist entry
292 */
Shuo Chen9a43f162014-07-01 13:43:54 +0800293 size_t
Shuo Chenbf2248d2014-07-12 13:47:20 +0800294 pickRandomLevel() const
295 {
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400296 static std::mt19937 gen(std::random_device{}());
297 static std::geometric_distribution<size_t> dist(Traits::getProbability());
Shuo Chenbf2248d2014-07-12 13:47:20 +0800298 return std::min(dist(gen), Traits::getMaxLevels());
299 }
Shuo Chen9a43f162014-07-01 13:43:54 +0800300
Shuo Chenbf2248d2014-07-12 13:47:20 +0800301protected:
302 NodePointer m_head;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800303 std::allocator<T> m_dataAllocator;
Shuo Chen9a43f162014-07-01 13:43:54 +0800304 Compare m_compare;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800305 size_t m_size;
Shuo Chen9a43f162014-07-01 13:43:54 +0800306};
307
Shuo Chenbf2248d2014-07-12 13:47:20 +0800308
Shuo Chen9a43f162014-07-01 13:43:54 +0800309template<typename T, typename Compare, typename Traits>
Shuo Chenbf2248d2014-07-12 13:47:20 +0800310typename SkipList<T, Compare, Traits>::const_iterator
311SkipList<T, Compare, Traits>::lower_bound(const T& x) const
Shuo Chen9a43f162014-07-01 13:43:54 +0800312{
Shuo Chenbf2248d2014-07-12 13:47:20 +0800313 size_t nLevels = m_head->nexts.size();
314 NodePointer p = m_head;
WeiqiShia79c7782014-12-26 09:42:10 +0800315 NodePointer q = p->nexts.back();
Shuo Chenbf2248d2014-07-12 13:47:20 +0800316 for (int i = nLevels - 1; i >= 0; --i) {
WeiqiShia79c7782014-12-26 09:42:10 +0800317 typename std::list<SkipListNodePointer>::iterator it_p = p->nexts.begin();
318 for (int j = 0; j < i; j++) {
319 it_p++;
320 }
321 q = *it_p;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800322 if (q != m_head) {
323 while (m_compare(q->data, x)) {
WeiqiShia79c7782014-12-26 09:42:10 +0800324 p = *it_p;
325 it_p = p->nexts.begin();
326 for (int j = 0; j < i; j++) {
327 it_p++;
328 }
329 q = *it_p;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800330 if (q == m_head) {
331 break;
332 }
333 }
334 }
335 }
336 return const_iterator(q);
Shuo Chen9a43f162014-07-01 13:43:54 +0800337}
338
339template<typename T, typename Compare, typename Traits>
Shuo Chenbf2248d2014-07-12 13:47:20 +0800340typename SkipList<T, Compare, Traits>::const_iterator
341SkipList<T, Compare, Traits>::find(const T& x) const
Shuo Chen9a43f162014-07-01 13:43:54 +0800342{
Shuo Chenbf2248d2014-07-12 13:47:20 +0800343 const_iterator it = this->lower_bound(x);
344 if (it == this->end() || *it != x)
Shuo Chen9a43f162014-07-01 13:43:54 +0800345 return this->end();
346 return it;
347}
348
349template<typename T, typename Compare, typename Traits>
Shuo Chenbf2248d2014-07-12 13:47:20 +0800350std::pair<typename SkipList<T, Compare, Traits>::const_iterator, bool>
351SkipList<T, Compare, Traits>::insert(const T& x)
Shuo Chen9a43f162014-07-01 13:43:54 +0800352{
Shuo Chenbf2248d2014-07-12 13:47:20 +0800353 size_t nLevels = m_head->nexts.size();
354 // 1. find insert position
355 std::vector<NodePointer> insertPositions(nLevels);
356 NodePointer p = m_head;
WeiqiShia79c7782014-12-26 09:42:10 +0800357 NodePointer q = p->nexts.back();
Shuo Chenbf2248d2014-07-12 13:47:20 +0800358 for (int i = nLevels - 1; i >= 0; --i) {
WeiqiShia79c7782014-12-26 09:42:10 +0800359 typename std::list<SkipListNodePointer>::iterator it_p = p->nexts.begin();
360 for (int j = 0; j < i; j++) {
361 it_p++;
362 }
363 q = *it_p;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800364 if (q != m_head) {
365 while (m_compare(q->data, x)) {
WeiqiShia79c7782014-12-26 09:42:10 +0800366 p = *it_p;
367 it_p = p->nexts.begin();
368 for (int j = 0; j < i; j++) {
369 it_p++;
370 }
371 q = *it_p;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800372 if (q == m_head) {
Shuo Chen9a43f162014-07-01 13:43:54 +0800373 break;
374 }
375 }
376 }
Shuo Chenbf2248d2014-07-12 13:47:20 +0800377 insertPositions[i] = p;
378 }
379 // 2. whether q->data == x?
380 if (q != m_head)
381 if (!m_compare(q->data, x) && !m_compare(x, q->data)) {
382 return std::pair<const_iterator, bool>(const_iterator(q), false);
383 }
384 // 3. construct new node;
385 NodePointer newNode = createNode(x);
386 // 4. pick random nLevels
387 size_t newLevel = pickRandomLevel();
388 // 5. insert the new node
389 newNode->nexts.resize(newLevel + 1);
390 newNode->prevs.resize(newLevel + 1);
391 if (newLevel > nLevels - 1) {
392 m_head->nexts.resize(newLevel + 1, m_head);
393 m_head->prevs.resize(newLevel + 1, m_head);
394 insertPositions.resize(newLevel + 1, m_head);
395 }
Wentao Shanga8f3c402014-10-30 14:03:27 -0700396 for (size_t i = 0; i <= newLevel; i++) {
WeiqiShia79c7782014-12-26 09:42:10 +0800397 typename std::list<SkipListNodePointer>::iterator it_newNode_next = newNode->nexts.begin();
398 for (size_t j = 0; j < i; j++) {
399 it_newNode_next++;
400 }
401 typename std::list<SkipListNodePointer>::iterator it_insert_next = insertPositions[i]->nexts.begin();
402 for (size_t j = 0; j < i; j++) {
403 it_insert_next++;
404 }
405 *it_newNode_next = *it_insert_next;
406
407 typename std::list<SkipListNodePointer>::iterator it_newNode_prev = newNode->prevs.begin();
408 for (size_t j = 0; j < i; j++) {
409 it_newNode_prev++;
410 }
411 *it_newNode_prev = insertPositions[i];
412
413 it_insert_next = insertPositions[i]->nexts.begin();
414 for (size_t j = 0; j < i; j++) {
415 it_insert_next++;
416 }
417 *it_insert_next = newNode;
418 it_newNode_next = newNode->nexts.begin();
419 for (size_t j = 0; j < i; j++) {
420 it_newNode_next++;
421 }
422 typename std::list<SkipListNodePointer>::iterator it_newNode_next_prev = (*it_newNode_next)->prevs.begin();
423 for (size_t j = 0; j < i; j++) {
424 it_newNode_next_prev++;
425 }
426 *it_newNode_next_prev = newNode;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800427 }
Shuo Chen9a43f162014-07-01 13:43:54 +0800428
Shuo Chenbf2248d2014-07-12 13:47:20 +0800429 ++m_size;
430 return std::pair<const_iterator, bool>(const_iterator(newNode), true);
431}
Shuo Chen9a43f162014-07-01 13:43:54 +0800432
Shuo Chenbf2248d2014-07-12 13:47:20 +0800433template<typename T, typename Compare, typename Traits>
434typename SkipList<T, Compare, Traits>::const_iterator
435SkipList<T, Compare, Traits>::erase(typename SkipList<T, Compare, Traits>::const_iterator it)
436{
437 NodePointer eraseNode = it.node;
438 if (!empty() && eraseNode != m_head) {
WeiqiShia79c7782014-12-26 09:42:10 +0800439 NodePointer returnNode = eraseNode->nexts.front();
Shuo Chenbf2248d2014-07-12 13:47:20 +0800440 size_t nLevels = eraseNode->nexts.size();
441 for (int i = nLevels - 1; i >= 0; --i) {
WeiqiShia79c7782014-12-26 09:42:10 +0800442 typename std::list<SkipListNodePointer>::iterator it_erase_next = eraseNode->nexts.begin();
443 for (int j = 0; j < i; j++) {
444 it_erase_next++;
445 }
446
447 typename std::list<SkipListNodePointer>::iterator it_erase_next_prev = (*it_erase_next)->prevs.begin();
448 for (int j = 0; j < i; j++) {
449 it_erase_next_prev++;
450 }
451
452 typename std::list<SkipListNodePointer>::iterator it_erase_prev = eraseNode->prevs.begin();
453 for (int j = 0; j < i; j++) {
454 it_erase_prev++;
455 }
456 *it_erase_next_prev = *it_erase_prev;
457
458 typename std::list<SkipListNodePointer>::iterator it_erase_prev_next = (*it_erase_prev)->nexts.begin();
459 for (int j = 0; j < i; j++) {
460 it_erase_prev_next++;
461 }
462
463 *it_erase_prev_next = *it_erase_next;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800464 // clear empty nLevels
WeiqiShia79c7782014-12-26 09:42:10 +0800465 if ((*it_erase_next == *it_erase_prev) && i > 0) {
Shuo Chenbf2248d2014-07-12 13:47:20 +0800466 m_head->nexts.pop_back();
467 m_head->prevs.pop_back();
468 }
469 }
470 destroyNode(eraseNode);
471 --m_size;
472 return const_iterator(returnNode);
Shuo Chen9a43f162014-07-01 13:43:54 +0800473 }
474 else {
475 return end();
476 }
477}
478
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400479} // namespace update1
Shuo Chen9a43f162014-07-01 13:43:54 +0800480
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400481#endif // REPO_TESTS_OTHER_SKIPLIST_LIST_HPP