块状链表及其实现

来源:互联网 发布:unity3d教程百度云 编辑:程序博客网 时间:2024/06/07 09:34

数组和链表是编程中存储数据的常用方法,两者都用优缺点,数组根据下标直接访问元素,但数组是静态的,有时会造成空间的浪费;链表可以动态申请空间,但访问需要进行遍历。于是乎,块状链表就出来了。

块状链表的结构如下图:


每个节点存储m个数据。节点的定义如下:

struct data{int s,a[2*m+5];data *next;};data *root;

next指向下一个节点,s是该节点的存储的实际数据的大小,a是存储数据的数组。

块状链表支持数据的插入、删除、查询等操作。

(1)插入(insert):数据插入的时候,插入的位置(pos)必须是合法的,也就是说不能大于数据的总数(n)。

数据插入过程:首先找到Pos位于哪个节点中,先将该节点pos及pos后面的数据(如果存在的话)向后移一位,然后将值x插入,将s加1。每个节点的存储的数据上限为2*n,如果达到这个上限,这需要在该节点后面新加一个节点,将m+1到2*m的数据复制到新建的节点。


void insert(int x,int pos){if(root == NULL){root = new(data);root->s = 1;root->a[1] = x;return ;}data *k = root;while(pos > k->s && k->next != NULL){pos -= k->s;k = k->next;}memmove(k->a+pos+1,k->a+pos,sizeof(int)*(k->s - pos +1));k->s++;k->a[pos] = x;if(k->s == 2*m){data *t = new(data);t->next = k->next;k->next = t;memcpy(t->a+1,k->a+m+1,sizeof(int)*m);t->s = k->s = m;}}

(2)删除(delete):插入和删除类似,首先找到pos所在的节点,把Pos后面的数据向前移动一位,然后该节点的s-1。


void del(int pos){data *k = root;while(pos > k->s && k->next != NULL){pos -= k->s;k = k->next;}memmove(k->a+pos,k->a+pos+1,sizeof(int)*(k->s - pos));k->s--;}

(3)查找(find):查找位置为Pos的数,找到pos所在节点,返回该值即可。


int find(int pos){data *k = root;while(pos > k->s && k->next != NULL){pos -= k->s;k = k->next;}return k->a[pos];}


(此段from:点击打开链接)(董的博客)

关键点和复杂度分析

该算法的核心是确定链表长度和每个节点的数组长度,以及怎么保证这个长度值?设块状链表中元素总个数为X,链表长度为n,每个节点中数据长度为m,则当m=n=sqrt(X)时,可保证m和n同时最小,此时各种操作的时间复杂度最低。在实际应用时,需维持块状链表的每个节点大小在[sqrt(n)/2, 2*sqrt(n)],否则,块状链表会退化。维护方法是,适当的时候,对节点进行合并与分裂(维护本身不会使复杂度增加)。


0 0
原创粉丝点击