1. 스택이란
- 가장 나중에 쌓은 데이터를 가장 먼저 빼낼 수 있는 데이터구조 (LIFO)
2. 스택의 제약
- 데이터는 스택의 끝에만 삽입가능
- 데이터는 스택의 끝에서만 읽을 수 있다.
- 데이터는 스택의 끝에서만 삭제할 수 있다.
3. 스택의 활용
- 오래 사용할 데이터를 저장할 때는 일반적으로 스택을 사용하지 않지만 임시 데이터를 다뤄야 하는 알고리즘에서는 스택이 유용한 도구
- 컴퓨터 내부의 프로세스 구조의 함수 동작 방식
4. 스택 예제
- 재귀함수가 대표적인 예제이다.
def recursive(data)
if data < 0
puts "end"
else
puts data
recursive(data-1)
puts "returned #{data}"
end
end
5. 스택의 장단점
- 장점 : 구현이 쉽고 데이터 저장/읽기 속도가 빠르다
- 단점
- 데이터 최대 갯수를 미리 정해야 한다 (파이썬의 경우 재귀함수는 1000번까지만 호출 가능)
- 저장공간 낭비가 발생 (미리 최대갯수만큼 저장공간 확보해야되기 때문)
6. 괄호 문법 검사 코드 예제
- 괄호 문법 오류 3가지
- 오류타입1 : 여는 괄호는 있는데 대응하는 닫는 괄호 없는 경우
- 오류타입2 : 여는 괄호가 나오지 않았는데 닫는 괄호 나오는 경우
- 오류타입3 : 닫는 괄호가 바로 앞에 나온 여는 괄호와 종류가 다른 경우
- 규칙
- 괄호가 아닌 모든 문자는 무시하고 넘어감
- 여는 괄호가 나오면 스택에 푸시. 스택에 넣는다는 것은 이 괄호가 닫히기를 기다린다는 의미이다
- 닫는 괄호가 나오면 스택 확인. 그리고 아래와 같이 분석
- 스택에 원소가 없으면 닫는 괄호에 대응하는 여는 괄호가 없는 것이다. 오류타입2이다.
- 스택에 데이터가 있지만, 괄호 종류가 다르다. 오류타입3이다.
- 닫는 괄호가 스택 위에 있는 원소와 괄호 종류와 같다면 여는 괄호를 성공적으로 닫았다는 뜻이다. 해당 원소를 스택에서 팝한다.
- 줄 끝에 도달했는데 스택에 여전히 남아있는 괄호가 있다면 닫는 괄호가 없다는 의미이다. 오류타입1이다.
- 코드예제
class Linter
attr_reader :error
def initialize
@stack = []
end
def lint(text)
text.each_char.with_index do |char, index|
if opening_brace?(char)
@stack.push(char)
elsif closing_brace?(char)
if closes_most_recent_opening_brace?(char)
# 닫는 괄호 문자가 가장 최근에 나온 여는 괄호를 닫았다면 스택에서 해당 괄호를 팝한다
@stack.pop
else # 닫는 괄호문자가 가장 최근에 나온 여는 괄호를 닫지 않았다면
@error = "incorrect closing brace: #{char} at index #{index}"
return
end
end
end
if @stack.any?
# 줄 끝에 도달했는데 스택이 비어있지 않다면 대응하는 닫는 괄호가 나오지 않은 여는 괄호가 있는 것
@error = "#{@stack.last} does not have a closing brace"
end
end
private
def opening_brace?(char)
["(", "[", "{"].include?(char)
end
def closing_brace?(char)
[")", "]", "}"].include?(char)
end
def opening_brace_of(char)
{")"=>"(", "]"=>"[", "}"=>"{"}[char]
end
def most_recent_opening_brace
@stack.last
end
def closes_most_recent_opening_brace?(char)
opening_brace_of(char) == most_recent_opening_brace
end
end
linter = Linter.new
lint.lint("(var x = {y: [1,2,3])}")
puts linter.error # Incorrect closing brace: ) at index 25
linter1 = Linter.new
lint1.lint("(var x = {y: [1,2,3])}")
puts linter1.error # ( does not have a closing brace
** 패스트캠퍼스의 '알고리즘/기술면접 완전 정복 올인원 패키지' 강의를 듣고 작성한 글입니다
'TIL > Data Structures and Algorithms' 카테고리의 다른 글
(자료구조) 배열 (0) | 2022.04.08 |
---|---|
(자료구조) 큐(QUEUE) (0) | 2021.02.03 |
(알고리즘) 최단경로 알고리즘 - 다익스트라 알고리즘 (0) | 2021.01.29 |
(알고리즘) 탐욕 알고리즘 (0) | 2021.01.28 |
(알고리즘) 깊이우선탐색 (DFS) (0) | 2021.01.28 |