/* Copyright (c) 2019 The Linux Foundation. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of The Linux Foundation, nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * */ #ifndef LOC_SKIP_LIST_H #define LOC_SKIP_LIST_H #include #include #include #include #include using namespace std; namespace loc_util { template > class container = list> class SkipNode { public: typedef typename container>::iterator NodeIterator; int mLevel; T mData; NodeIterator mNextInLevel; SkipNode(int level, T& data): mLevel(level), mData(data) {} }; template class SkipList { using NodeIterator = typename SkipNode::NodeIterator; private: list> mMainList; vector mHeadVec; vector mTailVec; public: SkipList(int totalLevels); void append(T& data, int level); void pop(int level); void pop(); T front(int level); int size(); void flush(); list> dump(); list> dump(int level); }; template SkipList::SkipList(int totalLevels): mHeadVec(totalLevels, mMainList.end()), mTailVec(totalLevels, mMainList.end()) {} template void SkipList::append(T& data, int level) { if ( level < 0 || level >= mHeadVec.size()) { return; } SkipNode node(level, data); node.mNextInLevel = mMainList.end(); mMainList.push_back(node); auto iter = --mMainList.end(); if (mHeadVec[level] == mMainList.end()) { mHeadVec[level] = iter; } else { (*mTailVec[level]).mNextInLevel = iter; } mTailVec[level] = iter; } template void SkipList::pop(int level) { if (mHeadVec[level] == mMainList.end()) { return; } if ((*mHeadVec[level]).mNextInLevel == mMainList.end()) { mTailVec[level] = mMainList.end(); } auto tmp_iter = (*mHeadVec[level]).mNextInLevel; mMainList.erase(mHeadVec[level]); mHeadVec[level] = tmp_iter; } template void SkipList::pop() { pop(mMainList.front().mLevel); } template T SkipList::front(int level) { return (*mHeadVec[level]).mData; } template int SkipList::size() { return mMainList.size(); } template void SkipList::flush() { mMainList.clear(); for (int i = 0; i < mHeadVec.size(); i++) { mHeadVec[i] = mMainList.end(); mTailVec[i] = mMainList.end(); } } template list> SkipList::dump() { list> li; for_each(mMainList.begin(), mMainList.end(), [&](SkipNode &item) { li.push_back(make_pair(item.mData, item.mLevel)); }); return li; } template list> SkipList::dump(int level) { list> li; auto head = mHeadVec[level]; while (head != mMainList.end()) { li.push_back(make_pair((*head).mData, (*head).mLevel)); head = (*head).mNextInLevel; } return li; } } #endif