块状链表的数据结构。

首先,块状链表是数组和链表的结合体。我们知道,在数组中删除,插入一个元素的复杂度是O(n),在链表中,插入和删除的复杂度是O(1)。 而在链表中,查找的复杂度是O(n)的,数组中是O(1)的。于是就有人想到一个方法,把数组放在链表里面,形成块状链表。这里给出结论,块状数组的查询删除插入复杂度为O(x+N/x) 这里的x为块的大小N为元素个数。

在普通链表里面    data1 -->data2-->data3--------             块状链表里面    data1【n】-->data2【n】------

 

我们先用C++里面的容器来生成动态数组会比较好一点。并且,像链表一样,写一个next,不过在这里我是用数组存下一个地址的,当然用指针也是可以的。既然,我用数组,那么我一开始就必须得初始化一下这个next数组了,并且全都至为0。方便后面的操作。

我们先讲插入,如果我们的插入位置,小于第一块块状链表里面的数组大小的话,那么我们就插在这一块。如果插入位置超出了这一块,那么我们就顺着next数组指向的地址去插入下一块块状数组里面的数组。如果还是没有就一直找下去,直到出现可以插入的位置。并且,最重要的是,在插入的时候如果这个数组的大小超过了我们想要分配的数组的大小,我们就要进行分割了。做法也很简单,就是将后半段的数据直接丢到下一个块里面去就好了。这个时候必然会有分割块所占区域小于我们想要分割的大小。

接下来就是读取数据了。这个和插入差不多,就是属于找位置,如果超过第一块的数组大小的话,就去找连接的那块,就一直找下去,直到找到自己的位置。

#include<bits/stdc++.h> 
using namespace std;
const int maxn=100005;
int maxlen;       //由均值不等式得  O(x+n/x)  x=sqrt(n)得时候时间复杂度最低。
int n;
struct node
{
    int next[maxn];
    vector<int> block[maxn];
    int top;
    node()
    {
        clear();
    }
    void clear()
    {
        for(int i = 0; i<maxn ; i++)
        {
            next[i]=0;
            block[i].clear();
        }
        top=1;
    }
    void insert(int index,int value)
    {
        int id=1;
        while(id)
        {
            if(index <= block[id].size())
            {
                block[id].insert(block[id].begin()+index,value);
                if(block[id].size()>maxlen)
                {
                    sqlit(id);
                }
                return ;
            }
            else
            {
                index-=block[id].size();
                id = next[id];
            }
        }
    }
    void sqlit(int id)
    {
        top++;
        int siz = block[id].size()/2;
        block[top].assign(block[id].begin()+siz,block[id].end()); //替换
        block[id].resize(siz);//清除 siz后面的。
        next[top] = next[id];
        next[id] = top;
    }
    int get(int index)
    {
        int id=1;
        while(id)
        {
            if(index < block[id].size())
            {
                return block[id][index];
            }
            else
            {
                index-=block[id].size();
                id = next[id];
            }
        }
    }
    void dele(int index)
    {
        int id = 1;
        while(id)
        {

            if(block[id].size() > index)
            {
                block[id].erase(block[id].begin()+index);
                return ;
            }
            else
            {
                index -=block[id].size();
                id = next[id];
            }
        }
    }
} arr;
int main()
{
   int q;
    scanf("%d %d",&n,&q);
    maxlen=sqrt(n)+1;
    for(int i = 0 ;i<n;i++)
    {
        int x;
        scanf("%d",&x);
        arr.insert(i,x);
    }
   cout << arr.get(5) <<endl;
}

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值