blob: 72d1dda4821c7da68863c73b076ccf18562341b0 [file] [log] [blame]
Shuo Chen9a43f162014-07-01 13:43:54 +08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3* Copyright (c) 2014, 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*/
19
WeiqiShia79c7782014-12-26 09:42:10 +080020#ifndef REPO_TESTS_OTHER_SKIPLIST_LIST_HPP
21#define REPO_TESTS_OTHER_SKIPLIST_LIST_HPP
Shuo Chen9a43f162014-07-01 13:43:54 +080022#include "common.hpp"
23
WeiqiShia79c7782014-12-26 09:42:10 +080024namespace update1 {
Shuo Chen9a43f162014-07-01 13:43:54 +080025
Shuo Chenbf2248d2014-07-12 13:47:20 +080026class SkipList32Levels25Probabilty
Shuo Chen9a43f162014-07-01 13:43:54 +080027{
28public:
29 static size_t
Shuo Chenbf2248d2014-07-12 13:47:20 +080030 getMaxLevels()
Shuo Chen9a43f162014-07-01 13:43:54 +080031 {
32 return 32;
33 }
34
35 static double
36 getProbability()
37 {
Shuo Chenbf2248d2014-07-12 13:47:20 +080038 return 0.25; // 25%
Shuo Chen9a43f162014-07-01 13:43:54 +080039 }
40};
41
Shuo Chenbf2248d2014-07-12 13:47:20 +080042template<typename T>
43struct SkipListNode
44{
45 typedef SkipListNode<T>* SkipListNodePointer;
46 T data;
WeiqiShia79c7782014-12-26 09:42:10 +080047 std::list<SkipListNodePointer> prevs;
48 std::list<SkipListNodePointer> nexts;
Shuo Chenbf2248d2014-07-12 13:47:20 +080049};
50
51template<typename T, class Ref, class Ptr>
52class SkipListIterator : public std::iterator<std::bidirectional_iterator_tag, T>
53{
54public:
55 typedef SkipListNode<T>* NodePointer;
56 NodePointer node;
57
58 typedef SkipListIterator<T, Ref, Ptr> Self;
59 typedef T value_type;
60 typedef Ptr pointer;
61 typedef Ref reference;
62 typedef ptrdiff_t difference_type;
63 typedef SkipListIterator<T, const T&, const T*> const_iterator;
64 /// alias of const_iterator
65 typedef const_iterator iterator;
66
67public:
68 // constructor
69 SkipListIterator()
70 {
71 }
72
73 explicit
74 SkipListIterator(NodePointer x)
75 : node(x)
76 {
77 }
78
79 SkipListIterator(const SkipListIterator& x)
80 : node(x.node)
81 {
82 }
83
84 bool
85 operator==(const const_iterator& x) const
86 {
87 return node == x.node;
88 }
89
90 bool
91 operator!=(const const_iterator& x) const
92 {
93 return node != x.node;
94 }
95
96 reference
97 operator*() const
98 {
99 return (*node).data;
100 }
101
102 pointer
103 operator->() const
104 {
105 return &(operator*());
106 }
107
108 Self&
109 operator++()
110 {
WeiqiShia79c7782014-12-26 09:42:10 +0800111 node = node->nexts.front();
Shuo Chenbf2248d2014-07-12 13:47:20 +0800112 return *this;
113 }
114
115 Self
116 operator++(int)
117 {
118 Self tmp = *this;
119 ++*this;
120 return tmp;
121 }
122
123 Self&
124 operator--()
125 {
WeiqiShia79c7782014-12-26 09:42:10 +0800126 node = node->prevs.front();
Shuo Chenbf2248d2014-07-12 13:47:20 +0800127 return *this;
128 }
129
130 Self
131 operator--(int)
132 {
133 Self tmp = *this;
134 --*this;
135 return tmp;
136 }
137};
138
139/*
140 * @brief SkipList
141 *
142 * Examples of internal structure:
143 * "A <-i-> B" means A->nexts[i] = B and B->prevs[i] = A
144 *
145 * case 1: an empty skip list
146 * m_head <-0-> m_head
147 *
148 * case 2: a skip list with only one level and only one node
149 * m_head <-0-> A <-0-> m_head
150 *
151 * case 3: a skip list with three nodes, node A and B appear on one level,
152 * node C appears on two levels
153 * m_head <-1-> C <-1-> m_head
154 * m_head <-0-> A <-0-> B <-0-> C <-0-> m_head
155 */
156
Shuo Chen9a43f162014-07-01 13:43:54 +0800157template<typename T, typename Compare = std::less<T>,
Shuo Chenbf2248d2014-07-12 13:47:20 +0800158 typename Traits = SkipList32Levels25Probabilty>
Shuo Chen9a43f162014-07-01 13:43:54 +0800159class SkipList
160{
161public:
Shuo Chenbf2248d2014-07-12 13:47:20 +0800162 typedef T value_type;
163 typedef value_type* pointer;
164 typedef const value_type* const_pointer;
165 typedef value_type& reference;
166 typedef const value_type& const_reference;
167 typedef SkipListNode<T> Node;
168 typedef Node* NodePointer;
169 typedef size_t size_type;
170 typedef ptrdiff_t difference_type;
171 typedef SkipListIterator<T, const T&, const T*> const_iterator;
172 /// alias of const_iterator
173 typedef const_iterator iterator;
WeiqiShia79c7782014-12-26 09:42:10 +0800174 typedef SkipListNode<T>* SkipListNodePointer;
Shuo Chen9a43f162014-07-01 13:43:54 +0800175
176public:
177 explicit
Shuo Chenbf2248d2014-07-12 13:47:20 +0800178 SkipList()
179 {
180 initializeHead();
181 }
Shuo Chen9a43f162014-07-01 13:43:54 +0800182
Shuo Chenbf2248d2014-07-12 13:47:20 +0800183 ~SkipList()
184 {
185 clear();
WeiqiShia79c7782014-12-26 09:42:10 +0800186 delete(m_head);
Shuo Chenbf2248d2014-07-12 13:47:20 +0800187 }
188
189 const_iterator
190 begin() const
191 {
192 return const_iterator(*(*m_head).nexts.begin());
193 }
194
195 const_iterator
196 end() const
197 {
198 return const_iterator(m_head);
199 }
200
201 bool
202 empty() const
203 {
204 return *(m_head->nexts.begin()) == m_head;
205 }
Shuo Chen9a43f162014-07-01 13:43:54 +0800206
207 size_t
Shuo Chenbf2248d2014-07-12 13:47:20 +0800208 size() const
209 {
210 return m_size;
211 }
Shuo Chen9a43f162014-07-01 13:43:54 +0800212
Shuo Chenbf2248d2014-07-12 13:47:20 +0800213 const_iterator
214 lower_bound(const T& x) const;
Shuo Chen9a43f162014-07-01 13:43:54 +0800215
Shuo Chenbf2248d2014-07-12 13:47:20 +0800216 const_iterator
217 find(const T& x) const;
Shuo Chen9a43f162014-07-01 13:43:54 +0800218
Shuo Chenbf2248d2014-07-12 13:47:20 +0800219 std::pair<const_iterator, bool>
220 insert(const T& x);
Shuo Chen9a43f162014-07-01 13:43:54 +0800221
Shuo Chenbf2248d2014-07-12 13:47:20 +0800222 const_iterator
223 erase(const_iterator it);
Shuo Chen9a43f162014-07-01 13:43:54 +0800224
Shuo Chenbf2248d2014-07-12 13:47:20 +0800225protected:
Shuo Chen9a43f162014-07-01 13:43:54 +0800226
Shuo Chenbf2248d2014-07-12 13:47:20 +0800227 /*
228 * @brief initialize the node
229 */
230 NodePointer
231 createNode()
232 {
WeiqiShia79c7782014-12-26 09:42:10 +0800233 NodePointer p = new Node;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800234 return p;
235 }
Shuo Chen9a43f162014-07-01 13:43:54 +0800236
Shuo Chenbf2248d2014-07-12 13:47:20 +0800237 /*
238 * @brief initialize the node with given value
239 * @para to be set to the value of node
240 */
241 NodePointer
242 createNode(const T& x)
243 {
WeiqiShia79c7782014-12-26 09:42:10 +0800244 NodePointer p = new Node;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800245 m_dataAllocator.construct(&(p->data), x);
246 return p;
247 }
248
249 /*
250 * @brief destructror of the node
251 * @para given pointer of node to be destructed
252 */
253 void
254 destroyNode(NodePointer p)
255 {
WeiqiShia79c7782014-12-26 09:42:10 +0800256 delete(p);
Shuo Chenbf2248d2014-07-12 13:47:20 +0800257 }
258
259 /*
260 * @brief initialize the head
261 */
262 void
263 initializeHead()
264 {
265 m_head = createNode();
266 m_head->prevs.push_back(m_head);
267 m_head->nexts.push_back(m_head);
268 m_size = 0;
269 }
270
271 /*
272 * @brief destroy all the nodes of skiplist except the head
273 */
274 void
275 clear()
276 {
WeiqiShia79c7782014-12-26 09:42:10 +0800277 NodePointer cur = m_head->nexts.front();
Shuo Chenbf2248d2014-07-12 13:47:20 +0800278 while (cur != m_head) {
279 NodePointer tmp = cur;
WeiqiShia79c7782014-12-26 09:42:10 +0800280 cur = cur->nexts.front();
Shuo Chenbf2248d2014-07-12 13:47:20 +0800281 destroyNode(tmp);
282 }
WeiqiShia79c7782014-12-26 09:42:10 +0800283 m_head->nexts.front() = m_head;
284 m_head->prevs.front() = m_head;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800285 }
286
287 /*
288 * @brief pick a random height for inserted skiplist entry
289 */
Shuo Chen9a43f162014-07-01 13:43:54 +0800290 size_t
Shuo Chenbf2248d2014-07-12 13:47:20 +0800291 pickRandomLevel() const
292 {
293 static boost::random::mt19937 gen;
294 static boost::random::geometric_distribution<size_t> dist(Traits::getProbability());
295 return std::min(dist(gen), Traits::getMaxLevels());
296 }
Shuo Chen9a43f162014-07-01 13:43:54 +0800297
Shuo Chenbf2248d2014-07-12 13:47:20 +0800298protected:
299 NodePointer m_head;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800300 std::allocator<T> m_dataAllocator;
Shuo Chen9a43f162014-07-01 13:43:54 +0800301 Compare m_compare;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800302 size_t m_size;
Shuo Chen9a43f162014-07-01 13:43:54 +0800303};
304
Shuo Chenbf2248d2014-07-12 13:47:20 +0800305
Shuo Chen9a43f162014-07-01 13:43:54 +0800306template<typename T, typename Compare, typename Traits>
Shuo Chenbf2248d2014-07-12 13:47:20 +0800307typename SkipList<T, Compare, Traits>::const_iterator
308SkipList<T, Compare, Traits>::lower_bound(const T& x) const
Shuo Chen9a43f162014-07-01 13:43:54 +0800309{
Shuo Chenbf2248d2014-07-12 13:47:20 +0800310 size_t nLevels = m_head->nexts.size();
311 NodePointer p = m_head;
WeiqiShia79c7782014-12-26 09:42:10 +0800312 NodePointer q = p->nexts.back();
Shuo Chenbf2248d2014-07-12 13:47:20 +0800313 for (int i = nLevels - 1; i >= 0; --i) {
WeiqiShia79c7782014-12-26 09:42:10 +0800314 typename std::list<SkipListNodePointer>::iterator it_p = p->nexts.begin();
315 for (int j = 0; j < i; j++) {
316 it_p++;
317 }
318 q = *it_p;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800319 if (q != m_head) {
320 while (m_compare(q->data, x)) {
WeiqiShia79c7782014-12-26 09:42:10 +0800321 p = *it_p;
322 it_p = p->nexts.begin();
323 for (int j = 0; j < i; j++) {
324 it_p++;
325 }
326 q = *it_p;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800327 if (q == m_head) {
328 break;
329 }
330 }
331 }
332 }
333 return const_iterator(q);
Shuo Chen9a43f162014-07-01 13:43:54 +0800334}
335
336template<typename T, typename Compare, typename Traits>
Shuo Chenbf2248d2014-07-12 13:47:20 +0800337typename SkipList<T, Compare, Traits>::const_iterator
338SkipList<T, Compare, Traits>::find(const T& x) const
Shuo Chen9a43f162014-07-01 13:43:54 +0800339{
Shuo Chenbf2248d2014-07-12 13:47:20 +0800340 const_iterator it = this->lower_bound(x);
341 if (it == this->end() || *it != x)
Shuo Chen9a43f162014-07-01 13:43:54 +0800342 return this->end();
343 return it;
344}
345
346template<typename T, typename Compare, typename Traits>
Shuo Chenbf2248d2014-07-12 13:47:20 +0800347std::pair<typename SkipList<T, Compare, Traits>::const_iterator, bool>
348SkipList<T, Compare, Traits>::insert(const T& x)
Shuo Chen9a43f162014-07-01 13:43:54 +0800349{
Shuo Chenbf2248d2014-07-12 13:47:20 +0800350 size_t nLevels = m_head->nexts.size();
351 // 1. find insert position
352 std::vector<NodePointer> insertPositions(nLevels);
353 NodePointer p = m_head;
WeiqiShia79c7782014-12-26 09:42:10 +0800354 NodePointer q = p->nexts.back();
Shuo Chenbf2248d2014-07-12 13:47:20 +0800355 for (int i = nLevels - 1; i >= 0; --i) {
WeiqiShia79c7782014-12-26 09:42:10 +0800356 typename std::list<SkipListNodePointer>::iterator it_p = p->nexts.begin();
357 for (int j = 0; j < i; j++) {
358 it_p++;
359 }
360 q = *it_p;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800361 if (q != m_head) {
362 while (m_compare(q->data, x)) {
WeiqiShia79c7782014-12-26 09:42:10 +0800363 p = *it_p;
364 it_p = p->nexts.begin();
365 for (int j = 0; j < i; j++) {
366 it_p++;
367 }
368 q = *it_p;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800369 if (q == m_head) {
Shuo Chen9a43f162014-07-01 13:43:54 +0800370 break;
371 }
372 }
373 }
Shuo Chenbf2248d2014-07-12 13:47:20 +0800374 insertPositions[i] = p;
375 }
376 // 2. whether q->data == x?
377 if (q != m_head)
378 if (!m_compare(q->data, x) && !m_compare(x, q->data)) {
379 return std::pair<const_iterator, bool>(const_iterator(q), false);
380 }
381 // 3. construct new node;
382 NodePointer newNode = createNode(x);
383 // 4. pick random nLevels
384 size_t newLevel = pickRandomLevel();
385 // 5. insert the new node
386 newNode->nexts.resize(newLevel + 1);
387 newNode->prevs.resize(newLevel + 1);
388 if (newLevel > nLevels - 1) {
389 m_head->nexts.resize(newLevel + 1, m_head);
390 m_head->prevs.resize(newLevel + 1, m_head);
391 insertPositions.resize(newLevel + 1, m_head);
392 }
Wentao Shanga8f3c402014-10-30 14:03:27 -0700393 for (size_t i = 0; i <= newLevel; i++) {
WeiqiShia79c7782014-12-26 09:42:10 +0800394 typename std::list<SkipListNodePointer>::iterator it_newNode_next = newNode->nexts.begin();
395 for (size_t j = 0; j < i; j++) {
396 it_newNode_next++;
397 }
398 typename std::list<SkipListNodePointer>::iterator it_insert_next = insertPositions[i]->nexts.begin();
399 for (size_t j = 0; j < i; j++) {
400 it_insert_next++;
401 }
402 *it_newNode_next = *it_insert_next;
403
404 typename std::list<SkipListNodePointer>::iterator it_newNode_prev = newNode->prevs.begin();
405 for (size_t j = 0; j < i; j++) {
406 it_newNode_prev++;
407 }
408 *it_newNode_prev = insertPositions[i];
409
410 it_insert_next = insertPositions[i]->nexts.begin();
411 for (size_t j = 0; j < i; j++) {
412 it_insert_next++;
413 }
414 *it_insert_next = newNode;
415 it_newNode_next = newNode->nexts.begin();
416 for (size_t j = 0; j < i; j++) {
417 it_newNode_next++;
418 }
419 typename std::list<SkipListNodePointer>::iterator it_newNode_next_prev = (*it_newNode_next)->prevs.begin();
420 for (size_t j = 0; j < i; j++) {
421 it_newNode_next_prev++;
422 }
423 *it_newNode_next_prev = newNode;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800424 }
Shuo Chen9a43f162014-07-01 13:43:54 +0800425
Shuo Chenbf2248d2014-07-12 13:47:20 +0800426 ++m_size;
427 return std::pair<const_iterator, bool>(const_iterator(newNode), true);
428}
Shuo Chen9a43f162014-07-01 13:43:54 +0800429
Shuo Chenbf2248d2014-07-12 13:47:20 +0800430template<typename T, typename Compare, typename Traits>
431typename SkipList<T, Compare, Traits>::const_iterator
432SkipList<T, Compare, Traits>::erase(typename SkipList<T, Compare, Traits>::const_iterator it)
433{
434 NodePointer eraseNode = it.node;
435 if (!empty() && eraseNode != m_head) {
WeiqiShia79c7782014-12-26 09:42:10 +0800436 NodePointer returnNode = eraseNode->nexts.front();
Shuo Chenbf2248d2014-07-12 13:47:20 +0800437 size_t nLevels = eraseNode->nexts.size();
438 for (int i = nLevels - 1; i >= 0; --i) {
WeiqiShia79c7782014-12-26 09:42:10 +0800439 typename std::list<SkipListNodePointer>::iterator it_erase_next = eraseNode->nexts.begin();
440 for (int j = 0; j < i; j++) {
441 it_erase_next++;
442 }
443
444 typename std::list<SkipListNodePointer>::iterator it_erase_next_prev = (*it_erase_next)->prevs.begin();
445 for (int j = 0; j < i; j++) {
446 it_erase_next_prev++;
447 }
448
449 typename std::list<SkipListNodePointer>::iterator it_erase_prev = eraseNode->prevs.begin();
450 for (int j = 0; j < i; j++) {
451 it_erase_prev++;
452 }
453 *it_erase_next_prev = *it_erase_prev;
454
455 typename std::list<SkipListNodePointer>::iterator it_erase_prev_next = (*it_erase_prev)->nexts.begin();
456 for (int j = 0; j < i; j++) {
457 it_erase_prev_next++;
458 }
459
460 *it_erase_prev_next = *it_erase_next;
Shuo Chenbf2248d2014-07-12 13:47:20 +0800461 // clear empty nLevels
WeiqiShia79c7782014-12-26 09:42:10 +0800462 if ((*it_erase_next == *it_erase_prev) && i > 0) {
Shuo Chenbf2248d2014-07-12 13:47:20 +0800463 m_head->nexts.pop_back();
464 m_head->prevs.pop_back();
465 }
466 }
467 destroyNode(eraseNode);
468 --m_size;
469 return const_iterator(returnNode);
Shuo Chen9a43f162014-07-01 13:43:54 +0800470 }
471 else {
472 return end();
473 }
474}
475
WeiqiShia79c7782014-12-26 09:42:10 +0800476} //end namespace update1
Shuo Chen9a43f162014-07-01 13:43:54 +0800477
WeiqiShia79c7782014-12-26 09:42:10 +0800478#endif // REPO_TESTS_UNIT_SKIPLIST_LIST_HPP