DS双向链表—祖玛

题目描述

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

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

输入

第一行是一个由大写字母'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>
using namespace std;

class Node {
public:
    char data;
    Node* next;
    Node* prio;
    Node() { data = NULL; next = NULL; prio = NULL; }
};

class List {
    Node* head;
    int len;
public:
    List() {
        string s;
        head = new Node;
        head->prio = NULL;//规范性,都初始化为空
        head->data = NULL;
        cin >> s;
        len = s.length();//取字符串长度
        Node* p = head;//取头结点
        for (int i = 0; i < len; i++) {
            Node* q = new Node;//new一个新节点
            q->data = s[i];//赋值
            p->next = q;
            q->prio = p;
            p = q;//p右移一位
        }
        p->next = NULL;//最后为空
    }
    void list_insert() {
        int i;
        char item;
        cin >> i >> item;
        Node* p = head;//用于保存插入结点的前一个节点,注意题目意思第0个不是head
        for (int j = 0; j < i; j++) {
            p = p->next;
        }
        Node* q = new Node;
        Node* temp;
        q->next = p->next;
        if(p->next) p->next->prio = q;//注意,每次使用两个单箭头复合都要检查
        p->next = q;                 //接上一句:第一个单箭头是否为空
        q->prio = p;
        q->data = item;
        len++;
        int snum = 1;//用来记录重复元素个数
        Node* left = q->prio;//插入元素的左边一个元素
        Node* right = q->next;//插入元素的右边一个元素
        while (true) {//跳出条件在内部break
            while (left) {
                if (left->data == item) {
                    snum++;//左边计数
                    left = left->prio;
                }
                else {
                    break;//一旦不相等(说明不连续重复)就跳出
                }
            }
            while (right) {
                if (right->data == item) {
                    snum++;//右边计数
                    right = right->next;
                }
                else {
                    break;//与右边相同
                }
            }
            if (snum >= 3) {
                left = left->next;//这句之前left指向左边第一个不重复的元素,所以要处理
                while (snum--) {
                    temp = left;
                    left = left->next;
                    list_del(temp);//一定要用一个temp保留之前的left
                }                  //而且不能想着把这一句换成list_del(left.prio),因为left有可能为空
                if (left) {//再次检查,重新设置item,snum等参数
                    snum = 1;
                    item = left->data;
                    left = left->prio;
                    right = right->next;
                }
            }
            else {
                break;//跳出大循环
            }
        }
    }
    void list_del(Node*p) {
        Node* temp = p;
        p->prio->next = p->next;
        if (p->next)  p->next->prio = p->prio;//和上面一样,要判断
        len--;
        free(temp);
    }
    void list_disply() {
        Node* p = head->next;
        if (p) {
            for (int i = 0; i < len; i++) {
                cout << p->data;
                p = p->next;
            }
        }
        else {
            cout << "-";
        }
        cout << endl;
    }
};

int main()
{
    int n;
    List list;
    list.list_disply();
    cin >> n;
    while (n--) {
        list.list_insert();
        list.list_disply();
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值