块状链表之代码剖析

来源:互联网 发布:免费抽奖软件 编辑:程序博客网 时间:2024/06/03 12:58

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

块状链表解析

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);/*赋值*/        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 ;    }

④:删除

    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();}






原创粉丝点击