关闭

块状链表及其实现

标签: 数据结构块状链表
136人阅读 评论(0) 收藏 举报
分类:

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

块状链表的结构如下图:


每个节点存储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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:24558次
    • 积分:916
    • 等级:
    • 排名:千里之外
    • 原创:70篇
    • 转载:1篇
    • 译文:1篇
    • 评论:0条
    最新评论