blob: 8ef1ed98635274484d2843e6c68a0f3c50386e4e [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_VECTOR_HPP
21#define REPO_TESTS_OTHER_SKIPLIST_VECTOR_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 update2 {
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;
50 std::vector<SkipListNodePointer> prevs;
51 std::vector<SkipListNodePointer> nexts;
52};
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
142/*
143 * @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
Shuo Chenbf2248d2014-07-12 13:47:20 +0800230 /*
231 * @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
Shuo Chenbf2248d2014-07-12 13:47:20 +0800240 /*
241 * @brief initialize the node with given value
242 * @para to be set to the value of node
243 */
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
252 /*
253 * @brief destructror of the node
254 * @para given pointer of node to be destructed
255 */
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
262 /*
263 * @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
274 /*
275 * @brief destroy all the nodes of skiplist except the head
276 */
277 void
278 clear()
279 {
280 NodePointer cur = m_head->nexts[0];
281 while (cur != m_head) {
282 NodePointer tmp = cur;
283 cur = cur->nexts[0];
284 destroyNode(tmp);
285 }
286 m_head->nexts[0] = m_head;
287 m_head->prevs[0] = m_head;
288 }
289
290 /*
291 * @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;
315 NodePointer q = p->nexts[nLevels - 1];
316 for (int i = nLevels - 1; i >= 0; --i) {
317 q = p->nexts[i];
318 if (q != m_head) {
319 while (m_compare(q->data, x)) {
320 p = p->nexts[i];
321 q = p->nexts[i];
322 if (q == m_head) {
323 break;
324 }
325 }
326 }
327 }
328 return const_iterator(q);
Shuo Chen9a43f162014-07-01 13:43:54 +0800329}
330
331template<typename T, typename Compare, typename Traits>
Shuo Chenbf2248d2014-07-12 13:47:20 +0800332typename SkipList<T, Compare, Traits>::const_iterator
333SkipList<T, Compare, Traits>::find(const T& x) const
Shuo Chen9a43f162014-07-01 13:43:54 +0800334{
Shuo Chenbf2248d2014-07-12 13:47:20 +0800335 const_iterator it = this->lower_bound(x);
336 if (it == this->end() || *it != x)
Shuo Chen9a43f162014-07-01 13:43:54 +0800337 return this->end();
338 return it;
339}
340
341template<typename T, typename Compare, typename Traits>
Shuo Chenbf2248d2014-07-12 13:47:20 +0800342std::pair<typename SkipList<T, Compare, Traits>::const_iterator, bool>
343SkipList<T, Compare, Traits>::insert(const T& x)
Shuo Chen9a43f162014-07-01 13:43:54 +0800344{
Shuo Chenbf2248d2014-07-12 13:47:20 +0800345 size_t nLevels = m_head->nexts.size();
346 // 1. find insert position
347 std::vector<NodePointer> insertPositions(nLevels);
348 NodePointer p = m_head;
349 NodePointer q = p->nexts[nLevels - 1];
350 for (int i = nLevels - 1; i >= 0; --i) {
351 q = p->nexts[i];
352 if (q != m_head) {
353 while (m_compare(q->data, x)) {
354 p = p->nexts[i];
355 q = p->nexts[i];
356 if (q == m_head) {
Shuo Chen9a43f162014-07-01 13:43:54 +0800357 break;
358 }
359 }
360 }
Shuo Chenbf2248d2014-07-12 13:47:20 +0800361 insertPositions[i] = p;
362 }
363 // 2. whether q->data == x?
364 if (q != m_head)
365 if (!m_compare(q->data, x) && !m_compare(x, q->data)) {
366 return std::pair<const_iterator, bool>(const_iterator(q), false);
367 }
368 // 3. construct new node;
369 NodePointer newNode = createNode(x);
370 // 4. pick random nLevels
371 size_t newLevel = pickRandomLevel();
372 // 5. insert the new node
373 newNode->nexts.resize(newLevel + 1);
374 newNode->prevs.resize(newLevel + 1);
375 if (newLevel > nLevels - 1) {
376 m_head->nexts.resize(newLevel + 1, m_head);
377 m_head->prevs.resize(newLevel + 1, m_head);
378 insertPositions.resize(newLevel + 1, m_head);
379 }
Wentao Shanga8f3c402014-10-30 14:03:27 -0700380 for (size_t i = 0; i <= newLevel; i++) {
Shuo Chenbf2248d2014-07-12 13:47:20 +0800381 newNode->nexts[i] = insertPositions[i]->nexts[i];
382 newNode->prevs[i] = insertPositions[i];
383 insertPositions[i]->nexts[i] = newNode;
384 newNode->nexts[i]->prevs[i] = newNode;
385 }
Shuo Chen9a43f162014-07-01 13:43:54 +0800386
Shuo Chenbf2248d2014-07-12 13:47:20 +0800387 ++m_size;
388 return std::pair<const_iterator, bool>(const_iterator(newNode), true);
389}
Shuo Chen9a43f162014-07-01 13:43:54 +0800390
Shuo Chenbf2248d2014-07-12 13:47:20 +0800391template<typename T, typename Compare, typename Traits>
392typename SkipList<T, Compare, Traits>::const_iterator
393SkipList<T, Compare, Traits>::erase(typename SkipList<T, Compare, Traits>::const_iterator it)
394{
395 NodePointer eraseNode = it.node;
396 if (!empty() && eraseNode != m_head) {
397 NodePointer returnNode = eraseNode->nexts[0];
398 size_t nLevels = eraseNode->nexts.size();
399 for (int i = nLevels - 1; i >= 0; --i) {
400 eraseNode->nexts[i]->prevs[i] = eraseNode->prevs[i];
401 eraseNode->prevs[i]->nexts[i] = eraseNode->nexts[i];
402 // clear empty nLevels
403 if ((eraseNode->nexts[i] == eraseNode->prevs[i]) && i > 0) {
404 m_head->nexts.pop_back();
405 m_head->prevs.pop_back();
406 }
407 }
408 destroyNode(eraseNode);
409 --m_size;
410 return const_iterator(returnNode);
Shuo Chen9a43f162014-07-01 13:43:54 +0800411 }
412 else {
413 return end();
414 }
WeiqiShia79c7782014-12-26 09:42:10 +0800415
Shuo Chen9a43f162014-07-01 13:43:54 +0800416}
417
Davide Pesavento49f3a5f2017-09-23 01:36:33 -0400418} // namespace update2
Shuo Chen9a43f162014-07-01 13:43:54 +0800419
WeiqiShia79c7782014-12-26 09:42:10 +0800420#endif // REPO_TESTS_OTHER_SKIPLIST_VECTOR_HPP