skiplist.cpp

Bài toán

Cài skip list, thực hiện các thao tác chèn, xóa, tìm kiếm giá trị trong một tập hợp.

Độ phức tạp

Bộ nhớ: trung bình O(n)

Chèn: trung bình O(logn)

Xóa: trung bình O(logn)

Tìm kiếm: trung bình O(logn)

Code này của Nguyễn Tiến Trung Kiên

#include <stdio.h>

#include <stdlib.h>

#include <set>

#include <iostream>

using namespace std;

#define scanf asdfsadfas

#define printf(...) fprintf(stderr, ">"__VA_ARGS__)

#define SetLength(a, n, t) a=(t*)calloc(n, sizeof(t))

#define f0(i,n) for (int i=0; i<n; i++)

#define f1(i,n) for (int i=1; i<=n; i++)

struct node;

node* nil;

struct node {

    int key, height;

    node ** succ;

    node(int _height, int _key){

        height=_height;

        key=_key;

        SetLength(succ, height, node*);

        f0(i,height) succ[i]=nil;

    }

};

struct skip_list {

    int height;

    node* header;

    

    int random_height(int height){

        f1(i,height) if (rand()&1) return i;

        return height;

    }

    

    node* surround(int key, node ** update){

        node* a=header;

        for (int i=height-1; i>=0; i--){

            while (a->succ[i]->key < key) a=a->succ[i];

            update[i]=a;

        }

        return a->succ[0];

    }

    

    node* lower_bound(int key){

        node* a=header;

        for (int i=height-1; i>=0; i--)

        while (a->succ[i]->key < key) a=a->succ[i];

        return a->succ[0];

    }

    

    void insert(int key){

        node* update[height];

        node* a = surround(key, update);

        if (a->key==key) return;

        a=new node(random_height(height), key);

        f0(i,a->height) {

            a->succ[i]=update[i]->succ[i];

            update[i]->succ[i]=a;

        }

    }

    

    void erase(int key){

        node* update[height];

        node* a = surround(key, update);

        if (a->key != key) return ;

        f0(i,a->height) {

            if (update[i]->succ[i] != a) break;

            update[i]->succ[i] = a->succ[i];

        }

        delete a;

    }

    

    void show(){

        for (node* i=header->succ[0]; i!=nil; i=i->succ[0])

        cout << i->key << endl;

    }

    skip_list(int _height){

        if (nil==NULL){

            nil = new node(height, 0x55556666);

            f0(i,height) nil->succ[i]=nil;

        }

        height=_height;

        header=new node(height, -0x55556666);

    }

    

};

skip_list skl(20);

int m;

main(){

    set<int> S;

    S.insert(0x55556666);

    cin >> m;

    for (int i=1; i<=m; i++){

        char c; int x;

        x=rand()%100*1000;

        if (rand()&1) { skl.insert(x); S.insert(x); }

        else if (rand()&1) { skl.erase(x); S.erase(x); }

        else if (rand()&1) {

            int r1 = skl.lower_bound(x)->key;

            int r2 = *S.lower_bound(x);

            assert(r1==r2);

            cout << r1 << endl;

        }

        

        {

            node* i=skl.header->succ[0];

            set<int> :: iterator j=S.begin();

            while (i!=nil) {

                assert(i->key==*j);

                i=i->succ[0], j++;

            }

        }

    }

    

}

Nhận xét

Code trên đã được kiểm tra đọ chính xác bằng cách thực hiện các truy vấn random và so sánh với kiểu std::set.

Tuy nhiên thời gian chạy chưa được kiểm tra.