04-C. DS双向链表

04-顺序表和堆栈练习

题目描述
祖玛是一款曾经风靡全球的游戏,其玩法是:在一条轨道上初始排列着若干个彩色珠子,其中任意三个相邻的珠子不会完全同色。此后,你可以发射珠子到轨道上并加入原有序列中。一旦有三个或更多同色的珠子变成相邻,它们就会立即消失。这类消除现象可能会连锁式发生,其间你将暂时不能发射珠子。

给定轨道上初始的珠子序列,然后是玩家所做的一系列操作。你的任务是,在各次操作之后及时计算出新的珠子序列。

输入
第一行是一个由大写字母’A’~'Z’组成的字符串,表示轨道上初始的珠子序列,不同的字母表示不同的颜色。

第二行是一个数字n,表示玩家共有n次操作。

接下来的n行依次对应于各次操作。每次操作由一个数字k和一个大写字母描述,以空格分隔。其中,大写字母为新珠子的颜色。若插入前共有m颗珠子,位置0-m-1,则k ∈ [0, m]表示新珠子嵌入在轨道上的位置。


输出
输出共n行,依次给出各次操作(及可能随即发生的消除现象)之后轨道上的珠子序列。

如果轨道上已没有珠子,则以“-”表示。

输入样例
ACCBA
5
1 B
0 A
2 B
4 C
0 A

ABCCBA
AABCCBA
AABBCCBA

A

以下有四个方法
第三个方法存在编译错误,第四个方法存在溢出

#include<iostream>
#include<string.h>
using namespace std;

typedef struct node
{
 char data;
 node *prior;
 node *next;
}node;//创建双向链表结构体 

void init(node *N)//双链表初始化 
{
 	N->next=NULL;
 	N->prior=NULL;
 	
 	char datas[100];//开字符数组输入 
 	cin>>datas;
 	int l=strlen(datas);//数组长度 
 	int i=0;
 	
 	node *s;//临时数组储存数据 
 	while(l--)//尾插法,把字符串导入双链表中 
 	{
  		s=new node; s->prior=NULL; s->next=NULL;
  		s->data=*(datas+i);
  		s->prior=N; N->next=s;
  		N=s;
  		i++;
 	}
 	//尾巴 在双链表最后
 	node *tail;
 	tail=new node;
 	tail->prior=NULL;tail->next=NULL;
 	tail->prior=N;
 	N->next=tail;
}

void printnode(node *N)//定义打印函数 
{
 	if(N->next->next)//判断是否为空 
 	{
  		N=N->next;
  		while(N->next)
 		{
  			cout<<N->data;
  		 	N=N->next;
  		} 
 	}
 	else
  		cout<<"-";
 	cout<<endl;
}

node* insert(node *N,int step,char color)//创建插入函数,返回头指针 
{
 int i;
 node *H=N;//指向头 
 node *s;  //临时储存 
 for(i=0;i<step;i++)//找到位于step位置的节点 
  N=N->next;
  
 s=new node;
 s->next=NULL;
 s->prior=NULL;
 s->data=color;
 
 s->prior=N;//插入函数关键步骤,两边顾 
 s->next=N->next;
 N->next->prior=s;
 N->next=s;
 
 while(H->prior)//找到头 
  H=H->prior;
 return H;//返回头 
}

void find(node *N)//查找函数 !核心
{
 	node *k=N->next;//定义指针用于循环 
 	int flag;//标记次数 
 
 while(k->next->next)//从第一个非空节点开始扫描 
 //想要在一次操作里删除三个相等的颜色组:在最外面套个while重复筛查
 {
 	flag=1;
  	while((k->data)==(k->next->data))
  	{
   		flag++;//假如数据相等,次数++ 
   		k=k->next;//移动到下一个节点 
 	}
  	if(flag>=3)//假如次数大于等于三 
  	{
   		while(flag--)
   		{
    		k->next->prior=k->prior;//删除 
    		k->prior->next=k->next;
    		k=k->prior; 
    	}
    	if(N->next->next) //key!如链表以空不要再移动 
     		k=N->next;
  	}
  	else
   		k=k->next;
 }
}
 
int main()
{
 int n,step;
 char color;
 node *N;
 N=new node;
 
 init(N);
 cin>>n;
 while(n--)
 {
  cin>>step>>color;
  insert(N,step,color);
  find(N);
  printnode(N);
 }
 return 0;
}
#include<iostream>
#include<string>
using namespace std;

class node
{
public:
 char ch;
 int data;
 node* next;
 node* prior;
};

void create(node* head, int n, string s)
{
    node* tail = head;
    head->data = 0;
    char ch;
    for (int i = 0; i < n; i++)
    {
        node* pnew = new node;
        pnew->next = NULL;
        pnew->prior = tail;
        pnew->ch = s[i];
        tail->next = pnew;
        tail = pnew;
        head->data++;
    }
}
void print(node* head)
{
    node* h = head->next;
    if (!head->data) cout << "-";
    else
    {
        for (int i = 0; i < head->data; i++)
        {
            cout << h->ch;
            h = h->next;
        }
    }
}

//插入
void insert(node* head, int index, char ch)
{
    node* p = head->next;
    if (index)
    {
        for (int i = 1; i < index; i++)
            p = p->next;
        
        node* pnew = new node;
        pnew->ch = ch;
        pnew->prior = p;
        pnew->next = p->next;
        p->next = pnew;
        
        if (pnew->next)
            pnew->next->prior = pnew;
        
        head->data++;
    }
    else if (head->data)
    {
        p = head;
        node *pnew = new node;
        
        pnew->ch = ch;
        pnew->prior = p;
        pnew->next = p->next;
        p->next = pnew;
        pnew->next->prior = pnew;
        
        head->data++;
    }
    else
    {
        p = head;
        node* pnew = new node;
        pnew->ch = ch;
        pnew->prior = p;
        pnew->next = p->next;
        p->next = pnew;
        head->data++;
    }
}
//遍历检查
void rearch(node* head)
{
 node* p = head->next;
 while (p)
 {
  if (!p->next) break;
  if (p->ch == p->prior->ch && p->ch == p->next->ch)
  {
   int sum = 3;
   //用d0指向需删除最左端珠子的前继
   node* d0 = p->prior->prior;
   //用d1指向需删除最右端珠子的后继
   node* d1 = p->next->next;
   if (d1)
    while (d1->ch == p->ch)
    {
     if (!d1->next) break;
     d1 = d1->next;
     //需删除总数++
     sum++;
    }
   if (d1)
   {
    d0->next = d1;
    d1->prior = d0;
   }
   else d0->next = NULL;

   head->data -= sum;
   p = head->next;
  }
  else
   p = p->next;
 }
}
int main()
{
 string s;
 char ch;
 int index;
 cin >> s;
 int n = s.length();
 node *head = new node;
 create(head, n, s);
 int t;
 cin >> t;
 while (t--)
 {
  cin >> index >> ch;
     
  insert(head, index, ch);
  rearch(head);
  print(head);
     
  if (t)cout << endl;
 }
 return 0;
}
#include<iostream>
#include<string.h>
#include<cstdio>
#define MAX 200000000
using namespace std;

typedef struct node
{
 char data;
 struct node *next;
 struct node *prior;
}node;

int main()
{
    int n,len,i,sum;
    node *L=new node;
    struct node *p=L;
    struct node *q;
    char a[100];

    gets(a);
    len=strlen(a);
    
    for(i=0;i<len;i++)
    {
        q=new node;
        q->data=a[i];
        q->prior=p;p->next=q;
        p=q;
    }
    
    cin>>n;
    
    while(n--)
    {
        
        int j;
        char ch;
        cin>>j>>ch;
        
        struct node *p,*q;
        p=L->next;
        while(j--)
            p=p->next;
        
        
        //在t之后插入ch
        q=new node;
        q->data=ch;
        q->prior=p->prior;
        p->prior->next=q;
        q->next=p;
        p->prior=q;
        
        len++;
        
        //删除三个一起的字母
        
        while(1)
        {
        while(q&&q->data==ch)
            q=q->next;
        while(p->prior&&p->data==ch)
            p=p->prior;
            
        struct node *r=p;
        sum=0;
        while(r&&r!=q)
        {
            r=r->next;
            sum++;
        }
        if(sum>=4)
        {
            p->next=q;
            if(q)
                q->prior=p;
            if(p!=L)
                ch=p->data;
            else if(q)
                ch=q->data;
                
            len-=(sum-1);
            //shanchu(ch,p,q,L,len);
        }
        else
            break;
        }
        
        if(len==0)
        cout<<"-";
        else
        {
            p=L;
            for(i=0;i<len;i++)
            {
                p=p->next;
                cout<<p->data;
            }
        }
        cout<<"\n";
    }
    
    return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;

#define MAX 200000000

//祖玛色块类
struct Zuma{
    char date;
    Zuma *up;
    Zuma *down;
    Zuma(){};
    Zuma(char s):date(s){};
}*header,*tailer;    //首尾哨兵

char s[MAX];
int length;    //链表长度
int k;    //记录数据长度

//双向链表-尾插法
void Creat_zuma(char *s)
{
    header = new Zuma();
    header->up = NULL;

    Zuma *rear = header;    //定义尾部指针-穿针
    for (int i = 0; i < length; i++)
    {
        Zuma *p = new Zuma(s[i]);
        rear->down = p;
        p->up = rear;

        rear = p;    //换针
    }
    tailer = new Zuma();
    rear->down = tailer;
    tailer->up = rear;
    tailer->down = NULL;
}

//遍历查找pos位置的指针
Zuma* Find(int pos)
{
    int counter = 0;
    Zuma *p = header;
    if (length - pos >= pos)    //首部遍历
    {
        while (counter < pos && p->down != tailer)
        {
            p = p->down;
            counter++;
        }
    }
    else{                        //尾部遍历
        p = tailer;
        counter = length;
        while (counter >= pos && p->up != header)
        {
            p = p->up;
            counter--;
        }
    }
    return p;
}

//消除
Zuma* Remove(Zuma *cur,char c)
{
    while (1)
    {
        Zuma *pre = cur->down;
        int counter = 0;
        while (cur != header && cur->date == c)    //向前查重
        {
            cur = cur->up;
            counter++;
        }
        while (pre != tailer && pre->date == c)    //向后查重
        {
            pre = pre->down;
            counter++;
        }
        if (counter >= 3)    //重复元素大于三个
        {
            length -= counter;
            Zuma *p1 = cur->down, *p2;
            while (p1 != pre)    //delete
            {
                p2 = p1->down;
                delete p1;
                p1 = p2;
            }
            cur->down = pre;
            if (pre != NULL)
                pre->up = cur;
            c = cur->date;
        }
        else break;
    }
    return cur;
}

//插入
void Insert(Zuma *p, char c)
{
    Zuma *x = new Zuma(c);
    if (p->down != NULL)
    {
        x->up = p;
        x->down = p->down;
        p->down->up = x;
        p->down = x;
    }
    else{
        x->up = p;
        x->down = NULL;
        p->down = x;
    }
    length++;
}
int main()
{
    int n;
    gets(s);
    scanf("%d", &n);
    length = strlen(s);
    //搭建
    Creat_zuma(s);

    for (int t = 0; t < n; t++)
    {
        char c[2];
        int pos;
        scanf("%d%s", &pos, &c);

        Zuma *p = Find(pos);
        Insert(p, c[0]);
        Zuma *flag = Remove(p, c[0]);
        //Record
        if (flag == header && flag->down == tailer)
        {
            s[k++] = '-';
            s[k++] = '\n';
        }
        else{
            flag = header;
            while (flag->down != tailer)
            {
                s[k++] = flag->down->date;
                flag = flag->down;
            }
            s[k++] = '\n';
        }
        //Single Input
        if (t == n - 1)
        {
            s[k] = '\0';
            printf("%s", s);
            k = 0;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值