[Algorithm] Stack & Queue

Stack & Queue

알고리즘을 이야기 할 때, 혹은 공부하려 할 때 가장 먼저 접하는 이론은 아마 십중팔구는 Stack과 Queue 를 보게 될 것이다. 대학생때 배웠던 자료구조-알고리즘 수업도 1장은 인트로, 2장이 Array, 3장이 Stack & Queue 였었다.
(아, 적고보니 Array 부터 포스팅 해야하는 건가, 싶은 생각이 드는데..이건 다음에 해야겠다. 이렇게 컨텐츠 적립하는 거지 뭐)

그래서 첫 알고리즘 카테고리 포스팅으로 Stack 과 Queue를 생각했는데, 사실 이게 설명하기가 좀 애매한 구석이 있다. 그 애매한 게 뭐냐하면 너무 잘 알고 익숙한 것이라, 어떻게 설명을 해야 할 지 난감한게 문제다.

어떻게 걷고 뛰는 건지에 대한 방법론을, 서른 둘이 된 지금의 시점에서 누군가에게 설명하라고 한다면..음..그냥 다리를 움직이면 걷고 뛰어요..라는 생각이 맨 처음에 드는 거랑 같은 느낌이랄까.

그러니 일단, 정의부터 내려보자.


Stack

한 단어로 정의하자면, LIFO다. Last In, First Out. 마지막에 들어온 놈이, 가장 먼저 나간다. 즉 입구와 출구가 하나다. 땅으로 깊게 파 놓은 구덩이를 생각해보자.

그 구덩이에 데이터(변수든 Array든, 객체든 뭐든 여튼 하드웨어 적으로 메모리를 잡아먹는 무엇)를 집어넣고 그 위로 또 데이터를 집어넣는다. 그러고 나중에 데이터를 다시 꺼내려면, 옆으로 땅굴이라도 뚫지 않는 이상 가장 먼저 넣은 데이터를 우선적으로 꺼낼 수가 없다. 그 상태에서 꺼낼 수 있는 데이터는 가장 위에 보이는 데이터이다.

위 이미지는 Stack 이라는 안드로이드 게임인데, 실제 플레이를 해보면 계속해서 육면체 박스가 위로 쌓이기만 한다. 타이밍을 맞춰서 쌓고 가장 높은 위치까지 쌓는 것을 다투는 게임인데, 정말 이름을 따라서 쌓고, 또 쌓기만 한다(안타깝게도 꺼내진 않는다)

이처럼 Stack은 쌓고, 쌓은 걸 빼는 자료구조라고 생각하면 된다.
또한 범용적으로 쓰이는 용어가 있는데 데이터를 Stack에 넣는 것을 ‘밀어 넣는다’라는 의미로 push. Stack에 쌓인 데이터를 빼는 행위를 ‘꺼내다’라는 의미로 pop 이라고 부른다.

실제로 Stack을 코드로써 구현한 대부분의 API들은 push와 pop이라는 이름의 메서드를 만들어서 Stack에 데이터를 쌓고 데이터를 꺼내는데 활용되도록 가이드하고 있다.

실제 현업에서는 굳이 Stack을 코드로 한땀한땀 작성해서 사용하지는 않는다. 대학생, 혹은 자료구조를 처음 공부하는 입장에서는 직접 구현해보는 것이 도움이 되겠지만, 이미 C++이나 Java등의 언어에서 기본 적인 자료구조는클래스 형태로 제공을 하고 있기 때문이다. 거기에 위에서 말한 push, pop 이외에도 size,empty등 Stack을 활용함에 있어서 부가적으로 필요한 정보들을 리턴해주는 메서드들도 제공해주고 있기 때문에 우리는 잘 만들어진 아이들을 잘 사용해주면 된다.

두 언어에 대한 짧은 사용 예시를 아래에 함께 하니 참고하기 바란다.
C++의 경우 #include<stack>

#include<iostream>
#include<stack>

int main(){
stack<int> stack;

stack.push(4);
stack.push(5);
stack.push(1);

cout << stack.size() << endl; // 3
cout << stack.top() << endl; // 1

stack.pop();
cout << stack.size() << endl; // 2
cout << stack.top() << endl; // 5

}

Java의 경우 import java.util.Stack;

import java.util.Stack;

public class StackExample {
public static void main(String[] args){
Stack<Integer> stack = new Stack();

stack.push(4);
stack.push(5);
stack.push(1);

System.out.println(stack.size()); // 3
System.out.println(stack.peek()); // 1

System.out.println(stack.size()); // 3
System.out.println(stack.pop()); // 1

System.out.println(stack.size()); // 2
System.out.println(stack.peek()); // 5

}
}


Queue

와..Stack에 대한 글이 생각보다 길어졌다. 사실 이렇게 길게 적을 거라곤 생각 안 했는데, 예시 코드와 함께 쓰다보니 좀 길어진 거 같다. 그럼 이제 Stack 과 늘 함께 설명되는 Queue에 대해 포스팅을 해보겠다.

Stack과 Queue는 둘다 선형 알고리즘이다(물론 Queue의 경우 환형도 있긴하지만).
‘선형’. 데이터를 저장하고 활용하는 방식이 ‘선’을 그은 것과 같은 형태를 띈다고 해서 선형 알고리즘이라고 불리운다. 앞에서 설명한 Stack을 생각해보자. 입구와 출구가 하나인 구덩이를 예시로 들었었다. 그 구덩이도 잘 보면 세로로 세워진 선과 같은 형태이다.

그럼 Queue는 Stack과 무엇이 다를까?

일단 Queue는 FIFO다. First In First Out. 먼저 들어온 데이터가 먼저 나간다. 즉, 데이터가 들어오는 입구와 출구가 별개다. 다만, 별개라고 해서 내가 사용하고자 하는 데이터가 중간쯤 들어왔는데 얘부터 먼저 쏙 빼서 사용할 수는 없다. 먼저 들어온 데이터가, 먼저 나가야 하는 것이 Queue의 원칙이자 정의이다.

이 사진은 2014년에 영국 여행을 하며 본 안내문이다. 당시 관광지에 들어가기 위한 대기줄을 서 있었고 이 안내문을 보고는 단박에 Queue에 대한 깨달음을 얻을 수 있었다. 늘 코드와 이론으로만 보던 내용을 이렇게 실생활에서 보게 되다니, 신기할 따름이었다. 사실상 영어단어로써의 Queue는 이와 같이 무언가를 하기 위해 일렬로 늘어선 사람들로 이루어진 줄을 의미하기도 하는데, 실제로 이렇게 대기줄로 형성된 사람들은 가장 먼저 선 사람이 볼 일을 보고 다음 사람이 순번을 이어받게 된다. First In, First Out 의 형태인 것이다.

이와 동일한 예제로 내가 대학생 시절 받았던 Queue관련 과제는 은행의 업무처리 시스템을 개발하는 것이었다. 말해놓고보니 되게 거창한 과제 같은데, 실제 돈을 송금하고 인출하고 하는 은행 시스템을 생각한다면 오산이다. 과제 설명을 조금 하자면 은행원이 3명이 있을 때 각 은행원 별로 능력의 역차가 있어서 하나의 일에 대해 A는 3분, B는 5분, C는 1분이 걸려 일을 처리한다고 가정한다. 거기에 손님들이 9시부터 1분에 한 명씩 입장할 때에 은행에 업무가 종료되는 가장 빠른 시각은 언제인가, 를 구하는 과제였다.
전형적인 대기줄(Queue)문제였는데, 정확치는 않지만 해결하는데 이틀 정도 걸렸던 것 같다(이틀 내내 했다는게 아니라..학교가고 밥 먹고 잠자고 놀고 할 거 다 하고…)

물론, Queue 또한 Stack 처럼 잘 작성 된 API들이 존재하므로 필요시 가져다 잘 사용해주기만 하면 된다. 가장 대표적인 C++과 Java의 예시를 아래에 작성하니 참고바란다.

C++의 경우 #include<queue>

#inlcude<iostream>
#include<queue>
using namespace std;

int main(){
queue<int> q;

q.push(4);
q.push(5);
q.push(1);

cout << q.size() << endl; // 3
cout << q.front() << endl; // 4
cout << q.back() << endl; // 1

q.pop();
cout << stack.size() << endl; // 2
cout << q.front() << endl; // 5
cout << q.back() << endl; // 1

}

Java의 경우 import java.util.Queue;

import java.util.LinkedList;
import java.util.Queue;

public class StackExample {
public static void main(String[] args){
Queue<Integer> q = new LinkedList<Integer>();

q.offer(4);
q.offer(5);
q.offer(1);

System.out.println(q.size()); // 3
System.out.println(q.peek()); // 4

System.out.println(q.size()); // 3
System.out.println(q.poll()); // 4

System.out.println(q.size()); // 2
System.out.println(q.peek()); // 5

}
}

Share Comments

[Hexo] Github Page로 블로그 만들기 08

블로그 포스팅은 끝날 길이 없어보인다.
하나를 해결하면 하나의 특이점이 나와서..해야 할 게 늘어나버리는 거 같다.

오늘 포스팅하는 내용도 비슷한 맥락이다.
7번째 블로그 포스팅을 마지막으로 더 이상 블로그 만들기에 대한 포스팅을 할 일이 없을거라 생각했는데, 나의 오산이었다. 블로그에 알고리즘 관련 글을 포스팅하려고 하다보니 문제점을 하나 찾았는데, Markdown 코드블럭에 하이라이팅이 되지 않고 있었다.

보통 마크다운운은 ``` 이렇게 따옴표 3개로 열고 닫는 사이에 프로그램 코드를 작성하면 테마에 따라서 표시를 해준다. 클래스명은 클래스명대로, 변수명은 변수명대로, 자료형은 자료형대로, 예약어는 예약어대로..색의 분간을 줘서 보는 사람이 좀 더 편하게 볼 수 있도록 해주는 것이다.

근데 그 기능이 동작하지 않고 있었다.

생각해보면 기존에 올렸던 명령어들에서도 그 동작이 일어났어야 하는건데 그냥 까만 배경에 회색 글씨였는데..이걸 왜 이제서야 눈치챈 건지.

하이라이팅 관련해서는 내가 사용하는 icarus 테마에서 지원하는 기능이 있었다.
highlight.js를 디폴트값으로 해서 _config.yml 파일에 옵션을 줌으로써 제공이 되어야 하는데…실제 띄워놓은 서버를 보니 동작을 하지 않고 있었다.

짧은 코드야 괜찮지만, 코드가 길어질 경우에는 가독성에서 확실히 차이가 난다.
그리고 이 블로그는 기술 블로그이기 때문에 언제, 어떤 식으로든 코드가 올라 올 것이다.
그렇기에 코드 하이라이팅은 중요한 기능 중에 하나라서, 오늘 또 해법을 찾아 이리저리 돌아다녔다.


찾은 방법은 총 3가지였다.

  1. icarus 에서 제공하는 기본 기능.
  2. hexo-prism-plugin 이라는 별도의 npm package
  3. hexo의 기본 기능

결론부터 말하자면 3. hexo의 기본 하이라이팅 기능을 사용하게 되었다.
이유는 간단하다…3번이 너무 강력해서 서버를 띄웠을 때 1,2번이 동작을 하지 않았다.
(물론 내가 1,2번을 정확하게 적용하는 법을 모른 것일 수도 있다.)

해결법부터 소개를 하자면

이것도 결국 7번에 포스팅(이미지 첨부 관련)했던 것과 마찬가지로 태그 플러그인을 사용하게 되었다.
사실 태그 플러그인 페이지를 가봐도 코드에 대해서 Markdown처럼 장문의 코드를 ``` 로 처리하라고 되 있지만..
이걸 사용하면 정말 딱, 코드인 것처럼 보이면서 + 라인 줄 수 정도만 알 수 있다.

사용된 코드가 C인지 Java인지 Javascript인지 SQL인지..알 수가 없다.

하지만 코드 태그 플러그인을 사용하면 어떤 종류의 코드인지를 명시해 줄 수 있고, 명시된 코드의 형태에 따라서 하이라이팅이 적용된다.
사용법은 아래와 같다(실제 사용시에는 중괄호와 퍼센테이지 사이를 붙여야 한다.)

{ % codeblock lang:java % }
코드 작성 부분
{ % endcodeblock % }

이와 같은 형태로 사용해주면 되며 lang 옵션에 내가 사용한 언어의 종류를 적어주면 된다.
lang 옵션을 주지 않으면 그냥 까만 배경에 회색글씨로 표현이 되는 형태로 보이게 되며, 실제로 들어갈 수 있는 값은 highlight.js demo에서 확인할 수 있으며 우리가 사용하는 대부분의 프로그래밍 언어들은 있다고 보면 된다.


1번과 2번

혹시나 나와 달리 1번과 2번 방법들로 성공시켜보고자 하시는 분들이 있을까봐 글을 좀 더 써본다.

1번. icarus에서 제공하는 기본 기능

icarus에서 제공하는 기본 기능에 대한 사용법은 이 링크에 들어가보면 간략히 설명이 나와있는데…
사실 themes > _config.yml 에 있는 customize: 아래에 highlight: 항목에 테마명을 명시하라는 게 전부였다.
그리고 거기에 명시가능한 테마의 이름은 themes > icarus테마 > source > css > _highlight 에서 확인할 수 있음..

겨우 이 설명이 전부였다. 이 설명을 따라 _config.yml 파일에서 테마명을 변경해 봤지만, 동작하지 않았다.
그래서 이 값도 저 값도 바꿔봤지만, 역시나 fail..다른 방법을 모색했고 그러다 찾은 게 아래에 나오는 2번 방법이다.

2번. hexo-prism-plugin 이라는 별도의 npm package

1번의 방법이 실패하고 구글링을 시작했다.
hexo icarus highlight, hexo code highlight, hexo code, hexo markdown code등등..수많은 키워드들로 구글링을 하고 Github Wiki를 봤지만 마땅한 해법이 나오지 않았다.
그렇게 계속 삽질을 하다가 보인 것이 code highlight를 해주는 npm package 였다.

npm-prism-plugin의 설명도 비교적 심플하다.
들어가보면 알겠지만 npm i -S hexo-prism-plugin 로 해당 패키지를 설치하고
블로그 디렉토리 > _config.yml에 관련 옵션값을 설정한다.
그 뒤에 hexo clean, hexo generate를 통해서 정적파일들을 새롭게 빌드하고 서버를 올리면 코드에 하이라이팅이 먹힌다는 게, 해당 패키지의 설명이었다.
단, 이때 hexo가 기본적으로 제공하는 highlight가 disabled 되어야 하므로 _config.yml에서 false로 값을 줘야 했는데…이렇게 하고 서버를 올리니, 데헿, 아예 블럭단위의 코드가 먹지를 않는다
(여러줄의 코드들이 전부 한 줄짜리 코드들처럼 하이라이팅되어 나오더라)

그래서 아,이것도 안되나보다 하고 package.json과 node_modules 디렉토리에 새로 설치된 패키지들을 지우고 어찌해야하나 고민하다가, 아 잠깐? 기본 코드 하이라이팅을 false 해서 다른 애들이 아예 안 먹는거면 가장 강력한 코드 하이라이팅 도구가 hexo의 기본 도구 아닌가? 라는 생각에 도달하였고 그 생각을 바탕으로 hexo 공홈을 뒤지기 시작했다.
그러다 찾은 게 태그 플러그인을 사용하는 코드 블럭 작성이었고, 이 포스팅의 결론과 같은 답을 찾게 된 것이다.

위에서도 말했듯, 3가지의 방법이 있었고 나는 그 중 3번 방법을 택한 것일 뿐이다.
이 글을 참고해서 자신의 블로그에 적용했는데 1번이나 2번 기능이 제대로 동작한다면, 마음에 드는 방법을 선택하며 된다.

Share Comments

180504_근황

음, 오랜만에 포스팅이다.
그간, 좀 바빴다…라는 건 좀 핑계고, 기술 블로그에 뭘 써야 할 지 고민을 했다.

지금 하고 있는 웹 관련 기술을 정리할까 싶다가
예전에 그 첨예한논리적 감각을 일깨울까 싶어 알고리즘을 정리할까 싶다가
최근에 보고 있던 안드로이드를 할까 싶다가 그냥 신기술동향이나 찾아볼까 하다가,
그렇게 하다가 시간을 또 보냈다.

정말 쓸데없이.

그렇다고 해서 그간 놀기만 한 건 아니다.
Vue.js 를 좀 더 깊이 보고 싶은 욕심이 들어서 관련 공부를 했고 지금은 적당하다 싶을 정도로 활용할 수 있을 레벨이 되었다. Vue.js 라는 UI Framework이론에 맞춰서 설계를 하고 간략한 컴포넌트를 개발할 수 있을 정도랄까(물론, 심도있고 복잡한 건 또 다른 이야기다)

그 사이에 안드로이드도 좀 급하게 해야 할 일이 있어서 집에서 금,토,일,월의 자체 3박 4일 해커톤을 혼자 진행했다가 피곤에 찌들어서 좀비로 살기도 했었고.
알고리즘 문제를 풀 때 유용한 자바 코드들을 정리해서 문제를 풀며 감을 익히는 공부도 했고, 개인적으론 삿포로 여행도 다녀왔다.

…뭐, 그냥 이래저래 바빴다는 이야기다.
이제 틈바구니 같은 시간이 생겼으니(오늘부터 3일 연휴, 야호!) 그간 못 한 기술 포스팅을 좀 하려한다.

Share Comments