当前位置: 代码迷 >> 综合 >> UVA-11988 Broken Keyboard (模拟,字符串,单向链表(指针实现、数组实现))
  详细解决方案

UVA-11988 Broken Keyboard (模拟,字符串,单向链表(指针实现、数组实现))

热度:48   发布时间:2023-12-09 20:51:50.0

Ps.很好的一道对链表的练习题,第一次练习使用链表,也是发现了自己对链表实现很多不清晰的理解(一片WA声) b( ̄▽ ̄)d

题目:UVA-11988

题目描述:每个样例是一行无空格的字符串,模拟在电脑上打字,’[’ 代表光标移至开头,之后的字符串整体打印在开头,‘]’ 代表光标移至末尾,之后的字符正常在末尾打印。要求输出打印出来的字符

样例输入:This_is_a_[Beiju]_text
     [[]][][]Happy_Birthday_to_Tsinghua_University

样例输出:BeijuThis_is_a__text
     Happy_Birthday_to_Tsinghua_University

分析:
  首先这题用单纯数组存储来实现是肯定不行的,数组的插入需要把后面所有元素后移一位,会TLE,而链表就可以很灵活地插入了。
  一开始理解错了题意,用了双向的链表,左右两边延伸,导致样例输入的“This_is_a_[Beiju]_text"的输出变成了“ujieBThis_is_a__text”。这里 ‘[’ 的意思应该是将从 ‘[’ 之后到下一个 ‘[ ’ 或 ‘]’ 之前的所有字符原顺序打印在开头,所有应该是单向链表的插入操作,把 '[’ 之后的字符挨个插入到head节点后面。

首先是用指针实现链表(一堆注释,给自己理解):

#include<iostream>
#include<string>
#include<cstdio>
#include<sstream>
using namespace std;
struct node 
{
    char ch;node *next;
};
int main()
{
    node *head, *tail, *p;  //head 头节点,tail指向尾部(用于返回末尾)string str;             //指针p代表光标位置,每下一个字符都放在p节点(光标)之后 while (cin >> str)      //读取一行{
    	p = tail = head = new(node);   //统一初始化,头节点并不用于存放元素p->next = NULL;stringstream ss(str);   //将str放入名为ss的流中 (需要头文件sstream)char c;while (ss>>c)          //从ss中依次读取字符{
    if (c == '[')        //若为‘[’ 光标p移至开头p = head;else if (c == ']')   //若为‘]’ 光标p移至末尾p = tail;else{
    node *x = new (node);  //创建新节点xx->ch = c;x->next = NULL;if (p->next == NULL)   //当光标p后没有字符{
                          p->next = x;       p = tail = x;      //末尾更新为x,光标p后移一位(等于x)}else                      //当光标p后面有字符{
    x->next = p->next;    //进行链表插入操作(插入到光标p之后)p->next = x;p = x;                //光标p后移一位(等于x)}}}node *prei=head;for (node *i = head->next; i != NULL; i = i->next){
                             //输出,同时释放内存(delete)putchar(i->ch);delete(prei);prei = i;}delete(prei);putchar('\n');}return 0;
}

单向链表用数组来实现会方便很多,但是我一开始看用数组实现的链表一脸懵逼,写一下我自己对其的理解吧。

数组实现的链表 类比于 结构体指针的链表

数组实现中用node[maxn]来存储节点数据,在这里,node的下标实际上相当于一个地址,每个节点都有各自的下标(理解为地址),node[maxn]中只需要依次存储就行。

数组实现中用next[maxn]来充当指针,每个next中存储着链表中该节点下一位的下标(理解为地址),那么i=next[i]就相当于p=p->next,以此类推。
举个栗子:

在位于链表末尾的节点a(下标为a)后面插入一个下标为b的节点,那么操作就是

//数组实现
next[b]=next[a];    //next[b]是b的下一位,next[a]是a的下一位
next[a]=b;//链表实现
b->next=a->next;
a->next=b;

这样类比一下,数组实现链表就很好理解了( ?? ω ?? )y

以下数组实现链表的解题代码

#include<iostream>
#include<string>
#include<cstdio>
#include<sstream>
using namespace std;
int main()
{
    char node[100001];char c;string str;while (cin >> str) {
    	int head = 0, tail=0, p=0, count=0;  //count用于在node中依次存储int next[100001] = {
     0 };            //next全初始化为0,类比于空指针stringstream ss(str);                //p依旧代表光标while (ss>>c){
    if (c == '[')p = head;else if (c == ']')p = tail;else{
    count++;node[count] = c;     //现在count就相当于现在这个节点的地址了if (next[p] == 0)    //当p为末尾,新节点接到后面然后更新为末尾{
    next[p] = count;p=tail= count;}else                         //当p不为末尾,则插入{
    next[count] = next[p];next[p] = count;p = count;}}}for (int i = next[head]; i != 0; i = next[i])  putchar(node[i]);       //一样的遍历方式,head只做头节点,不存数据putchar('\n');}return 0;
}
  相关解决方案