块状链表之代码分析

http://blog.csdn.net/bin314/article/details/7900427

对块状链表不熟悉的请移步

块状链表解析

1.链表节点(block):

block加入模板

template<class ElemType>

构造函数

block<ElemType>(block<ElemType>* to,block<ElemType>* p):next(to),pre(p)


①:属性

    ElemType data[MAXN];
    int len ;	/*本block有效数据的长度*/
    bool rev ;
    block<ElemType> *next , *pre ;


 

并添加基本操作:分割,合并,删除下一个块

②:分割

在本块的指定位置处分割

void split(int pos)	/*分裂,在pos处,分裂成->[0,pos)->[pos,len)->*/
    {
        if( pos >= len || pos <= 0 ) return ;	/*非法位置*/
        if( this->rev )/*在某例中可能出现的反转情况*/
        {
            reverse(this->data,this->data+this->len);
            this->rev = 0 ;
        }
        block<ElemType>* newblock = new block<ElemType>(this->next,this);
        if( this->next != NULL )	this->next->pre = newblock ;
        this->next = newblock ;
        /*注意修改一些基本的field*/
        newblock->len = len - pos ;
        newblock->setData(data+pos,len-pos);<span style="white-space: pre;">	</span>/*赋值*/
        this->len = pos ;	/*完成[0,pos)的分裂*/
    }


 

③:合并

本块合并掉下一块

    bool Union()	/*当下一块和本块数据之和 < maxn 的时候可以合并*/
    {
        block<ElemType>* nextBlock = this->next ;
        if( nextBlock == NULL ) return false ;
        if( nextBlock->len + this->len > maxn ) return false ;
        /*合并*/

        if( this->rev )
        {
            reverse(this->data,this->data+this->len);
            this->rev = 0 ;
        }
        if( nextBlock->rev )
        {
            reverse(nextBlock->data,nextBlock->data+nextBlock->len);
            nextBlock->rev = 0 ;
        }

        this->next = nextBlock->next ;
        if( nextBlock->next != NULL ) nextBlock->next->pre = this ;
        int i ;
        for( i = 0 ; i < nextBlock->len ; i++) data[this->len++] = nextBlock->data[i] ;
        delete nextBlock;
        return true ;
    }


 

    bool Union()	/*当下一块和本块数据之和 < maxn 的时候可以合并*/
    {
        block<ElemType>* nextBlock = this->next ;
        if( nextBlock == NULL ) return false ;
        if( nextBlock->len + this->len > maxn ) return false ;
        /*合并*/

        if( this->rev )
        {
            reverse(this->data,this->data+this->len);
            this->rev = 0 ;
        }
        if( nextBlock->rev )
        {
            reverse(nextBlock->data,nextBlock->data+nextBlock->len);
            nextBlock->rev = 0 ;
        }

        this->next = nextBlock->next ;
        if( nextBlock->next != NULL ) nextBlock->next->pre = this ;
        int i ;
        for( i = 0 ; i < nextBlock->len ; i++) data[this->len++] = nextBlock->data[i] ;
        delete nextBlock;
        return true ;
    }

④:删除

    void del()	/*delete the next block*/
    {
        block<ElemType> * nextBlock = this->next ;
        if( nextBlock == NULL ) return ;
        this->next = nextBlock->next ;
        if( nextBlock->next != NULL )		nextBlock->next->pre = this ;
        delete nextBlock ;
    }


2.blocklist的编写

这里就是一个链表,节点为block,针对具体情况有不同的操作。

附个editor和反转列表完整代码(合并在一起了)

#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <iostream>
#include <string>
#include <math.h>
#include <time.h>
#include <vector>
#include <queue>
#include <algorithm>

#define showArray(a,len) for( i = 0 ; i < len ; i++) printf("%d ",*(a+i)); puts("");

/************************************************************************/
/* 块状链表                                                             */
/************************************************************************/

using namespace std;

/*

  insert 3
  1 2 3
  insert 3
  1 2 3
  delete 3
  show 9

*/

const int MAXN = 300 ;

template<class ElemType>
class block
{
    public:
    static int maxn ;
    ElemType data[MAXN];
    int len ;	/*本block有效数据的长度*/
    bool rev ;
    block<ElemType> *next , *pre ;
    block<ElemType>(block<ElemType>* to,block<ElemType>* p):next(to),pre(p)
    {
        len = 0 ;
        rev = false ;
    }
    /*注意pos=0,len的情况
    	1 <= pos < len
    */
    void split(int pos)	/*分裂,在pos处,分裂成->[0,pos)->[pos,len)->*/
    {
        if( pos >= len || pos <= 0 ) return ;	/*非法位置*/
        if( this->rev )
        {
            reverse(this->data,this->data+this->len);
            this->rev = 0 ;
        }
        block<ElemType>* newblock = new block<ElemType>(this->next,this);
        if( this->next != NULL )	this->next->pre = newblock ;
        this->next = newblock ;
        /*注意修改一些基本的field*/
        newblock->len = len - pos ;
        //strcpy((char*)newblock->data,(char*)&data[pos]);	/*完成[pos,len)的分裂*/
        newblock->setData(data+pos,len-pos);
        this->len = pos ;	/*完成[0,pos)的分裂*/
    }
    bool Union()	/*当下一块和本块数据之和 < maxn 的时候可以合并*/
    {
        block<ElemType>* nextBlock = this->next ;
        if( nextBlock == NULL ) return false ;
        if( nextBlock->len + this->len > maxn ) return false ;
        /*合并*/

        if( this->rev )
        {
            reverse(this->data,this->data+this->len);
            this->rev = 0 ;
        }
        if( nextBlock->rev )
        {
            reverse(nextBlock->data,nextBlock->data+nextBlock->len);
            nextBlock->rev = 0 ;
        }

        this->next = nextBlock->next ;
        if( nextBlock->next != NULL ) nextBlock->next->pre = this ;
        //strcpy((char*)&this->data[len],(char*)nextBlock->data);
        int i ;
        for( i = 0 ; i < nextBlock->len ; i++) data[this->len++] = nextBlock->data[i] ;
        delete nextBlock;
        return true ;
    }
    ElemType select(int k)
    {
        if( k < len && k >= 0 )
            return data[k] ;
        return 0 ;
    }
    void del()	/*delete the next block*/
    {
        block<ElemType> * nextBlock = this->next ;
        if( nextBlock == NULL ) return ;
        this->next = nextBlock->next ;
        if( nextBlock->next != NULL )		nextBlock->next->pre = this ;
        delete nextBlock ;
    }
    void setData(ElemType array[],int len)
    {
        this->len = len ;
        int i ;
        for( i = 0 ; i < len ; i++) this->data[i] = array[i] ;
    }
};

template<class ElemType>
int block<ElemType>::maxn = MAXN ;

template<class ElemType>
class CBlockList
{
public:
    block<ElemType>* head ;
    block<ElemType>* cur ;	/*指向当前的block*/
    int offset ;	/*block内偏移*/
    CBlockList<ElemType>()
    {
        head = new block<ElemType>(NULL,NULL);
        cur = head ;
        offset = -1 ;
    }

    /*一下是NOI2003 editor要求的操作*/

    /*指针到第pos个位置去*/
    void moveKth(int pos);
    /*指针前移*/
    void PREV();
    /*指针前移*/
    void NEXT();
    /*输出指针后n个字符,指针位置不变*/
    void get(int n);
    /*删除指针后n个字符*/
    void del(int n);
    /*在指针后插入n个字符*/
    void insert(ElemType array[],int n);

};

template<class ElemType>
void CBlockList<ElemType>::moveKth(int pos)
{
    block<ElemType> *temp = head->next , *fa = head ;
    int accumulation = 0 ;
    while ( temp != NULL )
    {
        if( accumulation + temp->len >= pos ) break ;
        fa = temp ;	/*去掉fa faster*/
        accumulation += temp->len ;
        temp = temp->next ;
    }
    if( temp == NULL ) /*超出边界后,默认指向最后一个元素*/
    {
        cur = fa ;
        this->offset = cur->len - 1 ;	/*note:if there is no data in blocklist , offset = -1 */
    }
    else
    {
        cur = temp ;
        this->offset = pos - accumulation - 1 ;
    }
    if( cur != NULL ) while(cur->Union());
}

template<class ElemType>
void CBlockList<ElemType>::PREV()
{
    if( this->offset == -1 )
    {
        /*initial cur and offset */
        if( head->next != NULL ) cur = head->next ;
    }
    else if( this->offset == 0 ) /*go to pre block's last data*/
    {
        if( cur != head->next ) /*if equals, there is no previous data*/
        {
            cur = cur->pre ;
            this->offset = cur->len - 1 ;
        }
        else this->offset--;
    }
    else
    {
        this->offset--;
    }
    if( cur != NULL ) while(cur->Union());
}

template<class ElemType>
void CBlockList<ElemType>::NEXT()
{
    if( this->offset == -1 )
    {
        /*initial cur and offset */
        if( head->next != NULL ) cur = head->next , this->offset = 0 ;
    }
    else if( this->offset == cur->len - 1 ) /*go to pre block's last data*/
    {
        if( cur->next != NULL ) /*if not , there's no next data*/
        {
            cur = cur->next ;
            this->offset = 0 ;
        }
    }
    else
    {
        this->offset++;
    }
    if( cur != NULL ) while(cur->Union());
}

template<class ElemType>
void CBlockList<ElemType>::get(int n)
{
    if( this->offset == -1 )
    {
        /*initial cur and this->offset */
        if( head->next == NULL ) return ;
        cur = head->next ;
    }
    block<ElemType> *temp ;
    int i , pos ;
    temp = cur ;
    for ( i = 0 , pos = this->offset + 1 ; i < n ; i++,pos++)
    {
        if( pos == temp->len )
        {
            temp = temp->next ;
            if( temp == NULL ) break;
            pos = 0 ;
        }
        if( temp != NULL )
            printf("%c",temp->select(pos));
    }
    puts("");
}

template<class ElemType>
void CBlockList<ElemType>::insert(ElemType array[],int n)
{
    if( n <= 0 ) return ;
    block<ElemType>* father , *next ;

    if ( this->offset == -1 )
    {
        /*insert into the first block*/
        next = head->next ;	/*insert before head*/
        father = head ;
    }
    else
    {
        /*split */
        cur->split(this->offset+1);
        next = cur->next ;
        father = cur ;
    }

    int len , accumulation = 0 ;
    do
    {
        block<ElemType>* newBlock = new block<ElemType>(NULL,father);
        if( n > block<ElemType>::maxn ) len = block<ElemType>::maxn ;
        else len = n ;

        newBlock->setData(array+accumulation,len);

        //newBlock->pre = father ;
        /*father must not empty*/
        father->next = newBlock ;
        father = newBlock ;

        n -= len ;
        accumulation += block<ElemType>::maxn ;
    }
    while ( n > 0 ) ;

    father->next = next ;
    /*总是成对出现的,不要总忘了*/
    if( next != NULL ) next->pre = father ;
    /*note:revise cur*/
    if( this->offset == -1 ) cur = head->next ;
    if( cur != NULL ) while(cur->Union());
}

template<class ElemType>
void CBlockList<ElemType>::del(int n)
{
    if( this->offset == -1 )
    {
        /*initial cur and offset */
        if( head->next == NULL ) return ;
        cur = head ;
    }
    else
    {
        /*先分割,分割时前pos个data在一起*/
        cur->split(this->offset+1);
    }
    int accumulation = 0 ;
    block<ElemType>* temp = cur->next ;
    while ( temp != NULL )
    {
        if( temp->len + accumulation <= n )
        {
            /*delete the temp block*/
            accumulation += temp->len ;
            temp = temp->next ;
            cur->del();
        }
        else
        {
            /*split temp block*/
            if( n > accumulation )
            {
                temp->split(n-accumulation);
                cur->del();
            }
            break ;
        }
    }
    if( this->offset == -1 ) cur = head->next ;
    /*合并*/
    /*!!!找了半个多小时才找到的错误= =*/
    if( cur != NULL )	while(cur->Union());
}

/************************************************************************/
/* editor指令操作:                                                     */
/* insert X                                                             */
/* delete X		                                                */
/* goto X			                                        */
/* pre				                                        */
/* next				                                        */
/* show X			                                        */
/************************************************************************/

class CEditor
{
public:
    const int maxn ;
    CEditor():maxn(1024*1024*2) { 	}
    char array[1024*1024*2+10];
    CBlockList<char> list ;
    void handle()
    {
        char op[16] , ch ;
        int i , x , pos , t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%s",op);
            switch(tolower(op[0]))
            {
            case 'i':
                scanf("%d",&x);
                for( i = 0 ; i < x ; )
                {
                    ch = getchar();
                    if( ch >= 32 && ch <= 126 ) array[i++] = ch ;
                }
                list.insert(array,x);
                break;
            case 'm':
                scanf("%d",&pos);
                list.moveKth(pos);
                break;
            case 'p':
                list.PREV();
                break;
            case 'n':
                list.NEXT();
                break;
            case 'g':
                scanf("%d",&x);
                list.get(x);
                break;
            case 'd':
                scanf("%d",&x);
                list.del(x);
                break;
            default:
                ;
            }
        }
    }
};

template<class ElemType>
class CRevBlockList: public CBlockList<ElemType>
{
public:
    void build(int n);
    void rev(int l,int r);
    void show();
};

template<class ElemType>
void CRevBlockList<ElemType>::rev(int l,int r)
{
    this->moveKth(l-1);
    block<ElemType> *temp = this->cur , *curNext , *tmp ;
    this->cur->split(this->offset+1);
    /*注意这种未分割的情况!!!*/
    if( this->offset == -1 ) temp = this->cur->pre ;
    this->moveKth(r);
    this->cur->split(this->offset+1);
    /*reverse (temp,cur] */
    curNext = this->cur->next ;
    temp->next = this->cur ;
    tmp = temp ;
    //if( this->cur == temp ) this->cur->rev ^= 1 ;
    while ( this->cur != tmp )
    {
        this->cur->rev ^= 1 ;
        temp->next = this->cur ;
        this->cur->next = this->cur->pre ;
        if( this->cur->pre != NULL ) this->cur->pre = temp ;
        temp = this->cur ;
        this->cur = this->cur->next ;
    }
    temp->next = curNext ;
    if( curNext != NULL ) curNext->pre = temp ;
}

template<class ElemType>
void CRevBlockList<ElemType>::show()
{
    int i ;
    block<ElemType>* tmp = this->head->next ;
    while ( tmp != NULL )
    {
        if( tmp->rev )
        {
            for( i = tmp->len - 1 ; i >= 0 ; i--) printf("%d ",tmp->data[i]);
        }
        else
        {
            for( i = 0 ; i < tmp->len ; i++) printf("%d ",tmp->data[i]);
        }
        tmp = tmp->next ;
    }
    puts("");
};

template<class ElemType>
void CRevBlockList<ElemType>::build(int n)
{
    int i , j ;
    block<ElemType>* tmp = new block<ElemType>(NULL,this->head) , *fa ;
    fa = this->head ;
    fa->next = tmp ;
    for( i = 1 ; i <= n ; i++)
    {
        if( tmp->len == block<ElemType>::maxn )
        {
            fa = tmp ;
            tmp = new block<ElemType>(NULL,fa) ;
            fa->next = tmp ;
            i--;
        }
        else
        {
            tmp->data[tmp->len++] = i ;
        }
    }
};

class CRevClient
{
public:
    CRevBlockList<int> list ;
    void handle()
    {
        int n , m , l , r ;
        while (~scanf("%d%d",&n,&m))
        {
            list.build(n);
            while (m--)
            {
                scanf("%d%d",&l,&r);
                list.rev(l,r);
            }
            list.show();
        }
    }
};

int main()
{

    CRevClient client ;
    client.handle();
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值