본문 바로가기

BOJ

[백준 C++] 10866, 1406번 덱, 에디터

에디터


이중 연결리스트를 공부하려고 푼 문제다. 에디터 문제를 먼저 풀었는데 정말이지 죽을 뻔 했다. Node 의 previous Node 와 next Node 를 모두 연결하는 작업이 너무 헷갈리기도 했고, 실수도 많이 할 수 밖에 없는 자료구조인 것 같다. 그래도 에디터 문제를 풀면서 Node 들과 씨름을 하다 보니 좀 익숙해져서 덱 문제는 훨씬 쉽게 풀었다.


덱 문제는 사실 STL 에 있는 것을 가져다와서 사용해도 되는데 처음부터 STL 에 길들여지면 안될 것 같아서 직접 구현하려고 마음먹었다. 이중 연결리스트로 구현할 수있다는 말을 듣고 이중 연결 리스트를 공부해보기로 했다. 


사실 덱을 위한 이중 연결리스트는 중요한 기능이 빠져 있다. 에디터 문제에서도 나오겠지만 이중 연결리스트는 그 이름 답게 연결된 노드들끼리 왔다갔다 하면서 노드들 넣었다가 뺐다가 하는 작업이 복잡한데 여기서는 Front 에 노드를 추가하고 빼며, Back 에 노드를 추가하고 빼는게 전부다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include <iostream>
#include <string>
using namespace std;
 
struct Node {
    int data;
    struct Node* next;
    struct Node* prev;
};
 
class Deque
{
private:
    Node *head;
    Node *tail;
public:
    Deque() {
      head = new Node();
      tail = new Node();
      head -> prev = nullptr;
      head -> next = tail;
      tail -> next = nullptr;
      tail -> prev = head;
    }
    int size = 0;
    void pushFront(int data);
    void pushBack(int data);
    void removeFront();
    void removeBack();
    void front();
    void back();
};
 
void Deque::pushFront(int data) {
  Node *newNode = new Node();
  Node *dummy = head -> next;
 
  newNode -> data = data;
  newNode -> prev = head;
  newNode -> next = dummy;
 
  head -> next = newNode;
  dummy -> prev = newNode;
  size++;
}
 
void Deque::pushBack(int data) {
  Node *newNode = new Node();
  Node *dummy = tail -> prev;
 
  newNode -> data = data;
  newNode -> next = tail;
  newNode -> prev = dummy;
 
  tail -> prev = newNode;
  dummy -> next = newNode;
  size++;
}
 
void Deque::removeFront() {
  if (head -> next != tail) {
    Node *dummy = head -> next;
    cout << dummy -> data << '\n';
    head -> next = dummy -> next;
    dummy -> next -> prev = head;
    delete dummy;
    size--;
  } else cout << -1 << '\n';
}
 
void Deque::removeBack() {
  if (tail -> prev != head) {
    Node *dummy = tail -> prev;
    cout << dummy -> data << '\n';
    tail -> prev = dummy -> prev;
    dummy -> prev -> next = tail;
    delete dummy;
    size--;
  } else cout << -1 << '\n';
}
 
void Deque::front() {
  if (head -> next != tail) {
    cout << head -> next -> data << '\n';
  } else cout << -1 << '\n';
}
 
void Deque::back() {
  if (tail -> prev != head) {
    cout << tail -> prev -> data << '\n';
  } else cout << -1 << '\n';
}
 
int main()
{
  cin.tie(NULL);
  ios::sync_with_stdio(false);
 
  Deque d;
 
  int TC, n;
  string str;
 
  cin >> TC;
 
  while (TC--) {
    cin >> str;
    if (str == "push_front") {
      cin >> n;
      d.pushFront(n);
    } else if (str == "push_back") {
      cin >> n;
      d.pushBack(n);
    } else if (str == "pop_front") {
      d.removeFront();
    } else if (str == "pop_back") {
      d.removeBack();
    } else if (str == "size") {
      cout << d.size << '\n';
    } else if (str == "empty") {
      cout << ((d.size > 0) ? 0 : 1<< '\n';
    } else if (str == "front") {
      d.front();
    } else if (str == "back") {
      d.back();
    }
  }
  return 0;
}
cs


에디터

정말 힘들게 풀었다. 좀 쉬운 문제를 풀고 다른 문제를 풀어도 되는데 시작부터 너무 어려운 문제를 풀었던 것 같다.


간단한 에디터를 구현하는 문제인데, "abcd"라는 문자가 주어지면 여기서 커서를 옮겨가면서 문자를 넣었다가 빼고 해야한다. 주의할 점은 문자가 n 개면 커서가 놓일 수 있는 곳은 n + 1 가지이다. 문자열 말고도 리스트에 포함된 것이 있는데, head 와 tail 이다. 나는 tail 을 맨 마지막에 놓고, head 를 맨 앞에 놔서 이 문제를 해결했다. head 를 제외한 모든 노드는 자신의 왼쪽에 새로운 노드를 추가할 수 있다. 그래서 "abcd" 와 tail 의 왼쪽에 문자를 넣을 수 있으므로 5개의 위치에 커서를 놓을 수 있다. 


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <iostream>
#include <string>
using namespace std;
 
struct Node
{
    char data;
    struct Node* next;
    struct Node* prev;
};
 
class List
{
private:
    Node *head;
    Node *tail;
    Node *currNode;
public:
    List() {
      head = new Node();
      tail = new Node();
      head -> prev = nullptr;
      tail -> next = nullptr;
      currNode = tail;
    }
    int cnt = 0;
    void insert(char data);
    void remove();
    void goNext();
    void goBack();
    void print();
};
 
void List::insert(char data) {
  if (cnt == 0) {
    Node *newNode = new Node();
    newNode -> data = data;
    newNode -> next = tail;
    newNode -> prev = head;
    head -> next = newNode;
    tail -> prev = newNode;
  } else {
    Node *newNode = new Node();
    Node *dummy = currNode -> prev;
    newNode -> data = data;
    newNode -> next = currNode;
    newNode -> prev = dummy;
    dummy -> next = newNode;
    currNode -> prev = newNode;
  }
  cnt++;
}
 
void List::remove() {
  if (currNode -> prev != head) {
    Node *dummy = currNode -> prev;
    currNode -> prev = dummy -> prev;
    dummy -> prev -> next = currNode;
    delete dummy;
  }
}
 
void List::goNext() {
  if (currNode -> next != nullptr) currNode = currNode -> next;
}
 
void List::goBack() {
  if (currNode -> prev != head) currNode = currNode -> prev;
}
 
void List::print() {
  Node *tmp = head -> next;
  while (tmp != tail) {
    cout << tmp -> data;
    tmp = tmp -> next;
  }
  cout << '\n';
}
 
int main() {
  cin.tie(NULL);
  ios::sync_with_stdio(false);
  List list;
  string str;
  int n;
  char ch;
  cin >> str;
  for (int i = 0; i < str.length(); i++) {
    list.insert(str[i]);
  }
  cin >> n;
  while (n--) {
    cin >> ch;
    if (ch == 'P') {
      cin >> ch;
      list.insert(ch);
    } else if (ch == 'L') {
      list.goBack();
    } else if (ch == 'D') {
      list.goNext();
    } else {
      list.remove();
    }
  }
  list.print();
  return 0;
}
 
cs