[Date Structure] 스택
1. 스택
- Stack : 자료의 입출력이 후입선출(LIFO)의 형태로 일어나는 자료구조
- 스택 상단(Stack top) : 스택에서 입출력이 이루어지는 부분
- 스택 하단(stack bottom) : 반대쪽인 바닥 부분
- 요소(element, 항목) : 스택에 저장되는 것
- 공백(empty) 상태 : 스택에 요소가 하나도 없는 경우
- 포화(full) 상태 : 상태가 꽉 차서 더 이상 요소를 넣을 수 없는 상태
추상 자료형
데이터 : 후입선출(LIFO)의 접근 방법을 유지하는 요소들의 모임
연산
- init() : 스택을 초기화한다.
- is_empty() : 스택이 비어 있으면 TRUE를 반환하고 아니면 FALSE를 반환한다.
- is_full() : 스택이 가득 차 있으면 TRUE를 반환하고 아니면 FALSE를 반환한다.
- size() : 스택 내의 모든 요소들의 개수를 반환한다.
- push(x) : 주어진 요소 x를 스택의 맨 위에 추가한다.
- pop() : 스택 맨 위에 있는 요소를 삭제하고 반환한다.
- peek() : 스택 맨 위에 있는 요소를 삭제하지 않고 반환한다.
2. 배열을 이용한 스택의 구현
- 상수 MAX_STACK_SIZE : 스택에 저장할 수 있는 최대 요소의 개수
- 변수 top : 가장 최근에 입력된 항목의 위치
공백상태 : top = -1
포화상태 : top = MAX_STACK_SIZE - 1
#include <stdio.h>
#include <stdlib.h>
#define MAX_STACK_SZIE 100
// int를 저장하는 스택
typedef int Element;
Element data[MAX_STACK_SZIE];
int top;
// 구조체를 저장하는 스택
typedef struct Student {
int id;
char name[32];
char dept[32];
} Student;
typedef Student Element;
Element data[MAX_STACK_SZIE]
void error(char str[])
{
printf("%c", str);
exit(1);
}
void init_stack() {top = -1;}
int is_empty() {return top = -1;}
int is_full() {return top = MAX_STACK_SZIE - 1;}
int size() {return top + 1;}
void push(Element e)
{
if (is_full())
error("포화 상태 에러");
data[++top] = e;
}
Element pop()
{
if (is_empty())
error("공백 상태 에러");
return data[top--];
}
Element peek()
{
if (is_empty())
error("스택 공백 에러");
return data[top];
}
3. 연결 리스트를 이용한 스택의 구현
#include <stdio.h>
#include <stdlib.h>
typedef int Element;
typedef struct LinkedNode {
Element data;
struct LinkedNode *link;
} Node;
Node* top = NULL;
void error(char* str)
{
fprintf(stderr, "%s\n", str);
exit(1);
}
void init_stack() {top = NULL;}
int is_empty() {return top == NULL;}
int size()
{
Node* p;
int count = 0;
for (p = top; p -> link == NULL; p = p -> link) count++;
return count;
}
void push(Element e)
{
Node* p = (Node*)malloc(sizeof(Node));
p -> data = e;
p -> link = top;
top = p;
}
Element pop()
{
Node* p;
Element e;
if(is_empty())
error("공백 상태 에러");
p = top;
top = p -> link;
e = p -> data;
free(p);
return e;
}
Element peek()
{
if (is_empty())
error("공백 상태 에러");
return top -> data;
}
5. 괄호 검사
C언어 소스 코드에서 사용되는 대괄호 [], 중괄호 {}, 소괄호 ()는 다음 조건을 만족해야 한다.
조건 | 내용 |
---|---|
1 | 왼쪽 괄호의 개수와 오른쪽 괄호의 개수가 같아야 한다. |
2 | 같은 타입의 괄호에서 왼쪽 괄호는 오른쪽 괄호보다 먼저 나와야 한다. |
3 | 서로 다른 타입의 괄호 쌍이 서로를 교차하면 안 된다. |
괄호 검사 알고리즘
- 문자를 저장하는 스택을 준비한다. 처음에는 공색 상태가 되어야 한다.
- 입력 문자열을 하나씩 읽어 왼쪽 괄호를 맍나면 스택에 삽입한다.
- 오른쪽 괄호를 만나면 pop() 연산으로 가장 최근에 삽입된 괄호를 꺼낸다. 이때 스택이 비어 있으면 조건2에 위배된다.
- 꺼낸 괄호가 오른쪽 괄호와 짝이 맞지 않으면 조건3에 위배된다.
- 끝까지 처리했는데 스택에 괄호가 남아 있으면 조건1에 위배된다.
6. 후위 표기 수식의 계산
- 전위 표기법 : 연산자를 피연산자 앞에 표기한다.
- 중위 표기법 : 연산자를 피연산자 사이에 표기한다.
- 후위 표기법 : 연산자를 피연산자 뒤에 표기한다.
컴파일러는 중위 표기 수식을 후위 표기 수식으로 바꾸고, 변환된 후위 표기 수식을 계산한다.
- 괄호를 사용하지 않고도 계산 순서를 알 수 있다.
- 연산자의 우선순위를 고려할 필요가 없다.
- 수식을 읽으면서 바로 계산할 수 있다.
후위 표기 수식의 계산 알고리즘
- 전체 수식을 왼쪽에서 오른쪽으로 스캔한다.
- 피연산자가 나오면, 스택에 저장한다.
- 연산자가 나오면, 스택에서 피연산자 두 개를 꺼내 연산을 수행하고 그 결과를 스택에 저장한다.
- 이 과정을 반복한다.
7. 중위 표기 수식의 후위 표기 변환
계산기 프로그램을 구현하려면 사람이 입력하는 중위 표기 수식을 후위 표기식으로 변경해야 한다.
후위 표기 변환 알고리즘
- 입력된 중위 표기 수식을 순서대로 하나씩 스캔한다.
- 피연산자를 만나면, 바로 출력한다.
- 연산자를 만나면, 스택에 저장한다.