SkipList.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /* Copyright (c) 2019 The Linux Foundation. All rights reserved.
  2. *
  3. * Redistribution and use in source and binary forms, with or without
  4. * modification, are permitted provided that the following conditions are
  5. * met:
  6. * * Redistributions of source code must retain the above copyright
  7. * notice, this list of conditions and the following disclaimer.
  8. * * Redistributions in binary form must reproduce the above
  9. * copyright notice, this list of conditions and the following
  10. * disclaimer in the documentation and/or other materials provided
  11. * with the distribution.
  12. * * Neither the name of The Linux Foundation, nor the names of its
  13. * contributors may be used to endorse or promote products derived
  14. * from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
  17. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  18. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  20. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  21. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  22. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  23. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  24. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  25. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
  26. * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. *
  28. */
  29. #ifndef LOC_SKIP_LIST_H
  30. #define LOC_SKIP_LIST_H
  31. #include <stdlib.h>
  32. #include <list>
  33. #include <vector>
  34. #include <iostream>
  35. #include <algorithm>
  36. using namespace std;
  37. namespace loc_util {
  38. template <typename T,
  39. template<typename elem, typename Allocator = std::allocator<elem>> class container = list>
  40. class SkipNode {
  41. public:
  42. typedef typename container<SkipNode<T, container>>::iterator NodeIterator;
  43. int mLevel;
  44. T mData;
  45. NodeIterator mNextInLevel;
  46. SkipNode(int level, T& data): mLevel(level), mData(data) {}
  47. };
  48. template <typename T>
  49. class SkipList {
  50. using NodeIterator = typename SkipNode<T>::NodeIterator;
  51. private:
  52. list<SkipNode<T>> mMainList;
  53. vector<NodeIterator> mHeadVec;
  54. vector<NodeIterator> mTailVec;
  55. public:
  56. SkipList(int totalLevels);
  57. void append(T& data, int level);
  58. void pop(int level);
  59. void pop();
  60. T front(int level);
  61. int size();
  62. void flush();
  63. list<pair<T, int>> dump();
  64. list<pair<T, int>> dump(int level);
  65. };
  66. template <typename T>
  67. SkipList<T>::SkipList(int totalLevels): mHeadVec(totalLevels, mMainList.end()),
  68. mTailVec(totalLevels, mMainList.end()) {}
  69. template <typename T>
  70. void SkipList<T>::append(T& data, int level) {
  71. if ( level < 0 || level >= mHeadVec.size()) {
  72. return;
  73. }
  74. SkipNode<T> node(level, data);
  75. node.mNextInLevel = mMainList.end();
  76. mMainList.push_back(node);
  77. auto iter = --mMainList.end();
  78. if (mHeadVec[level] == mMainList.end()) {
  79. mHeadVec[level] = iter;
  80. } else {
  81. (*mTailVec[level]).mNextInLevel = iter;
  82. }
  83. mTailVec[level] = iter;
  84. }
  85. template <typename T>
  86. void SkipList<T>::pop(int level) {
  87. if (mHeadVec[level] == mMainList.end()) {
  88. return;
  89. }
  90. if ((*mHeadVec[level]).mNextInLevel == mMainList.end()) {
  91. mTailVec[level] = mMainList.end();
  92. }
  93. auto tmp_iter = (*mHeadVec[level]).mNextInLevel;
  94. mMainList.erase(mHeadVec[level]);
  95. mHeadVec[level] = tmp_iter;
  96. }
  97. template <typename T>
  98. void SkipList<T>::pop() {
  99. pop(mMainList.front().mLevel);
  100. }
  101. template <typename T>
  102. T SkipList<T>::front(int level) {
  103. return (*mHeadVec[level]).mData;
  104. }
  105. template <typename T>
  106. int SkipList<T>::size() {
  107. return mMainList.size();
  108. }
  109. template <typename T>
  110. void SkipList<T>::flush() {
  111. mMainList.clear();
  112. for (int i = 0; i < mHeadVec.size(); i++) {
  113. mHeadVec[i] = mMainList.end();
  114. mTailVec[i] = mMainList.end();
  115. }
  116. }
  117. template <typename T>
  118. list<pair<T, int>> SkipList<T>::dump() {
  119. list<pair<T, int>> li;
  120. for_each(mMainList.begin(), mMainList.end(), [&](SkipNode<T> &item) {
  121. li.push_back(make_pair(item.mData, item.mLevel));
  122. });
  123. return li;
  124. }
  125. template <typename T>
  126. list<pair<T, int>> SkipList<T>::dump(int level) {
  127. list<pair<T, int>> li;
  128. auto head = mHeadVec[level];
  129. while (head != mMainList.end()) {
  130. li.push_back(make_pair((*head).mData, (*head).mLevel));
  131. head = (*head).mNextInLevel;
  132. }
  133. return li;
  134. }
  135. }
  136. #endif