紫书第六章-----数据结构基础(数组模拟链表)

来源:互联网 发布:python ftp 传输模式 编辑:程序博客网 时间:2024/05/11 12:49

数组模拟单链表

例题6-4 Broken Keyboard (a.k.a. Beiju Text) UVA - 11988
这道题目可以直接用STL中list双向链表来做,思路和代码都很简单易想。也可以用数组模拟链表(不易懂)。
之所以不用vector是因为插入删除比较慢慢慢

AC代码(一):
STL的list版本

#include<iostream>#include<list>#include<string>using namespace std;int main(){    string s;    while(cin>>s){        list<char>l;        list<char>::iterator it=l.begin();        for(int i=0;i<s.length();i++){            if(s[i]=='[') it=l.begin();            else if(s[i]==']') it=l.end();            else{                it=l.insert(it,s[i]);                it++;            }        }        for(it=l.begin();it!=l.end();it++)            cout<<*it;        cout<<endl;    }    return 0;}

AC代码(二):
数组模拟链表版本

//数组模拟链表#include<stdio.h>#include<string.h>const int maxn=100000+5;int next[maxn];//next[i]表示链表中第i个结点下一个结点的编号char s[maxn];int cur;//当前光标所在位置,即指向当前结点的右侧int last;//当前最后一个结点的编号int main(){    //s[0]设置为类似链表的头结点,元素从下标1开始编号    while(scanf("%s",s+1)!=EOF){        int len=strlen(s+1);        cur=last=0;        next[0]=-1;//这里-1仅仅是一个标记,表示起初链表的头结点指向的数值                    //类似于指针链表初始化时候linklist->next=NULL        for(int i=1;i<=len;i++){            if(s[i]=='[') cur=0;//光标定位到开始,指向第0个元素(假想的头结点)的右侧            else if(s[i]==']') cur=last;//光标定位到最后一个元素,指向最后一个元素的右侧            else{            //插入新节点i,类似于链表中创建一个节点i,让他的next指向当前链表头(cur)的next            //再让当前链表头的next指向节点i            //和普通链表不同的是这里的链表头cur会变,但是next[0]永远是第一个字符哦                next[i]=next[cur];                next[cur]=i;                if(cur==last) last=i;//如果现在的cur=last,插入新节点后,更新last,手写易明白                                //由于cur可能会回到头变成0,所以这个操作技巧很好                cur=i;//插入一个新节点后,cur自然后移,指向当前节点的右侧            }        }        //上述过程完成了建立一个链表的过程,next[0]的值就是第一个字符的下标,next[1]就是第2个节点        //的下标,以此类推,最后一个节点的next必然是-1,想想链表建立过程,依次往后指,这一点应该很明白        for(int i=next[0];i!=-1;i=next[i])            printf("%c",s[i]);        printf("\n");    }    return 0;}

C语言代码(超时为何?):

#include<stdio.h>#include<string.h>const int maxn=100000+5;char s[maxn];typedef struct LINK{    LINK *next;    LINK *rear;    LINK *cur;    char c;}node,*linklist;void linklist_init(linklist &lis){    lis=new node;    lis->rear=lis;    lis->next=NULL;    lis->cur=lis;}void linklist_insert(linklist &lis,char e){    node *p=new node;    p->next=lis->cur->next;    p->c=e;    lis->cur->next=p;    if(lis->cur==lis->rear) lis->rear=p;    lis->cur=p;}int main(){    while(scanf("%s",s)!=EOF){        linklist lis;        linklist_init(lis);        for(int i=0;i<strlen(s);i++){            if(s[i]=='[') lis->cur=lis;            else if(s[i]==']'){lis->cur=lis->rear;}            else{                linklist_insert(lis,s[i]);            }        }        node *tmp=lis;        while(tmp->next){            printf("%c",tmp->next->c);            tmp=tmp->next;        }        printf("\n");    }    return 0;}

数组模拟双向链表

例题6-5 Boxes in a Line UVA - 12657
直接给出参考刘汝佳《算法竞赛入门经典》(第2版)代码参考:

#include<cstdio>const int maxn=100000+5;int n,m;int left[maxn],right[maxn];int kase=0;void link(int l,int r){    right[l]=r;    left[r]=l;}int main(){    while(scanf("%d%d",&n,&m)!=EOF){        for(int i=1;i<=n;i++){            left[i]=i-1;            right[i]=(i+1)%(n+1);        }        left[0]=n;right[0]=1;        int op,x,y;        bool inv=0;        while(m--){            scanf("%d",&op);            if(op==4) inv=!inv;            else{                scanf("%d%d",&x,&y);                if(op==3 && right[y]==x){int t=x;x=y;y=t;}//x,y相邻的情形统一变为yx右侧                //下面这个复合语句坑我了,下面这么写是对的,下面的复合语句全部用if,if是错的                {                    if(op==2 && inv) op=1;//逆转后,右边变左边,左边变右边                    else if(op==1 && inv) op=2;                }                if(op==1 && x==left[y]) continue;                if(op==2 && x==right[y]) continue;                int lx=left[x],rx=right[x],ly=left[y],ry=right[y];//这样已经保存了x,y的左右值哦,这样很方便后续操作                if(op==1){                    link(lx,rx);link(ly,x);link(x,y);                }                else if(op==2){                    link(lx,rx);link(y,x);link(x,ry);                }                else if(op==3){                    //分为两种情形,x,y相邻与否                    if(right[x]==y){                        link(lx,y);link(y,x);link(x,ry);                    }                    else{                            link(lx,y);link(y,rx);                            link(ly,x);link(x,ry);                    }                }            }        }        int j=0;        long long int ans=0;        for(int i=1;i<=n;i++){            j=right[j];            if(i%2==1) ans+=j;        }        if(inv && n%2==0) ans=(long long)n/2*(n+1)-ans;        printf("Case %d: %lld\n",++kase,ans);    }    return 0;}