跳跃表的实现(c++)

跳跃表简单的说就是个能够提供快车道(区间的索引)实现快速访问的有序链表,普通的链表的查找复杂度是n,这个复杂度太大了,跳跃表查找插入删除都在lg(n)的复杂度,是一种随手就能写出来的数据结构(为什么这么说呢,因为其它lg(n)的可以来实现查找的数据结构实在包含挺多细节的,对我这种渣渣来说每次看完红黑树过不了多久我就会忘了它的操作细节了,只记得它通过维护颜色的平衡来实现树的平衡,更别说随手写了)。关于跳跃表这里就不做介绍了,如果还没了解过这个数据结构的话还是看一遍《算法导论公开课 跳跃表》,才知道跳跃表的理论基础以及推导过程。

代码中有一个容易误解的地方解释一下,randomLevel模拟抛硬币的过程比较不太直观,在插入过程中一个节点上升的次数实际上等价于连续出现“正面”的次数,所以我们直接一次性算出来,而不是每插完一个节点抛一次硬币,这样方便在进行实际插入之前进行一些检查
还有由于插入提升节点的过程中,需要知道往上提升的位置,所以每次往下走的时候都要记住走下来的位置,我们用updateNode记住这个位置,其它的就是普通链表的细节了
本代码没有做边界检查和验证,仅做简单的实现示范使用

//List.h
#include <iostream>

namespace OJP {

    template<typename T>
        class Node {
            public:
                Node* next;
                Node* down;
                T val;
            public:
                void setNext(Node* next) {
                    this->next = next;
                }

                Node(const T& val) {
                    this->val = val;
                    this->next = NULL;
                }

                Node() {
                    this->next = NULL;
                    this->down = NULL;
                }
        };

    template<typename T>
        class List {
            public:
                Node<T>* head;
                Node<T>* end;
            public:
                List() {
                    head = new Node<T>();
                    end = NULL;
                    head->next = end;
                    head->down = NULL;
                }

                void pushBack(const T& val) {
                    auto node = new Node<T>(val);
                    auto tmp = head;
                    while(tmp->next != end) {
                        tmp = tmp->next;
                    }
                    node->next = end;
                    tmp->next = node;
                }

                void insert(Node<T>* node, const T& val) {
                    auto newNode = new Node<T>(val);
                    newNode->next = node->next;
                    node->next = newNode;
                }

                Node<T>* find(const T& val) {
                    auto tmp = head->next;
                    while(tmp != end) {
                        if(tmp->val == val) {
                            return tmp;
                        }
                        tmp = tmp->next;
                    }
                    return NULL;
                }

                Node<T>* findLastLEOf(const T& t, Node<T>* node = NULL) {
                    auto tmp = head;
                    if(node != NULL) {
                        tmp = node;
                        if(tmp != head && tmp->val > t) {
                            return NULL;
                        }
                    }
                    while(tmp->next != end && tmp->next->val <= t) {
                        tmp = tmp->next;
                    }
                    return tmp;
                }

                Node<T>* findLastLessOf(const T& t, Node<T>* node = NULL) {
                    auto tmp = head;
                    if(node != NULL) {
                        tmp = node;
                        if(tmp != head && tmp->val >= t) {
                            return NULL;
                        }
                    }
                    while(tmp->next != end && tmp->next->val < t) {
                        tmp = tmp->next;
                    }
                    return tmp;
                }

                bool remove(const T& t, Node<T>* after) {
                    auto tmp = head;
                    if(after != NULL) {
                        tmp = after;
                    }
                    while(tmp->next != end) {
                        if(tmp->next->val > t) {
                            return false;
                        }
                        if(tmp->next->val == t) {
                            Node<T>* delNode = tmp->next;
                            tmp->next = tmp->next->next;
                            delete delNode;
                            return true;
                        }
                    }
                    return false;
                }

                void for_each(void (*func)(const T& )) {
                    auto tmp = head->next;
                    while(tmp != end) {
                        func(tmp->val);
                        tmp = tmp->next;
                    }
                }

                ~List() {
                    auto tmp = head->next;
                    while(tmp != end) {
                        Node<T>* node = tmp;
                        tmp = tmp->next;
                        delete node;
                    }
                }
        };
}

template<typename T>
void print(const T& a) {
    std::cout<<a<<" ";
}
//SkipList.cpp
#include "List.h"
using namespace std;

template<typename T>
class SkipList {
    private:
        OJP::List<T>* lists;
        static const int initialLevel = 64;
        int level;

    public:
        SkipList() {
            lists = new OJP::List<T>[initialLevel];
            for(int i = 1; i < initialLevel; i++) {
                lists[i].head->down = lists[i - 1].head;
            }
            level = 0;
        }

        static int randomLevel() {
            int i = 0;
            while(rand() % 2 == 1) {
                i++;
            }
            return i;
        }

        bool push(const T& t) {
            auto updateNode = new OJP::Node<T>*[initialLevel];
            for(int i = 0; i < initialLevel; i++) {
                updateNode[i] = lists[i].head;
            }

            int updateLevel = level;
            auto searchFrom = lists[updateLevel].head;
            while(updateLevel >= 0) {
                OJP::List<T>* list = &lists[updateLevel];
                updateNode[updateLevel] = list->findLastLEOf(t, searchFrom);
                searchFrom = updateNode[updateLevel]->down;
                if(searchFrom != NULL) {
                }
                updateLevel--;
            }

            if(updateNode[0]->val == t) {
                return false;
            } else {
                lists[0].insert(updateNode[0], t);

                int newLevel = randomLevel();
                if(newLevel > initialLevel - 1) {
                    return false;
                } else if(newLevel > level) {
                    level = newLevel;
                }

                updateLevel = 0;
                while(updateLevel < newLevel) {
                    ++updateLevel;
                    lists[updateLevel].insert(updateNode[updateLevel], t);
                    updateNode[updateLevel]->next->down = updateNode[updateLevel - 1]->next;
                }
            }
            return false;
        }

        bool find(const T& t) {
            int searchLevel = level;
            auto searchFrom = lists[searchLevel].head;
            while(searchLevel >= 0) {
                OJP::List<T>* list = &lists[searchLevel];
                searchFrom = list->findLastLEOf(t, searchFrom);
                if(searchFrom->down && searchLevel > 0) {
                    searchFrom = searchFrom->down;
                }
                searchLevel--;
            }
            if(searchFrom->val == t && searchFrom != lists[0].head) {
                return true;
            }
            return false;
        }

        bool remove(const T& t) {
            int searchLevel = level;
            auto searchFrom = lists[searchLevel].head;
            while(searchLevel >= 0) {
                OJP::List<T>* list = &lists[searchLevel];
                searchFrom = list->findLastLessOf(t, searchFrom);
                list->remove(t, searchFrom);
                if(searchFrom->down && searchLevel > 0) {
                    searchFrom = searchFrom->down;
                }
                searchLevel--;
            }
            if(searchFrom->val == t && searchFrom != lists[0].head) {
                return true;
            }
            return false;
        }

        ~SkipList() {
            delete []lists;
        }

        void dump() {
            for(int i = level; i >= 0; i--) {
                cout<<"level["<<i<<"]: ";
                lists[i].for_each(print);
                cout<<endl;
            }
        }

};

int main() {
    SkipList<int> skipList = SkipList<int>();
    for(int i = 0; i < 100000; i++) {
        int val = rand() % 100000;
        cout<<"push "<<val<<endl;
        skipList.push(val);
    }
    for(int i = 0; i < 100000; i++) {
        int val = rand() % 100000;
        cout<<"find "<<val<<" "<<skipList.find(val)<<endl;
    }
    /*
    skipList.dump();
    skipList.remove(79);
    skipList.remove(92);
    skipList.remove(99);
    skipList.dump();*/
    return 0;
}
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值