데크
선형 자료구조 - 데크
데크 (Deque)
양쪽에서 삽입과 삭제가 모두 가능한 자료구조
Deque: Doubly-ended Queue
Stack과 Queue 를 합친 형태
데크 기본 구조
데크의 기본 구조는 양방향에서 삽입 삭제 가능한 구조
일부 기능을 제한하여 용도에 맞게 변형 가능
입력제한 데크 (Scroll)
한 쪽의 입력을 제한한 데크
출력제한 데크 (Shelf)
한 쪽의 출력을 제한한 데크
데크 구현
// 선형 자료구조 - 데크
import java.util.ArrayDeque;
import java.util.Deque;
public class Main {
public static void main(String[] args) {
Deque deque = new ArrayDeque();
// Front 부분 입력
deque.addFirst(1);
deque.addFirst(2);
deque.addFirst(3);
System.out.println(deque);
// Rear 부분 입력
deque.addLast(10);
deque.addLast(20);
deque.addLast(30);
System.out.println(deque);
// Front 부분 출력
System.out.println(deque.removeFirst());
System.out.println(deque);
// Rear 부분 출력
System.out.println(deque.removeLast());
System.out.println(deque);
System.out.println(deque.removeLast());
System.out.println(deque.removeLast());
System.out.println(deque.removeLast());
System.out.println(deque.removeLast());
System.out.println(deque);
System.out.println(deque.pollLast());
System.out.println(deque.removeLast());
}
}
[3, 2, 1]
[3, 2, 1, 10, 20, 30]
3
[2, 1, 10, 20, 30]
30
[2, 1, 10, 20]
20
10
1
2
[]
null
Exception in thread "main" java.util.NoSuchElementException
at java.base/java.util.ArrayDeque.removeLast(ArrayDeque.java:372)
at Main.main(Main.java:37)
ArrayList 를 이용한 데크 구현
// Practice1
// ArrayList 를 이용한 데크 구현
import java.util.ArrayList;
class MyDeque1 {
ArrayList list;
MyDeque1() {
this.list = new ArrayList();
}
public boolean isEmpty() {
if (this.list.size() == 0) {
return true;
} else {
return false;
}
}
public void addFirst(int data) {
this.list.add(0, data);
}
public void addLast(int data) {
this.list.add(data);
}
public Integer removeFirst() {
if (this.isEmpty()) {
System.out.println("Deque is empty!");
return null;
}
int data = (int)this.list.get(0);
this.list.remove(0);
return data;
}
public Integer removeLast() {
if (this.isEmpty()) {
System.out.println("Deque is empty!");
return null;
}
int data = (int)this.list.get(this.list.size() - 1);
this.list.remove(this.list.size() - 1);
return data;
}
public void printDeque() {
System.out.println(this.list);
}
}
public class Practice1 {
public static void main(String[] args) {
// Test code
MyDeque1 myDeque = new MyDeque1();
// Front 부분 입력
myDeque.addFirst(1);
myDeque.addFirst(2);
myDeque.addFirst(3);
myDeque.printDeque(); // 3 2 1
// Rear 부분 입력
myDeque.addLast(10);
myDeque.addLast(20);
myDeque.addLast(30);
myDeque.printDeque(); // 3 2 1 10 20 30
// Front 부분 출력
System.out.println(myDeque.removeFirst()); // 3
myDeque.printDeque(); // 2 1 10 20 30
// Rear 부분 출력
System.out.println(myDeque.removeLast()); // 30
myDeque.printDeque(); // 2 1 10 20
System.out.println(myDeque.removeLast()); // 20
System.out.println(myDeque.removeLast()); // 10
System.out.println(myDeque.removeLast()); // 1
System.out.println(myDeque.removeLast()); // 2
myDeque.printDeque();
}
}
[3, 2, 1]
[3, 2, 1, 10, 20, 30]
3
[2, 1, 10, 20, 30]
30
[2, 1, 10, 20]
20
10
1
2
[]
배열을 이용한 기본 데크 직접 구현
// Practice2
// 배열을 이용한 기본 데크 직접 구현
class MyDeque2 {
int[] arr;
int front = 0;
int rear = 0;
MyDeque2(int size) {
this.arr = new int[size + 1];
}
public boolean isEmpty() {
return this.rear == this.front;
}
public boolean isFull() {
return (this.rear + 1) % this.arr.length == this.front;
}
public void addFirst(int data) {
if (this.isFull()) {
System.out.println("Deque is full!");
return;
}
this.arr[front] = data;
this.front = (this.front - 1 + this.arr.length) % this.arr.length;
}
public void addLast(int data) {
if (this.isFull()) {
System.out.println("Deque is full!");
return;
}
this.rear = (this.rear + 1) % this.arr.length;
this.arr[this.rear] = data;
}
public Integer removeFirst() {
if (this.isEmpty()) {
System.out.println("Deque is empty!");
return null;
}
this.front = (this.front + 1) % this.arr.length;
return this.arr[this.front];
}
public Integer removeLast() {
if (this.isEmpty()) {
System.out.println("Deque is empty!");
return null;
}
int data = this.arr[this.rear];
this.rear = (this.rear - 1 + this.arr.length) % this.arr.length;
return data;
}
public void printDeque() {
int start = (this.front + 1) % this.arr.length;
int end = (this.rear + 1) % this.arr.length;
for (int i = start; i != end; i = (i + 1) % this.arr.length) {
System.out.print(this.arr[i] + " ");
}
System.out.println();
}
}
public class Practice2 {
public static void main(String[] args) {
// Test code
MyDeque2 myDeque = new MyDeque2(5);
// Front 부분 입력
myDeque.addFirst(1);
myDeque.addFirst(2);
myDeque.addFirst(3);
myDeque.printDeque(); // 3 2 1
// Rear 부분 입력
myDeque.addLast(10);
myDeque.addLast(20);
myDeque.addLast(30); // Deque is full!
myDeque.printDeque(); // 3 2 1 10 20
// Front 부분 출력
System.out.println(myDeque.removeFirst()); // 3
myDeque.printDeque(); // 2 1 10 20
// Rear 부분 출력
System.out.println(myDeque.removeLast()); // 20
myDeque.printDeque(); // 2 1 10
System.out.println(myDeque.removeLast()); // 10
System.out.println(myDeque.removeLast()); // 1
System.out.println(myDeque.removeLast()); // 2
System.out.println(myDeque.removeLast()); // Deque is empty!
}
}
3 2 1
Deque is full!
3 2 1 10 20
3
2 1 10 20
20
2 1 10
10
1
2
Deque is empty!
null
문제 풀이
// Practice1
// 데이터 재정렬
// D_0 -> D_1 -> ... -> D_n-1 -> D_n 순으로 되어 있는 데이터를
// D_0 -> D_n -> D_1 -> D_n-1 -> ... 순이 되도록 재정렬 하시오.
// 입력 예시)
// 입력 데이터: 1 -> 2 -> 3 -> 4 -> 5
// 출력 데이터: 1 -> 5 -> 2 -> 4 -> 3
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.stream.IntStream;
public class Practice1 {
public static void reorderData(int[] arr) {
Deque deque = new ArrayDeque();
ArrayList result = new ArrayList();
IntStream.of(arr).forEach(x -> deque.addLast(x));
System.out.println(deque);
while (!deque.isEmpty()) {
result.add(deque.removeFirst());
if (!deque.isEmpty()) {
result.add(deque.removeLast());
}
}
System.out.println("== 정렬 전 ==");
printData(arr);
System.out.println("== 정렬 후 ==");
printData(result.stream().mapToInt(x -> (int)x).toArray());
}
public static void printData(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
System.out.print(arr[i] + " -> ");
}
System.out.println(arr[arr.length - 1]);
}
public static void main(String[] args) {
// Test code
int[] arr = {1, 2, 3, 4, 5};
reorderData(arr); // 1 -> 5 -> 2 -> 4 -> 3
int[] arr2 = {1, 2, 3, 4, 5, 6, 7};
reorderData(arr2); // 1 -> 7 -> 2 -> 6 -> 3 -> 5 -> 4
}
}
[1, 2, 3, 4, 5]
== 정렬 전 ==
1 -> 2 -> 3 -> 4 -> 5
== 정렬 후 ==
1 -> 5 -> 2 -> 4 -> 3
[1, 2, 3, 4, 5, 6, 7]
== 정렬 전 ==
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7
== 정렬 후 ==
1 -> 7 -> 2 -> 6 -> 3 -> 5 -> 4
// Practice2
// Palindrome 찾기
// Palindrome 이면 true, 아니면 false 를 반환하세요.
// Palindrome: 앞으로 읽어도 거꾸로 읽어도 같은 문자열
// 입출력 예시)
// 입력: a
// 결과: true
// 입력: madam
// 결과: true
// 입력: abab
// 결과: false
import java.util.ArrayDeque;
import java.util.Deque;
public class Practice2 {
public static boolean checkPalindrome(String str) {
Deque deque = new ArrayDeque();
boolean isFront = true;
boolean isPalindrome = true;
for (String s: str.split("")) {
deque.addFirst(s);
}
while (!deque.isEmpty()) {
String s1 = (String)deque.pollFirst();
String s2 = (String)deque.pollLast();
if (s1 != null && s2 != null && !s1.equals(s2)) {
isPalindrome = false;
break;
}
}
return isPalindrome;
}
public static void main(String[] args) {
// Test code
System.out.println(checkPalindrome("a")); // true
System.out.println(checkPalindrome("aba")); // true
System.out.println(checkPalindrome("abba")); // true
System.out.println(checkPalindrome("abab")); // false
System.out.println(checkPalindrome("abcba")); // true
System.out.println(checkPalindrome("abccba")); // true
System.out.println(checkPalindrome("madam")); // true
}
}
true
true
true
false
true
true
true
// Practice3
// 데크 변형
// 기본 데크 구조에서 중간에 데이터를 추가하는 기능을 구현하세요.
// 단, 추가적인 자료구조 생성하지 말고 구현
// 입력 예시)
// 초기 데크 상태 (size: 5)
// -> 1, 2, 3, 4
// 중간 입력: 10
// 결과 데크
// -> 1, 2, 10, 3, 4
class MyDeque {
int[] arr;
int front = 0;
int rear = 0;
MyDeque(int size) {
this.arr = new int[size + 1];
}
public boolean isEmpty() {
return this.rear == this.front;
}
public boolean isFull() {
return (this.rear + 1) % this.arr.length == this.front;
}
public void addFirst(int data) {
if (this.isFull()) {
System.out.println("Deque is full!");
return;
}
this.arr[front] = data;
this.front = (this.front - 1 + this.arr.length) % this.arr.length;
}
public void addLast(int data) {
if (this.isFull()) {
System.out.println("Deque is full!");
return;
}
this.rear = (this.rear + 1) % this.arr.length;
this.arr[this.rear] = data;
}
public void addMiddle(int data) {
if (this.isFull()) {
System.out.println("Deque is full!");
return;
}
int elements = this.rear - this.front;
if (elements < 0) {
elements = this.arr.length + elements;
}
int mid = (this.rear - elements / 2 + this.arr.length) % this.arr.length + 1;
int start = (this.rear + 1) % this.arr.length;
int end = (this.rear - elements / 2 + this.arr.length) % this.arr.length;
for (int i = start; i != end ; i = (i - 1 +this.arr.length) % this.arr.length) {
this.arr[i] = this.arr[(i - 1 + this.arr.length) % this.arr.length];
}
this.arr[mid] = data;
this.rear = (this.rear + 1) % this.arr.length;
}
public Integer removeFirst() {
if (this.isEmpty()) {
System.out.println("Deque is empty!");
return null;
}
this.front = (this.front + 1) % this.arr.length;
return this.arr[this.front];
}
public Integer removeLast() {
if (this.isEmpty()) {
System.out.println("Deque is empty!");
return null;
}
int data = this.arr[this.rear];
this.rear = (this.rear - 1 + this.arr.length) % this.arr.length;
return data;
}
public void printDeque() {
int start = (this.front + 1) % this.arr.length;
int end = (this.rear + 1) % this.arr.length;
for (int i = start; i != end; i = (i + 1) % this.arr.length) {
System.out.print(this.arr[i] + " ");
}
System.out.println();
}
}
public class Practice3 {
public static void main(String[] args) {
// Test code
MyDeque myDeque1 = new MyDeque(5);
myDeque1.addLast(1);
myDeque1.addLast(2);
myDeque1.addLast(3);
myDeque1.addLast(4);
myDeque1.printDeque();
myDeque1.addMiddle(10);
myDeque1.printDeque();
MyDeque myDeque2 = new MyDeque(5);
myDeque2.addLast(10);
myDeque2.addLast(10);
myDeque2.addLast(10);
myDeque2.addLast(10);
myDeque2.addLast(10);
myDeque2.removeFirst();
myDeque2.removeFirst();
myDeque2.removeFirst();
myDeque2.removeFirst();
myDeque2.addLast(11);
myDeque2.addLast(12);
myDeque2.addLast(13);
myDeque2.printDeque();
myDeque2.addMiddle(100);
myDeque2.printDeque();
}
}
1 2 3 4
1 2 10 3 4
10 11 12 13
10 11 100 12 13
// Practice4
// 데크 리사이즈
// 기본 데크 구조에서 데크 공간이 full 일 때 데이터를 추가하는 경우,
// 데크 공간을 2배 씩 늘려주는 코드를 작성하세요.
class MyDeque2 {
int[] arr;
int front = 0;
int rear = 0;
MyDeque2(int size) {
this.arr = new int[size + 1];
}
public boolean isEmpty() {
return this.rear == this.front;
}
public boolean isFull() {
return (this.rear + 1) % this.arr.length == this.front;
}
public void increaseSize() {
System.out.println("MyDeque2.increaseSize");
int[] arrTmp = this.arr.clone();
this.arr = new int[this.arr.length * 2];
int start = (this.front + 1) % arrTmp.length;
int end = (this.rear + 1) % arrTmp.length;
int idx = 1;
for (int i = start; i != end ; i = (i + 1) % arrTmp.length) {
this.arr[idx++] = arrTmp[i];
}
this.front = 0;
this.rear = idx - 1;
}
public void addFirst(int data) {
if (this.isFull()) {
// System.out.println("Deque is full!");
// return;
this.increaseSize();
}
this.arr[front] = data;
this.front = (this.front - 1 + this.arr.length) % this.arr.length;
}
public void addLast(int data) {
if (this.isFull()) {
// System.out.println("Deque is full!");
// return;
this.increaseSize();
}
this.rear = (this.rear + 1) % this.arr.length;
this.arr[this.rear] = data;
}
public Integer removeFirst() {
if (this.isEmpty()) {
System.out.println("Deque is empty!");
return null;
}
this.front = (this.front + 1) % this.arr.length;
return this.arr[this.front];
}
public Integer removeLast() {
if (this.isEmpty()) {
System.out.println("Deque is empty!");
return null;
}
int data = this.arr[this.rear];
this.rear = (this.rear - 1 + this.arr.length) % this.arr.length;
return data;
}
public void printDeque() {
int start = (this.front + 1) % this.arr.length;
int end = (this.rear + 1) % this.arr.length;
for (int i = start; i != end; i = (i + 1) % this.arr.length) {
System.out.print(this.arr[i] + " ");
}
System.out.println();
}
}
public class Practice4 {
public static void main(String[] args) {
// Test code
MyDeque2 myDeque = new MyDeque2(5);
myDeque.addLast(1);
myDeque.addLast(2);
myDeque.addLast(3);
myDeque.addLast(4);
myDeque.addLast(5);
myDeque.printDeque();
myDeque.addLast(6);
myDeque.addLast(7);
myDeque.addLast(8);
myDeque.addLast(9);
myDeque.addLast(10);
myDeque.printDeque();
myDeque.removeLast();
myDeque.removeLast();
myDeque.addFirst(100);
myDeque.addFirst(200);
myDeque.printDeque();
myDeque.addFirst(300);
myDeque.addFirst(400);
myDeque.addFirst(500);
myDeque.printDeque();
}
}
1 2 3 4 5
MyDeque2.increaseSize
1 2 3 4 5 6 7 8 9 10
200 100 1 2 3 4 5 6 7 8
MyDeque2.increaseSize
500 400 300 200 100 1 2 3 4 5 6 7 8
출처 : 제로베이스
Leave a comment