题目要求
三个或三个以上的字符相邻,就都消失,输入原始字符,操作次数n,每次输入插入位置和相应字符,每操作一次,输出一次,当没有剩余字符,输出-.
案例
输入
ACCBA
5
1 B
0 A
2 B
4 C
0 A
输出
ABCCBA
AABCCBA
AABBCCBA
-
A
解题分析
因为看到了要连续删除,我决定用双向链表,也就是再单向链表的基础上,在单个节点上增加了指向前一个节点的prev指针,在链表内加了一个指向尾节点的last指针.
class ListNode {
public:
char element;
ListNode* prev;
ListNode* next;
ListNode() {};
ListNode(char e, ListNode* p, ListNode* n)
{
element = e;
prev = p;
next = n;
}
};
class LinkList {
public:
ListNode* first;
ListNode* last;
int len;
LinkList();
~LinkList();
int get(int i);
ListNode* node(int index);//通过索引返回节点指针
void add(int i, char item);
void del(int i);
void display();
void tri(); //找到连续三个或以上并删除
};
函数内相比于单向链表,需要改动的(除了基本的构造析构函数外)有:node函数 add函数 del函数 增加本题需要的tri函数.
node
ListNode* LinkList::node(int index)
{
if (index < (len >> 1)) //索引小于一半从前往后找 len>>1 是除以2的意思
{
ListNode* node = first;
for (int i = 0; i < index; i++)
{
node = node->next;
}
return node;
}
else //索引大于一半从后往前找
{
ListNode* node = last;
for (int i = len - 1; i > index; i--)
{
node = node->prev;
}
return node;
}
}
add
需要考虑的特殊情况:
- 链表添加的第一个元素
- 往链表开头加
- 往链表末尾加
怎么说,我感觉把双向链表的图画出来会好写一点(信我
void LinkList::add(int index, char item)
{
if (index == len) //往最后加
{
ListNode* Oldlast = last;
last = new ListNode(item, Oldlast, NULL);
if (Oldlast == NULL) //这是链表添加的第一个元素
{
first = last;
}
else
{
Oldlast->next = last;
}
}
else
{
ListNode* n = node(index);
ListNode* p = n->prev;
ListNode* node = new ListNode(item, p, n);
n->prev = node;
if (p == NULL) //index == 0
{
first = node;
}
else
{
p->next = node;
}
}
len++;
}
delete
需要考虑的特殊情况:
- 删除链表开头
- 删除链表末尾
void LinkList::del(int i)
{
ListNode* no = node(i);
ListNode* prev = no->prev;
ListNode* next = no->next;
if (prev == NULL) //i==0
first = next;
else
prev->next = next;
if (next == NULL) //i == len - 1
last = prev;
else
next->prev = prev;
len--;
}
tri删除三个及以上的相邻元素
我觉得最需要注意的地方就是当你要用 p->next 的时候,p会不会等于NULL(一个因为这个改了无数次的人的苦口婆心)
void LinkList::tri()
{
ListNode* p = first;
for (int i = 0; i < len; i++)
{
if (p&& p->next && p->prev && p->prev->element == p->element
&& p->next->element == p->element)
{
char a = p->element;//四个消消乐的时候
this->del(i - 1);
this->del(i - 1);
this->del(i - 1);
if (len != 0)
{
if (node(i - 1)->element == a)
{
this->del(i - 1);
}
}
p = first;
i = 0;
}
if (p)
p = p->next;
}
}
完整代码
#include <iostream>
using namespace std;
#define ok 0
#define error -1
class ListNode {
public:
char element;
ListNode* prev;
ListNode* next;
ListNode() {};
ListNode(char e, ListNode* p, ListNode* n)
{
element = e;
prev = p;
next = n;
}
};
class LinkList {
public:
ListNode* first;
ListNode* last;
int len;
LinkList();
~LinkList();
ListNode* indexOf(int i);
int get(int i);
ListNode* node(int index);
void add(int i, char item);
void del(int i);
void display();
void tri();
};
void LinkList::tri()
{
ListNode* p = first;
for (int i = 0; i < len; i++)
{
if (p&& p->next && p->prev && p->prev->element == p->element
&& p->next->element == p->element)
{
char a = p->element;//四个消消乐的时候
this->del(i - 1);
this->del(i - 1);
this->del(i - 1);
if (len != 0)
{
if (node(i - 1)->element == a)
{
this->del(i - 1);
}
}
p = first;
i = 0;
}
if (p)
p = p->next;
}
}
LinkList::LinkList()
{
first = NULL;
last = NULL;
len = 0;
}
LinkList::~LinkList()
{
ListNode* p, * q;
p = first;
while (p != NULL) {
q = p;
p = p->next;
delete q;
}
len = 0;
first = NULL;
}
void LinkList::display()
{
ListNode* p = first;
if (len == 0)
{
cout << "-";
}
for (int i = 0;p && i < len; i++)
{
cout << p->element;
p = p->next;
}
cout << endl;
}
int LinkList::get(int index)
{
return node(index)->element;
}
ListNode* LinkList::node(int index)
{
if (index < (len >> 1)) //索引小于一半从前往后找
{
ListNode* node = first;
for (int i = 0; i < index; i++)
{
node = node->next;
}
return node;
}
else //索引大于一半从后往前找
{
ListNode* node = last;
for (int i = len - 1; i > index; i--)
{
node = node->prev;
}
return node;
}
}
void LinkList::add(int index, char item)
{
if (index == len) //往最后加
{
ListNode* Oldlast = last;
last = new ListNode(item, Oldlast, NULL);
if (Oldlast == NULL) //这是链表添加的第一个元素
{
first = last;
}
else
{
Oldlast->next = last;
}
}
else
{
ListNode* n = node(index);
ListNode* p = n->prev;
ListNode* node = new ListNode(item, p, n);
n->prev = node;
if (p == NULL) //index == 0
{
first = node;
}
else
{
p->next = node;
}
}
len++;
}
void LinkList::del(int i)
{
ListNode* no = node(i);
ListNode* prev = no->prev;
ListNode* next = no->next;
if (prev == NULL) //i==0
first = next;
else
prev->next = next;
if (next == NULL) //i == len - 1
last = prev;
else
next->prev = prev;
len--;
}
int main()
{
int i = 0, t;
char n;
LinkList list;
cin >> n;
while (n >= 'A' && n <= 'Z')
{
list.add(i, n);
i++;
cin >> n;
}
t = n - '0';
while (t--)
{
int i;
cin >> i >> n;
list.add(i, n);
list.tri();
list.display();
}
}