blob: 6079dd3bc54ee0daa7cd471187c09a8c1d169deb [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_VECTOR_HPP
21#define REPO_TESTS_OTHER_SKIPLIST_VECTOR_HPP
Shuo Chen9a43f162014-07-01 13:43:54 +080022#include "common.hpp"
23
WeiqiShia79c7782014-12-26 09:42:10 +080024namespace update2 {
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;
47 std::vector<SkipListNodePointer> prevs;
48 std::vector<SkipListNodePointer> nexts;
49};
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 {
277 NodePointer cur = m_head->nexts[0];
278 while (cur != m_head) {
279 NodePointer tmp = cur;
280 cur = cur->nexts[0];
281 destroyNode(tmp);
282 }
283 m_head->nexts[0] = m_head;
284 m_head->prevs[0] = m_head;
285 }
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;
312 NodePointer q = p->nexts[nLevels - 1];
313 for (int i = nLevels - 1; i >= 0; --i) {
314 q = p->nexts[i];
315 if (q != m_head) {
316 while (m_compare(q->data, x)) {
317 p = p->nexts[i];
318 q = p->nexts[i];
319 if (q == m_head) {
320 break;
321 }
322 }
323 }
324 }
325 return const_iterator(q);
Shuo Chen9a43f162014-07-01 13:43:54 +0800326}
327
328template<typename T, typename Compare, typename Traits>
Shuo Chenbf2248d2014-07-12 13:47:20 +0800329typename SkipList<T, Compare, Traits>::const_iterator
330SkipList<T, Compare, Traits>::find(const T& x) const
Shuo Chen9a43f162014-07-01 13:43:54 +0800331{
Shuo Chenbf2248d2014-07-12 13:47:20 +0800332 const_iterator it = this->lower_bound(x);
333 if (it == this->end() || *it != x)
Shuo Chen9a43f162014-07-01 13:43:54 +0800334 return this->end();
335 return it;
336}
337
338template<typename T, typename Compare, typename Traits>
Shuo Chenbf2248d2014-07-12 13:47:20 +0800339std::pair<typename SkipList<T, Compare, Traits>::const_iterator, bool>
340SkipList<T, Compare, Traits>::insert(const T& x)
Shuo Chen9a43f162014-07-01 13:43:54 +0800341{
Shuo Chenbf2248d2014-07-12 13:47:20 +0800342 size_t nLevels = m_head->nexts.size();
343 // 1. find insert position
344 std::vector<NodePointer> insertPositions(nLevels);
345 NodePointer p = m_head;
346 NodePointer q = p->nexts[nLevels - 1];
347 for (int i = nLevels - 1; i >= 0; --i) {
348 q = p->nexts[i];
349 if (q != m_head) {
350 while (m_compare(q->data, x)) {
351 p = p->nexts[i];
352 q = p->nexts[i];
353 if (q == m_head) {
Shuo Chen9a43f162014-07-01 13:43:54 +0800354 break;
355 }
356 }
357 }
Shuo Chenbf2248d2014-07-12 13:47:20 +0800358 insertPositions[i] = p;
359 }
360 // 2. whether q->data == x?
361 if (q != m_head)
362 if (!m_compare(q->data, x) && !m_compare(x, q->data)) {
363 return std::pair<const_iterator, bool>(const_iterator(q), false);
364 }
365 // 3. construct new node;
366 NodePointer newNode = createNode(x);
367 // 4. pick random nLevels
368 size_t newLevel = pickRandomLevel();
369 // 5. insert the new node
370 newNode->nexts.resize(newLevel + 1);
371 newNode->prevs.resize(newLevel + 1);
372 if (newLevel > nLevels - 1) {
373 m_head->nexts.resize(newLevel + 1, m_head);
374 m_head->prevs.resize(newLevel + 1, m_head);
375 insertPositions.resize(newLevel + 1, m_head);
376 }
Wentao Shanga8f3c402014-10-30 14:03:27 -0700377 for (size_t i = 0; i <= newLevel; i++) {
Shuo Chenbf2248d2014-07-12 13:47:20 +0800378 newNode->nexts[i] = insertPositions[i]->nexts[i];
379 newNode->prevs[i] = insertPositions[i];
380 insertPositions[i]->nexts[i] = newNode;
381 newNode->nexts[i]->prevs[i] = newNode;
382 }
Shuo Chen9a43f162014-07-01 13:43:54 +0800383
Shuo Chenbf2248d2014-07-12 13:47:20 +0800384 ++m_size;
385 return std::pair<const_iterator, bool>(const_iterator(newNode), true);
386}
Shuo Chen9a43f162014-07-01 13:43:54 +0800387
Shuo Chenbf2248d2014-07-12 13:47:20 +0800388template<typename T, typename Compare, typename Traits>
389typename SkipList<T, Compare, Traits>::const_iterator
390SkipList<T, Compare, Traits>::erase(typename SkipList<T, Compare, Traits>::const_iterator it)
391{
392 NodePointer eraseNode = it.node;
393 if (!empty() && eraseNode != m_head) {
394 NodePointer returnNode = eraseNode->nexts[0];
395 size_t nLevels = eraseNode->nexts.size();
396 for (int i = nLevels - 1; i >= 0; --i) {
397 eraseNode->nexts[i]->prevs[i] = eraseNode->prevs[i];
398 eraseNode->prevs[i]->nexts[i] = eraseNode->nexts[i];
399 // clear empty nLevels
400 if ((eraseNode->nexts[i] == eraseNode->prevs[i]) && i > 0) {
401 m_head->nexts.pop_back();
402 m_head->prevs.pop_back();
403 }
404 }
405 destroyNode(eraseNode);
406 --m_size;
407 return const_iterator(returnNode);
Shuo Chen9a43f162014-07-01 13:43:54 +0800408 }
409 else {
410 return end();
411 }
WeiqiShia79c7782014-12-26 09:42:10 +0800412
Shuo Chen9a43f162014-07-01 13:43:54 +0800413}
414
WeiqiShia79c7782014-12-26 09:42:10 +0800415} //end namespace update2
Shuo Chen9a43f162014-07-01 13:43:54 +0800416
WeiqiShia79c7782014-12-26 09:42:10 +0800417#endif // REPO_TESTS_OTHER_SKIPLIST_VECTOR_HPP